/* MOALI violet/fuchsia brand skin on top of stock Bootstrap 5.3 (CDN).
   Hand-authored - overrides Bootstrap's runtime CSS custom properties
   instead of recompiling its Sass (no build step available). */

html {
  /* Bootstrap's rem-based type/spacing scale reads large at the default
     16px root - drop it so text and paddings shrink proportionally
     everywhere, without touching every component. */
  font-size: 14px;
}

:root,
[data-bs-theme="light"] {
  --bs-primary: #7c3aed;
  --bs-primary-rgb: 124, 58, 237;
  --bs-link-color: #7c3aed;
  --bs-link-color-rgb: 124, 58, 237;
  --bs-link-hover-color: #6d28d9;
  --bs-link-hover-color-rgb: 109, 40, 217;
}

[data-bs-theme="dark"] {
  --bs-primary: #a78bfa;
  --bs-primary-rgb: 167, 139, 250;
  --bs-link-color: #a78bfa;
  --bs-link-color-rgb: 167, 139, 250;
  --bs-link-hover-color: #c4b5fd;
  --bs-link-hover-color-rgb: 196, 181, 253;
}

.btn-primary {
  --bs-btn-bg: #7c3aed;
  --bs-btn-border-color: #7c3aed;
  --bs-btn-hover-bg: #6d28d9;
  --bs-btn-hover-border-color: #6d28d9;
  --bs-btn-active-bg: #6d28d9;
  --bs-btn-active-border-color: #5b21b6;
  --bs-btn-disabled-bg: #7c3aed;
  --bs-btn-disabled-border-color: #7c3aed;
  --bs-btn-focus-shadow-rgb: 124, 58, 237;
}

.btn-outline-primary {
  --bs-btn-color: #7c3aed;
  --bs-btn-border-color: #7c3aed;
  --bs-btn-hover-bg: #7c3aed;
  --bs-btn-hover-border-color: #7c3aed;
  --bs-btn-active-bg: #6d28d9;
  --bs-btn-active-border-color: #6d28d9;
  --bs-btn-focus-shadow-rgb: 124, 58, 237;
}

[data-bs-theme="dark"] .btn-primary {
  --bs-btn-bg: #7c3aed;
  --bs-btn-border-color: #7c3aed;
  --bs-btn-hover-bg: #8b5cf6;
  --bs-btn-hover-border-color: #8b5cf6;
  --bs-btn-active-bg: #8b5cf6;
  --bs-btn-active-border-color: #8b5cf6;
}

[data-bs-theme="dark"] .btn-outline-primary {
  --bs-btn-color: #a78bfa;
  --bs-btn-border-color: #a78bfa;
  --bs-btn-hover-bg: #a78bfa;
  --bs-btn-hover-color: #1e1b2e;
  --bs-btn-hover-border-color: #a78bfa;
}

.form-control:focus,
.form-select:focus {
  border-color: #a78bfa;
  box-shadow: 0 0 0 0.25rem rgba(124, 58, 237, 0.25);
}

/* Login page - split-panel layout (form on a plain surface, a branded
   photo pane on the other side, hidden below the lg breakpoint) in place
   of the old single centered card. */
.login-shell {
  min-height: 100vh;
}

.login-panel {
  max-width: 24rem;
}

/* Icon-prefixed pill-ish inputs, matching the rest of the app's
   .picker-field-control convention but roomier for a login form. */
.login-field {
  position: relative;
}

.login-field > i:first-child {
  position: absolute;
  left: 1rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--bs-secondary-color);
  font-size: 0.95rem;
  pointer-events: none;
}

.login-field .form-control {
  padding: 0.65rem 2.75rem;
  border-radius: 0.85rem;
  border-color: var(--bs-border-color-translucent);
  background-color: var(--bs-tertiary-bg);
}

.login-field .form-control:focus {
  background-color: var(--bs-body-bg);
  border-color: #7c3aed;
  box-shadow: 0 0 0 0.2rem rgba(124, 58, 237, 0.15);
}

.login-field-toggle {
  position: absolute;
  right: 0.9rem;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 0;
  color: var(--bs-secondary-color);
  font-size: 0.95rem;
  cursor: pointer;
  line-height: 1;
}

.btn-login {
  border-radius: 0.85rem;
  padding: 0.75rem 1rem;
  font-weight: 600;
  border: none;
  background-color: #7c3aed;
  color: #fff;
  transition: background-color 0.15s ease;
}

.btn-login:hover,
.btn-login:focus {
  background-color: #6d28d9;
  color: #fff;
}

/* Right-hand hero photo - a color-tinted scrim (brand blue/purple, mixed
   multiply) plus a bottom-up dark gradient so the caption text stays
   legible over whatever the photo underneath happens to show. */
.login-hero {
  position: relative;
  flex: 1 1 45%;
  background-size: cover;
  background-position: center;
}

.login-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(180deg, rgba(16, 24, 39, 0.1) 40%, rgba(16, 24, 39, 0.8));
}

.login-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(135deg, rgba(37, 99, 235, 0.35), rgba(124, 58, 237, 0.25));
  mix-blend-mode: multiply;
}

.login-hero-caption {
  position: relative;
  z-index: 1;
}

/* Sidebar surface - soft blue wash instead of a plain white/gray panel,
   with a quiet two-layer wave decoration anchored to the bottom
   (low-opacity brand purple/fuchsia, echoing .brand-icon's gradient). The
   waves sit on an absolutely-positioned ::after behind the brand header/
   nav list, so they read as a background texture rather than competing
   with the nav items on top of them. Both shades keep roughly the same
   lightness as the panel's earlier gray tones, so the existing dark
   (light theme) / light (dark theme) nav text still reads without needing
   its own color overrides. */
/* Bootstrap has no `.min-w-0` utility (only `.min-vw-100`/`.min-vh-100`
   exist) - without an explicit `min-width: 0`, this flex child refuses to
   shrink below its content's intrinsic width (e.g. a filter row with
   several unwrapped inputs), stretching the whole app shell wider than the
   viewport and forcing a page-level horizontal scrollbar on narrow
   screens. */
.app-content-col {
  min-width: 0;
}

/* Sidebar surface - a flat panel on its own --sidebar-* tokens (not the
   page's own --bs-body-bg), so it reads as visually distinct from the
   content area (white-on-off-white in light mode, near-black in dark)
   without the decorative wash the sidebar used to carry. */
:root,
[data-bs-theme="light"] {
  --sidebar-bg: #ffffff;
  --sidebar-border: var(--bs-border-color-translucent);
  --sidebar-hover-bg: rgba(15, 23, 42, 0.045);
}

[data-bs-theme="dark"] {
  --sidebar-bg: #0b0e14;
  --sidebar-border: rgba(255, 255, 255, 0.08);
  --sidebar-hover-bg: rgba(255, 255, 255, 0.06);
}

.sidebar-aside {
  position: relative;
  width: 21rem;
  flex-shrink: 0;
  /* Rescopes the --bs-border-color the template's own .border-end utility
     reads, so that hairline follows --sidebar-border instead of the
     page's default border color. */
  --bs-border-color: var(--sidebar-border);
  background-color: var(--sidebar-bg);
  overflow: hidden;
  transition: width 0.2s ease;
}

/* Mobile nav (Bootstrap offcanvas) - same flat surface as the desktop
   .sidebar-aside, but kept as its own class so it never overrides
   .offcanvas's own `position: fixed` (needed for the slide-in behavior). */
.mobile-sidebar-aside {
  background-color: var(--sidebar-bg);
}

/* Sidebar brand header ("MOALI Report MIS") - a hairline border is the
   only separator from the scrollable nav list below; no shadow or wash,
   so the panel reads as one flat surface. */
.sidebar-brand {
  border-bottom: 1px solid var(--sidebar-border);
}

/* Uppercase muted-gray label above each nav group ("Monitoring",
   "Seed and crops", ...) - small and quiet so it reads as a caption over
   its section, not a sibling destination next to the items below it. */
.sidebar-group-label {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--bs-secondary-color);
}

/* Collapsible toggle for a group heading. Deliberately no background in
   either state, matching the panel's flat surface - only the chevron
   rotation and an accent text color mark the section as open. */
.sidebar-group-toggle {
  padding: 0.3rem 0.5rem;
  border-radius: 0.375rem;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.sidebar-group-toggle:not(.collapsed) {
  color: var(--bs-primary);
}

.sidebar-group-toggle:hover,
.sidebar-group-toggle:focus {
  background-color: var(--sidebar-hover-bg);
  color: var(--bs-primary);
}

.sidebar-nav .nav-link {
  align-items: flex-start;
  border-radius: 0.375rem;
  /* Left padding ~13px deeper than the group header's own inset
     (.sidebar-group-toggle's 0.5rem) so the parent/child relationship
     reads unambiguously even with the accordion collapsed state removed. */
  padding: 0.45rem 0.6rem 0.45rem calc(0.6rem + 13px);
  line-height: 1.4;
  font-size: 0.9rem;
  color: var(--bs-secondary-color);
  transition: background-color 0.15s ease, color 0.15s ease;
}

/* Icon column - fixed width/size so every item's label starts at the same
   x-position regardless of which glyph it uses. */
.sidebar-nav-icon {
  width: 1.15rem;
  flex-shrink: 0;
  margin-top: 0.05rem;
  font-size: 17px;
  text-align: center;
  color: var(--bs-secondary-color);
  transition: color 0.15s ease;
}

.sidebar-nav .nav-link:not(.active):hover,
.sidebar-nav .nav-link:not(.active):focus {
  background-color: var(--sidebar-hover-bg);
  color: var(--bs-emphasis-color);
}

.sidebar-nav .nav-link:not(.active):hover .sidebar-nav-icon,
.sidebar-nav .nav-link:not(.active):focus .sidebar-nav-icon {
  color: var(--bs-primary);
}

/* Active item - a flat rounded tint fill mixed against transparent (not
   --bs-body-bg, which no longer matches the sidebar's own flat surface),
   so it reads the same way regardless of theme. */
.sidebar-nav .nav-link.active {
  background-color: color-mix(in srgb, var(--bs-primary) 14%, transparent);
  color: var(--bs-primary);
  font-weight: 500;
}

.sidebar-nav .nav-link.active .sidebar-nav-icon {
  color: var(--bs-primary);
}

/* Chevron on a collapsible group heading - flips to point up while its
   item list is expanded. Bootstrap's collapse JS toggles the "collapsed"
   class on the trigger itself, so the rotation just follows it. */
.sidebar-nav-chevron {
  transition: transform 0.15s ease;
}

.sidebar-group-toggle:not(.collapsed) .sidebar-nav-chevron {
  transform: rotate(180deg);
}

/* Collapsed sidebar rail - icon-only, toggled by the header's sidebar
   button (base.html toggleSidebar()). State lives in localStorage and is
   applied to <html> before first paint (same technique as the dark-mode
   toggle), so there's no flash of the expanded layout on load. Scoped to
   `.sidebar-aside` (not `.sidebar-brand`/`.sidebar-nav` alone) so the
   mobile offcanvas menu, which shares those classes, is never affected. */
html.sidebar-collapsed .sidebar-aside {
  width: 3.75rem;
}

html.sidebar-collapsed .sidebar-aside .sidebar-brand {
  justify-content: center;
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}

html.sidebar-collapsed .sidebar-aside .sidebar-brand > span:not(.brand-icon) {
  display: none;
}

html.sidebar-collapsed .sidebar-aside > nav {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}

/* A group heading has no room to stay a clickable label in rail mode, so
   it collapses to a plain hairline divider between sections instead. */
html.sidebar-collapsed .sidebar-aside .sidebar-group-label {
  height: 1px;
  min-height: 0;
  margin: 0.75rem 0.25rem;
  padding: 0;
  overflow: hidden;
  background-color: var(--sidebar-border);
  pointer-events: none;
}

html.sidebar-collapsed .sidebar-aside .sidebar-group-label > span:first-child,
html.sidebar-collapsed .sidebar-aside .sidebar-nav-chevron {
  display: none;
}

/* Force every group's items visible regardless of accordion state - a
   collapsed group heading is no longer clickable, so its icons must stay
   reachable without expanding anything. */
html.sidebar-collapsed .sidebar-aside .collapse {
  display: block !important;
}

html.sidebar-collapsed .sidebar-aside .sidebar-nav .nav-link {
  justify-content: center;
  padding: 0.55rem;
}

html.sidebar-collapsed .sidebar-aside .sidebar-nav .nav-link span {
  display: none;
}

html.sidebar-collapsed .sidebar-aside .sidebar-nav-icon {
  margin-top: 0;
}

.dropdown-item:hover,
.dropdown-item:focus {
  background-color: var(--bs-tertiary-bg);
}

.dropdown-item.active,
.dropdown-item:active {
  background-color: #7c3aed;
}

.avatar-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background-image: linear-gradient(135deg, #7c3aed, #d946ef);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 600;
  flex-shrink: 0;
}

.brand-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 0.5rem;
  background-image: linear-gradient(135deg, #7c3aed, #d946ef);
  color: #fff;
  flex-shrink: 0;
}

/* Smaller echo of .brand-icon, used to sign the footer with the same mark
   as the sidebar logo instead of leaving it as plain text. */
.footer-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 0.45rem;
  background-image: linear-gradient(135deg, #7c3aed, #d946ef);
  color: #fff;
  font-size: 0.7rem;
  flex-shrink: 0;
}

.icon-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  margin-bottom: 0.5rem;
}

/* Bigger, gradient-filled echo of .icon-badge for a dashboard's headline
   stat cards, where the icon is the focal point rather than an inline
   accent - same 135deg gradient language as .brand-icon/.avatar-circle,
   just re-colored per card via the .icon-badge-* variants below. */
.icon-badge-lg {
  width: 2.75rem;
  height: 2.75rem;
  font-size: 1.1rem;
  color: #fff;
}

.icon-badge-primary { background-image: linear-gradient(135deg, #7c3aed, #a78bfa); }
.icon-badge-success { background-image: linear-gradient(135deg, #0ca30c, #34d399); }
.icon-badge-info { background-image: linear-gradient(135deg, #0ea5e9, #67e8f9); }
.icon-badge-warning { background-image: linear-gradient(135deg, #f59e0b, #fbbf24); }

/* Headline stat card - a soft color-tinted wash (adapts to light/dark via
   color-mix against the theme's own body background) plus a gradient top
   edge, so each card reads with its own identity at a glance instead of
   four identical white boxes distinguished only by a small icon. */
.stat-card {
  position: relative;
  overflow: hidden;
  border: none;
}

.stat-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
}

.stat-card-primary { background-color: color-mix(in srgb, #7c3aed 7%, var(--bs-body-bg)); }
.stat-card-primary::before { background-image: linear-gradient(90deg, #7c3aed, #a78bfa); }

.stat-card-success { background-color: color-mix(in srgb, #0ca30c 7%, var(--bs-body-bg)); }
.stat-card-success::before { background-image: linear-gradient(90deg, #0ca30c, #34d399); }

.stat-card-info { background-color: color-mix(in srgb, #0ea5e9 7%, var(--bs-body-bg)); }
.stat-card-info::before { background-image: linear-gradient(90deg, #0ea5e9, #67e8f9); }

.stat-card-warning { background-color: color-mix(in srgb, #f59e0b 7%, var(--bs-body-bg)); }
.stat-card-warning::before { background-image: linear-gradient(90deg, #f59e0b, #fbbf24); }

/* Cards/tables read as plain, sharp-cornered boxes with stock Bootstrap -
   round the corners, add a soft shadow, and clip the table so its header
   doesn't poke square corners out past the card's rounded border. */
.card {
  border-radius: 0.9rem;
  border-color: var(--bs-border-color-translucent);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
  overflow: hidden;
}

.table {
  margin-bottom: 0;
}

.table > thead > tr > th {
  border-bottom-width: 1px;
  padding-top: 0.85rem;
  padding-bottom: 0.85rem;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--bs-secondary-color);
}

.table > :not(caption) > * > * {
  padding-left: 1rem;
  padding-right: 1rem;
  vertical-align: middle;
}

/* Faint zebra striping + a clearer hover state so dense rows of near-
   identical cells (student/record lists) stay easy to track by eye. */
.table > tbody > tr:nth-of-type(odd) > * {
  background-color: color-mix(in srgb, var(--bs-emphasis-color) 2.5%, var(--bs-body-bg));
}

.table-hover > tbody > tr:hover > * {
  background-color: color-mix(in srgb, #7c3aed 6%, var(--bs-body-bg));
}

.alert {
  border-radius: 0.75rem;
}

/* Compact number/count pill used for row ordinals and tallies. */
.number-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.6rem;
  height: 1.6rem;
  padding: 0 0.35rem;
  border-radius: 0.5rem;
  background-color: var(--bs-tertiary-bg);
  color: var(--bs-emphasis-color);
  font-size: 0.72rem;
  font-weight: 600;
}

/* Bigger echo of .number-badge for contexts where the number is the row's
   primary scanning anchor (e.g. a roll number column). */
.number-badge-lg {
  min-width: 2.1rem;
  height: 2.1rem;
  padding: 0 0.5rem;
  border-radius: 0.6rem;
  font-size: 0.95rem;
}

/* Soft pill for short metadata like a unit of measure. */
.unit-badge {
  display: inline-block;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  background-color: var(--bs-tertiary-bg);
  color: var(--bs-secondary-color);
  font-size: 0.72rem;
}

/* Square icon-only action button, sized to match .btn-sm's line-height. */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
}

/* Indented child row (a seasonal/variety breakdown of a parent crop). */
.row-child td:first-child {
  position: relative;
}

.row-child .row-child-name {
  padding-left: 1.5rem;
  position: relative;
}

.row-child .row-child-name::before {
  content: "";
  position: absolute;
  left: 0.4rem;
  top: 0;
  bottom: 50%;
  width: 0.6rem;
  border-left: 1px solid var(--bs-border-color);
  border-bottom: 1px solid var(--bs-border-color);
  border-bottom-left-radius: 0.4rem;
}

.table-empty-state {
  padding: 3rem 1.5rem;
  text-align: center;
  color: var(--bs-secondary-color);
}

/* Pill "back" link - soft brand tint that fills solid on hover, with the
   arrow nudging left to reinforce the direction of travel. */
.btn-back {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  background-color: var(--bs-primary-bg-subtle);
  color: var(--bs-primary-text-emphasis);
  font-size: 0.8rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}

.btn-back i {
  transition: transform 0.15s ease;
}

.btn-back:hover,
.btn-back:focus-visible {
  background-color: var(--bs-primary);
  color: #fff;
  text-decoration: none;
  box-shadow: 0 2px 8px rgba(124, 58, 237, 0.35);
}

.btn-back:hover i {
  transform: translateX(-3px);
}

/* Icon-prefixed select fields used on the planting-progress picker bar. */
.picker-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.picker-field-label {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--bs-secondary-color);
}

.picker-field-control {
  position: relative;
}

.picker-field-control > i {
  position: absolute;
  left: 0.85rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--bs-primary);
  font-size: 0.85rem;
  pointer-events: none;
}

.picker-field-control select.form-select,
.picker-field-control input.form-control {
  min-width: 11rem;
  padding-left: 2.25rem;
  border-radius: 0.65rem;
  border-color: var(--bs-border-color-translucent);
  background-color: var(--bs-tertiary-bg);
  font-weight: 500;
  transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;
}

.picker-field-control select.form-select:hover,
.picker-field-control input.form-control:hover {
  border-color: var(--bs-primary);
}

.picker-field-control select.form-select:focus,
.picker-field-control input.form-control:focus {
  background-color: var(--bs-body-bg);
}

/* Polished data-entry form (see reports/registration_add.html) - a bigger,
   airier card with grouped/titled sections, in place of the app's usual
   compact inline pickers. Scoped under .entry-form-card so the roomier
   inputs don't bleed into every other form on the site. */
.entry-form-card {
  border-radius: 1.1rem;
}

.entry-form-card .card-body {
  padding: 2rem;
}

.entry-form-section-title {
  font-size: 0.95rem;
  font-weight: 700;
  padding-bottom: 0.85rem;
  margin-bottom: 1.25rem;
  border-bottom: 1px solid var(--bs-border-color-translucent);
}

.entry-form-card .form-label {
  font-weight: 600;
  font-size: 0.8rem;
}

.entry-form-card .form-control,
.entry-form-card .form-select {
  border-radius: 0.65rem;
  padding: 0.6rem 0.9rem;
}

.entry-form-card .form-control:focus,
.entry-form-card .form-select:focus {
  box-shadow: 0 0 0 0.2rem rgba(124, 58, 237, 0.15);
}

.entry-form-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.75rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--bs-border-color-translucent);
}

/* Centred single-column variant of the entry form (see
   reports/sesame_trial_add.html) - the card is capped and centred in the
   main column so a short form doesn't stretch edge to edge on a wide
   screen, with quieter labels and softer inputs. Opt-in via
   .entry-form-centered so the existing .entry-form-card pages are
   untouched. */
.entry-form-centered-head {
  max-width: 56rem;
  margin-inline: auto;
}

.entry-form-centered {
  max-width: 56rem;
  margin-inline: auto;
  border: 1px solid var(--bs-border-color-translucent);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04), 0 8px 24px -12px rgba(15, 23, 42, 0.12);
}

.entry-form-centered .card-body {
  padding: 2rem 2.25rem;
}

@media (max-width: 575.98px) {
  .entry-form-centered .card-body {
    padding: 1.35rem 1.15rem;
  }
}

.entry-form-centered .entry-form-section-title {
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--bs-secondary-color);
  padding-bottom: 0.6rem;
  margin-bottom: 1.1rem;
}

.entry-form-centered .form-label {
  font-weight: 500;
  font-size: 0.925rem;
  color: var(--bs-secondary-color);
  margin-bottom: 0.35rem;
}

.entry-form-centered .form-control,
.entry-form-centered .form-select {
  border-radius: 0.7rem;
  padding: 0.7rem 0.95rem;
  font-size: 1rem;
  border-color: var(--bs-border-color);
  background-color: var(--bs-body-bg);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.entry-form-centered .form-control:hover,
.entry-form-centered .form-select:hover {
  border-color: var(--bs-secondary-border-subtle);
}

.entry-form-centered textarea.form-control {
  min-height: 5.25rem;
  resize: vertical;
}

/* Sit the footer flush with the card edge, like a dialog's action bar. */
.entry-form-centered .entry-form-actions {
  margin: 1.75rem -2.25rem -0.5rem;
  padding: 1.25rem 2.25rem 0;
}

@media (max-width: 575.98px) {
  .entry-form-centered .entry-form-actions {
    margin-inline: -1.15rem;
    padding-inline: 1.15rem;
  }
}

.entry-form-centered .entry-form-actions .btn {
  border-radius: 0.7rem;
  padding: 0.5rem 1.15rem;
  font-size: 0.925rem;
  font-weight: 500;
}

/* The #generic-add-modal / #generic-edit-modal dialog (schools dashboard -
   student, teacher, textbook, budget, furniture, equipment "add" forms all
   share this one modal + .generic-form). Quiet, shadcn-style dialog chrome:
   muted labels, soft-bordered inputs with a restrained focus ring instead
   of Bootstrap's default glow, calmer spacing. */
#generic-add-modal .modal-content,
#generic-edit-modal .modal-content {
  border-radius: 1rem;
  border-color: var(--bs-border-color-translucent);
  box-shadow: 0 20px 45px -20px rgba(15, 23, 42, 0.25);
}

#generic-add-modal .modal-header,
#generic-edit-modal .modal-header {
  border-bottom-color: var(--bs-border-color-translucent);
}

.generic-form .form-label {
  font-weight: 500;
  font-size: 0.825rem;
  color: var(--bs-secondary-color);
  margin-bottom: 0.35rem;
}

.generic-form .form-control,
.generic-form .form-select {
  border-radius: 0.6rem;
  padding: 0.55rem 0.85rem;
  font-size: 0.9rem;
  border-color: var(--bs-border-color);
  box-shadow: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.generic-form .form-control:hover,
.generic-form .form-select:hover {
  border-color: var(--bs-secondary-border-subtle);
}

.generic-form .form-control:focus,
.generic-form .form-select:focus {
  border-color: #a78bfa;
  box-shadow: 0 0 0 0.2rem rgba(124, 58, 237, 0.15);
}

.generic-form textarea.form-control {
  min-height: 5rem;
  resize: vertical;
}

.generic-form .form-check.form-switch {
  padding-top: 0.2rem;
}

.generic-form .d-flex.justify-content-end .btn {
  border-radius: 0.6rem;
  padding: 0.5rem 1.1rem;
  font-size: 0.9rem;
  font-weight: 500;
}

/* Account create/edit forms - role picker rendered as selectable "cards"
   (Bootstrap's stock .btn-check + label toggle pattern, just re-skinned)
   instead of a plain <select>, plus a sticky live preview panel echoing
   the header's own .avatar-circle gradient so an admin can see at a
   glance what account they're about to create/save. */
.role-card-group {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 0.75rem;
}

.role-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.35rem;
  height: 100%;
  padding: 0.9rem 1rem;
  border: 1.5px solid var(--bs-border-color-translucent);
  border-radius: 0.75rem;
  background-color: var(--bs-tertiary-bg);
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;
}

.role-card i {
  font-size: 1.15rem;
  color: var(--bs-primary);
}

.role-card-title {
  font-weight: 600;
  font-size: 0.85rem;
}

.role-card-desc {
  font-size: 0.72rem;
  color: var(--bs-secondary-color);
}

.role-card:hover {
  border-color: var(--bs-primary);
}

.btn-check:checked + .role-card,
.btn-check:focus-visible + .role-card {
  border-color: var(--bs-primary);
  background-color: var(--bs-primary-bg-subtle);
  box-shadow: 0 0 0 0.2rem rgba(124, 58, 237, 0.15);
}

/* Sticky only applies once the form/preview split into the two-column
   .col-lg-8/.col-lg-4 layout (user_add.html/user_edit.html) - below that
   breakpoint the columns stack into one, so a sticky card there would
   detach from its natural place at the end of the page and pin itself
   to the top of the screen as soon as the (much taller) form above it
   scrolls by.

   The submit button sits right after the preview card, so both are
   wrapped in this one sticky element (rather than making the card alone
   sticky) - otherwise the card stays pinned on scroll while the button,
   a plain sibling, keeps scrolling normally and slides up to touch/
   overlap the card's bottom edge. */
@media (min-width: 992px) {
  .account-preview-sticky {
    position: sticky;
    top: 1.25rem;
  }
}

.account-preview-avatar {
  width: 4rem;
  height: 4rem;
  font-size: 1.5rem;
}

/* Inbox (messaging app) - a self-contained two-pane "app shell" rather than
   a long scrolling page, echoing a real mail client: fixed height, its own
   internal scroll regions, list rows and message-sender avatars styled off
   the same violet/fuchsia .avatar-circle gradient already used for the
   header's own-account avatar, so the feature reads as native to the app
   rather than a bolted-on generic list+detail view. */
.inbox-shell {
  height: calc(100vh - 13.5rem);
  min-height: 28rem;
  border-radius: 1.25rem;
  overflow: hidden;
  box-shadow: 0 20px 45px -28px rgba(15, 23, 42, 0.28);
  border: 1px solid var(--bs-border-color-translucent);
}

.inbox-pane {
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  background-color: var(--bs-body-bg);
}

.inbox-pane + .inbox-pane {
  border-left: 1px solid var(--bs-border-color-translucent);
}

/* Thread list pane - full width below md (only one of list/detail pane is
   shown at a time there, toggled server-side via `thread`/`compose`), fixed
   width alongside the detail pane from md up. */
.inbox-pane-list {
  width: 100%;
  flex-shrink: 0;
}

@media (min-width: 768px) {
  .inbox-pane-list {
    width: 23rem;
  }
}

.inbox-search {
  position: sticky;
  top: 0;
  z-index: 2;
  background-color: var(--bs-body-bg);
  border-bottom: 1px solid var(--bs-border-color-translucent);
  padding: 1.1rem 1.1rem 0.9rem;
}

.inbox-search .form-control,
.inbox-search .form-select {
  border-radius: 0.65rem;
  background-color: var(--bs-tertiary-bg);
  border-color: transparent;
}

.inbox-search .form-control:focus,
.inbox-search .form-select:focus {
  background-color: var(--bs-body-bg);
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 0.2rem rgba(124, 58, 237, 0.15);
}

/* The main "search people, word or anything" field - a fuller pill shape
   (999px, taller) so it reads as the pane's primary control, distinct
   from the compact date/region filter inputs below it. */
.inbox-search-input.form-control {
  height: 2.6rem;
  border-radius: 999px;
  font-size: 0.85rem;
}

/* Compose - a filled circular icon button beside the pill search field,
   echoing the header's own circular .avatar-circle language instead of
   a plain rectangular button. */
.inbox-compose-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  border-radius: 50%;
  font-size: 1rem;
}

.inbox-thread {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  margin: 0.4rem 0.6rem;
  padding: 0.9rem 0.75rem;
  border-radius: 0.9rem;
  text-decoration: none;
  color: inherit;
  border-bottom: none;
  transition: background-color 0.15s ease;
}

.inbox-thread:hover {
  background-color: var(--bs-tertiary-bg);
  color: inherit;
}

.inbox-thread.active {
  background-color: var(--bs-primary-bg-subtle);
  box-shadow: none;
}

/* Reserves its column whether or not a given row is unread, so avatars
   stay aligned between read and unread rows instead of shifting. */
.inbox-thread-unread-dot {
  align-self: center;
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 50%;
  background-color: var(--bs-primary);
  flex-shrink: 0;
  visibility: hidden;
}

.inbox-thread.unread .inbox-thread-unread-dot {
  visibility: visible;
}

.inbox-thread-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  color: #fff;
  font-size: 0.9rem;
  font-weight: 600;
  flex-shrink: 0;
}

/* Fixed, role-based avatar colors - a small "legend" so who's on the other
   end of a thread is recognizable at a glance instead of every sender
   rendering in the same color. Applied to both the sidebar's thread
   avatar (colored by whichever side created the thread) and each message
   bubble's own sender avatar - .inbox-thread-avatar/.inbox-message-avatar
   never set their own background-color, so which of these role classes
   wins is never a source-order/specificity accident. */
.inbox-avatar-hq {
  background-color: #f59e0b;
}

.inbox-avatar-region {
  background-color: #7c3aed;
}

.inbox-avatar-district {
  background-color: #0ea5e9;
}

.inbox-avatar-township {
  background-color: #10b981;
}

.inbox-thread-body {
  min-width: 0;
  flex-grow: 1;
}

.inbox-thread-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}

.inbox-thread-subject {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.9rem;
  font-weight: 500;
}

.inbox-thread.unread .inbox-thread-subject {
  font-weight: 700;
}

.inbox-thread-time {
  flex-shrink: 0;
  font-size: 0.72rem;
  color: var(--bs-tertiary-color);
}

.inbox-thread-meta {
  display: block;
  font-size: 0.72rem;
  color: var(--bs-secondary-color);
  margin-bottom: 0.1rem;
}

.inbox-thread-preview {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.8rem;
  color: var(--bs-secondary-color);
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

/* Round icon-only button that reveals the date/region filter fields
   (.inbox-filter-group, collapsed by default) beside the search field,
   so the search bar itself stays uncluttered until a filter is needed. */
.inbox-filter-toggle-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  border-radius: 50%;
  flex-shrink: 0;
}

.inbox-detail-header {
  padding: 0.9rem 1.75rem;
  border-bottom: 1px solid var(--bs-border-color-translucent);
}

.inbox-detail-header h2 {
  font-size: 1.05rem;
}

/* Thread subject, shown once as a heading at the top of the scrollable
   message list rather than pinned in a persistent header bar - reads
   like an email's subject line rather than a page title. */
.inbox-subject-block {
  padding: 1.5rem 1.75rem 0.5rem;
}

.inbox-subject-heading {
  font-size: 1.35rem;
  font-weight: 700;
}

.inbox-message {
  display: flex;
  gap: 0.9rem;
  padding: 1.5rem 1.75rem;
  /* Softer than a plain border-color, and dropped entirely on the last
     message in a thread so the list doesn't end on a trailing divider
     right above the reply bar. */
  border-bottom: 1px solid color-mix(in srgb, var(--bs-border-color) 40%, transparent);
}

.inbox-message:last-child {
  border-bottom: none;
}

.inbox-message-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  color: #fff;
  font-size: 0.8rem;
  font-weight: 600;
  flex-shrink: 0;
}

.inbox-message-body {
  min-width: 0;
  max-width: 100%;
  flex-grow: 1;
  word-wrap: break-word;
  overflow-wrap: anywhere;
}

/* Sender name + role badge, and the timestamp/delete controls - an
   explicit flex row on each side rather than relying on inline whitespace
   collapsing, so it can't be knocked out of line by white-space rules
   (like .inbox-message-text's pre-wrap below) inherited from an ancestor. */
.inbox-message-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}

/* Only the actual message body text preserves literal whitespace/line
   breaks and force-breaks long unbroken tokens - scoped here rather than
   on .inbox-message-body itself, which previously let white-space:
   pre-wrap leak into the header and preserve the raw whitespace/newlines
   Django's template engine leaves between tags, breaking its layout. */
.inbox-message-text {
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

/* Attachments as small file-card tiles (icon over filename/size) rather
   than inline text chips - closer to how a mail client previews a
   document, and lets several attachments read as a tidy grid. */
.inbox-attachment-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 0.5rem;
}

.inbox-attachment-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  width: 6.5rem;
  padding: 0.75rem 0.5rem;
  border: 1px solid var(--bs-border-color-translucent);
  border-radius: 0.85rem;
  background-color: var(--bs-tertiary-bg);
  color: var(--bs-emphasis-color);
  text-align: center;
  text-decoration: none;
  transition: border-color 0.15s ease, background-color 0.15s ease, transform 0.15s ease;
}

.inbox-attachment-card:hover {
  border-color: var(--bs-primary);
  background-color: var(--bs-primary-bg-subtle);
  color: var(--bs-primary-text-emphasis);
  transform: translateY(-2px);
}

.inbox-attachment-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.3rem;
  height: 2.3rem;
  border-radius: 0.6rem;
  background-color: var(--bs-body-bg);
  color: var(--bs-primary);
  font-size: 1.05rem;
}

.inbox-attachment-name {
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.72rem;
  font-weight: 500;
}

.inbox-attachment-size {
  font-size: 0.65rem;
  color: var(--bs-secondary-color);
}

.inbox-reply-bar {
  padding: 1rem 1.75rem;
  background-color: var(--bs-tertiary-bg);
  border-top: 1px solid var(--bs-border-color-translucent);
}

.inbox-reply-bar textarea.form-control {
  border-radius: 1.15rem;
  background-color: var(--bs-body-bg);
  border-color: var(--bs-border-color-translucent);
  padding: 0.6rem 1rem;
  resize: none;
}

.inbox-reply-bar textarea.form-control:focus {
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 0.2rem rgba(124, 58, 237, 0.15);
}

.inbox-reply-bar button[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  border-radius: 50%;
  align-self: flex-end;
}

.inbox-reply-bar button[type="submit"] i {
  margin: 0;
}

.inbox-empty-state {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--bs-secondary-color);
  text-align: center;
  padding: 2rem;
}

.inbox-empty-state i {
  font-size: 2.75rem;
  color: var(--bs-primary);
  opacity: 0.35;
  margin-bottom: 0.75rem;
}

/* Compose's file picker - a dashed dropzone-styled label wrapping a hidden
   file input, rather than a bare <input type="file">, so it reads as a
   deliberate part of the compose form instead of a leftover browser
   default. Selected filenames are listed as chips below it by inbox.html's
   inline script. */
.inbox-attach-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  padding: 1.25rem;
  border-radius: 0.75rem;
  border: 1.5px dashed var(--bs-border-color);
  background-color: var(--bs-tertiary-bg);
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.inbox-attach-drop:hover {
  border-color: var(--bs-primary);
  background-color: var(--bs-primary-bg-subtle);
}

.inbox-attach-drop i {
  font-size: 1.5rem;
  color: var(--bs-primary);
}

.inbox-attach-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  background-color: var(--bs-tertiary-bg);
  color: var(--bs-emphasis-color);
  font-size: 0.75rem;
}

.inbox-attach-chip .btn-close {
  font-size: 0.55rem;
}

/* Compose's region/subject/body fields - one consistent boxed style
   (border + radius + padding), matching the attach dropzone's visual
   language, with each field's label stacked above it full-width rather
   than inline settings-row labels. */
.inbox-plain-input {
  width: 100%;
  border: 1px solid var(--bs-border-color-translucent);
  border-radius: 0.65rem;
  background-color: var(--bs-body-bg);
  padding: 0.5rem 0.75rem;
  color: var(--bs-body-color);
}

.inbox-plain-input:focus {
  outline: none;
  border-color: var(--bs-primary);
  background-color: var(--bs-body-bg);
  box-shadow: 0 0 0 0.2rem rgba(124, 58, 237, 0.15);
}

/* Rice Export Zone HQ report - completion donut (CSS conic-gradient, no
   charting library) showing how many regions have submitted data out of
   the total. --pct is 0-100, set inline per instance. */
.donut-chart-wrap {
  position: relative;
  width: 9.5rem;
  height: 9.5rem;
  margin: 0 auto;
}

.donut-chart {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: conic-gradient(var(--bs-primary) calc(var(--pct) * 1%), var(--bs-tertiary-bg) 0);
}

.donut-chart-center {
  position: absolute;
  inset: 1.1rem;
  border-radius: 50%;
  background-color: var(--bs-body-bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

/* Rice Export Zone HQ report - ranked horizontal bars (entry count per
   region), single brand hue since it's one measure ranked by length, not
   a categorical breakdown. */
.region-bar-list {
  max-height: 16rem;
  overflow-y: auto;
}

.region-bar-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}

.region-bar-row:last-child {
  margin-bottom: 0;
}

.region-bar-label {
  width: 8rem;
  flex-shrink: 0;
  font-size: 0.78rem;
  color: var(--bs-secondary-color);
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.region-bar-track {
  flex-grow: 1;
  height: 0.6rem;
  border-radius: 999px;
  background-color: var(--bs-tertiary-bg);
  overflow: hidden;
}

.region-bar-fill {
  height: 100%;
  border-radius: 999px;
  background-color: var(--bs-primary);
}

.region-bar-value {
  width: 2.2rem;
  flex-shrink: 0;
  font-size: 0.78rem;
  font-weight: 600;
  text-align: left;
}

/* Sidebar's date-range + region filter fields, grouped into one visually
   contained panel instead of floating individually against the search
   bar above them. */
.inbox-filter-group {
  background-color: var(--bs-tertiary-bg);
  border-radius: 0.75rem;
  padding: 0.75rem;
}

/* Smooth cross-fade for the #main-content swap when switching dashboard
   tabs (hx-boost + hx-swap="...transition:true" triggers the browser's
   native View Transitions API). Browsers without support (Firefox, older
   Safari) just skip straight to the new content - no error, no fallback
   needed. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.15s;
}

/* School dashboard's top-level section tabs (Students / Teachers /
   Textbooks / ...). Same underline-tab language as .inbox-tabs, just
   roomier since this is the page's primary navigation, not a filter. */
.dashboard-tabs {
  border-bottom-color: var(--bs-border-color-translucent);
  gap: 0.15rem;
}

.dashboard-tabs .nav-link {
  padding: 0.65rem 1.1rem;
  color: var(--bs-secondary-color);
  font-size: 0.875rem;
  font-weight: 500;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0.6rem 0.6rem 0 0;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.dashboard-tabs .nav-link:hover {
  color: var(--bs-emphasis-color);
  background-color: var(--bs-tertiary-bg);
}

.dashboard-tabs .nav-link.active {
  color: #7c3aed;
  font-weight: 600;
  background: transparent;
  border-bottom-color: #7c3aed;
}

[data-bs-theme="dark"] .dashboard-tabs .nav-link.active {
  color: #a78bfa;
  border-bottom-color: #a78bfa;
}

.dashboard-tabs .nav-link.active:hover {
  background-color: transparent;
}

/* All / Sent / Received tabs above the thread list. */
.inbox-tabs {
  font-size: 0.8rem;
  border-bottom-color: var(--bs-border-color-translucent);
}

.inbox-tabs .nav-link {
  padding: 0.4rem 0.75rem;
  color: var(--bs-secondary-color);
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0.5rem 0.5rem 0 0;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.inbox-tabs .nav-link:hover {
  color: var(--bs-emphasis-color);
  background-color: var(--bs-tertiary-bg);
}

.inbox-tabs .nav-link.active {
  color: var(--bs-primary);
  font-weight: 600;
  background: transparent;
  border-bottom-color: var(--bs-primary);
}

.inbox-tabs .nav-link.active:hover {
  background-color: transparent;
}

/* School dashboard (Students/Teachers/.../Results tabs) - deliberately
   monochrome, unlike the rest of the app's violet/fuchsia + per-status
   color language, but built on a soft charcoal/slate ink rather than
   literal #000/#fff (var(--bs-emphasis-color) is pure black in light
   mode) - flat black icons/buttons/underlines read heavy on a light
   page, so a slate tone plus light tile backgrounds and a hover lift
   carry the "premium flat dashboard" feel instead. Scoped to
   .school-dashboard (wraps schools/dashboard/_base.html's content
   block) so it doesn't touch the site's shared violet theme. */
.school-dashboard {
  --sd-ink: #1e293b;
  --sd-ink-soft: #475569;
  --sd-tile-bg: #eef1f5;
}

[data-bs-theme="dark"] .school-dashboard {
  --sd-ink: #e2e8f0;
  --sd-ink-soft: #94a3b8;
  --sd-tile-bg: #1c2534;
}

.school-dashboard .stat-card {
  background-color: var(--bs-body-bg);
  border: 1px solid var(--bs-border-color-translucent);
  border-radius: 1rem;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.school-dashboard .stat-card::before {
  display: none;
}

.school-dashboard .stat-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 28px -18px rgba(15, 23, 42, 0.25);
}

.school-dashboard .stat-card .card-body {
  padding: 1.25rem 1.35rem;
}

.school-dashboard .stat-card p.small {
  text-transform: uppercase;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

.school-dashboard .stat-card .h4 {
  color: var(--sd-ink);
  font-weight: 700;
  font-size: 1.6rem;
}

.school-dashboard .icon-badge {
  background-image: none;
  background-color: var(--sd-tile-bg);
  color: var(--sd-ink);
  border-radius: 0.85rem;
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--sd-tile-bg) 55%, transparent);
  transform: rotate(-6deg);
  transition: transform 0.2s ease;
}

.school-dashboard .stat-card:hover .icon-badge {
  transform: rotate(0deg) scale(1.06);
}

/* Oversized, low-opacity echo of the card's own icon, bleeding off the
   bottom-right corner - a quiet decorative motif (no extra color, just
   the existing ink tone at ~6% opacity) so the three stat cards read as
   more than identical text blocks without reaching for color. */
.school-dashboard .stat-card-bg-icon {
  position: absolute;
  right: -0.5rem;
  bottom: -1.5rem;
  font-size: 6rem;
  line-height: 1;
  color: var(--sd-ink);
  opacity: 0.07;
  transform: rotate(-10deg);
  pointer-events: none;
}

[data-bs-theme="dark"] .school-dashboard .stat-card-bg-icon {
  opacity: 0.1;
}

.school-dashboard .dashboard-tabs .nav-link.active,
[data-bs-theme="dark"] .school-dashboard .dashboard-tabs .nav-link.active {
  color: var(--sd-ink);
  border-bottom-color: var(--sd-ink);
}

.school-dashboard .btn-primary {
  --bs-btn-bg: var(--sd-ink);
  --bs-btn-border-color: var(--sd-ink);
  --bs-btn-color: var(--bs-body-bg);
  --bs-btn-hover-bg: var(--sd-ink-soft);
  --bs-btn-hover-border-color: var(--sd-ink-soft);
  --bs-btn-hover-color: var(--bs-body-bg);
  --bs-btn-active-bg: var(--sd-ink-soft);
  --bs-btn-active-border-color: var(--sd-ink-soft);
  --bs-btn-active-color: var(--bs-body-bg);
  --bs-btn-focus-shadow-rgb: 71, 85, 105;
  border-radius: 0.65rem;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
}

.school-dashboard .year-picker {
  background-color: var(--sd-tile-bg);
  border-color: var(--bs-border-color-translucent) !important;
  color: var(--sd-ink);
  border-radius: 0.85rem;
}

.school-dashboard .year-picker i,
.school-dashboard .year-picker label {
  color: var(--sd-ink);
}

.school-dashboard table thead.table-light {
  --bs-table-bg: var(--bs-tertiary-bg);
}

/* Table-footer pagination (student/teacher/etc list pages) - same
   pill/slate language as the rest of .school-dashboard rather than
   Bootstrap's boxy blue default. */
.school-dashboard .card-footer {
  border-top: 1px solid var(--bs-border-color-translucent);
  padding: 0.85rem 1.35rem;
}

.school-dashboard .pagination .page-item {
  margin: 0 0.15rem;
}

.school-dashboard .pagination .page-link {
  min-width: 2.1rem;
  text-align: center;
  border: none;
  background-color: transparent;
  color: var(--sd-ink-soft);
  font-weight: 600;
  font-size: 0.8rem;
  border-radius: 0.6rem;
  padding: 0.4rem 0.65rem;
  transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

.school-dashboard .pagination .page-link:hover {
  background-color: var(--sd-tile-bg);
  color: var(--sd-ink);
  transform: translateY(-1px);
}

.school-dashboard .pagination .page-item.active .page-link {
  background-color: var(--sd-ink);
  color: var(--bs-body-bg);
  box-shadow: 0 4px 10px -4px rgba(15, 23, 42, 0.35);
}

.school-dashboard .pagination .page-item.disabled .page-link {
  color: var(--sd-ink-soft);
  opacity: 0.35;
  background-color: transparent;
}

/* Cotton Farmer Record add page - compact inline-editable row table. */
.cotton-farmer-table th {
  font-size: 0.75rem;
  white-space: nowrap;
}

.cotton-farmer-table .form-control {
  min-width: 6rem;
  padding: 0.35rem 0.5rem;
  font-size: 0.85rem;
}
