/* ==========================================================================
   HSRO design system
   --------------------------------------------------------------------------
   Replaces css/global.css (217 lines of appearance-named classes like .redCap,
   .blueBody) and the 5,360 inline style= attributes scattered across the app.

   No build step. No framework. Plain CSS with custom properties.

   Structure:
     1. Tokens
     2. Reset + base
     3. App shell (topbar / sidebar / main)
     4. Components
     5. Utilities
     6. Print
   ========================================================================== */

/* ==========================================================================
   1. Tokens
   ========================================================================== */

:root {
  /* Brand — "Warm & Friendly" terracotta. Replaces the earlier cool blue; anchored
     on #C0603F (the accent from the design concept), warmed at both ends so links,
     badges, and hovers all read on cream surfaces. */
  --brand-50:  #fbf1ea;
  --brand-100: #f6e0d3;
  --brand-200: #ecc3aa;
  --brand-300: #dd9d78;
  --brand-400: #cf7d54;
  --brand-500: #c0603f;
  --brand-600: #a84f31;
  --brand-700: #8a4028;
  --brand-800: #6f3420;
  --brand-900: #5a2b1b;

  /* Neutrals — warm taupe rather than cool slate, to sit on cream without clashing.
     Lightness order is preserved, so every existing gray-N usage still reads right. */
  --gray-50:  #f6f1e8;
  --gray-100: #efe8db;
  --gray-200: #e7ddc9;
  --gray-300: #d4c7ae;
  --gray-400: #b0a58e;
  --gray-500: #8a8272;
  --gray-600: #6a6151;
  --gray-700: #4a4339;
  --gray-800: #3a352d;
  --gray-900: #2a251d;

  /* Surfaces — the layered cream system. Page is the deepest cream; cards sit a
     shade lighter; inputs / buttons / inner tiles stay white on top; bands tint
     action rows and footers. */
  --surface:        #fbf7f0;
  --surface-page:   #e9e6df;
  --surface-raised: #ffffff;
  --surface-band:   #f5eee1;
  --accent-gradient: linear-gradient(140deg, #c0603f, #d98c5f);

  /* Semantic */
  --success:     #047857;
  --success-bg:  #ecfdf5;
  --success-br:  #a7f3d0;
  --warning:     #b45309;
  --warning-bg:  #fffbeb;
  --warning-br:  #fde68a;
  --danger:      #b91c1c;
  --danger-bg:   #fef2f2;
  --danger-br:   #fecaca;
  --info:        var(--brand-700);
  --info-bg:     var(--brand-50);
  --info-br:     var(--brand-200);

  /* Typography — system stack. No webfont to download, no dependency. "Plus Jakarta
     Sans" leads the stack so that IF it is ever self-hosted (a single @font-face, no
     external request), the friendlier concept typeface applies automatically; until
     then it falls through to the system font with zero cost. */
  --font: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --text-xs:   0.75rem;    /* 12px */
  --text-sm:   0.8125rem;  /* 13px */
  --text-base: 0.9375rem;  /* 15px — data-dense app, 16px feels loose */
  --text-md:   1rem;
  --text-lg:   1.125rem;
  --text-xl:   1.375rem;
  --text-2xl:  1.75rem;

  /* Spacing — 4px scale */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;

  /* Radii — softened toward the concept's rounded, friendly feel. Cards get their
     own larger radius; controls stay tighter. */
  --radius-sm:   8px;
  --radius:      10px;
  --radius-lg:   14px;
  --radius-card: 18px;
  --radius-full: 999px;

  /* Shadows — warm (brown-tinted) rather than cool slate, per the concept. */
  --shadow-sm: 0 1px 2px rgb(80 60 40 / 0.06);
  --shadow:    0 2px 6px rgb(80 60 40 / 0.08), 0 1px 2px rgb(80 60 40 / 0.05);
  --shadow-md: 0 8px 20px rgb(80 60 40 / 0.12), 0 2px 6px rgb(80 60 40 / 0.06);
  --shadow-lg: 0 24px 60px -30px rgb(80 60 40 / 0.40);

  --sidebar-w: 264px;
  --topbar-h:  80px;   /* tall enough for the 3-line cover pill (name + email + phone) + margin */
  --topbar-item-h: 64px;   /* the cover pill's height inside the 80px bar; the logo + sign-out match it */

  --focus-ring: 0 0 0 3px var(--brand-200);
}

/* ==========================================================================
   2. Reset + base
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* The HTML `hidden` attribute must actually hide.
   `[hidden] { display: none }` is only a USER-AGENT rule, and any author rule beats a
   UA one regardless of specificity — so `.alert { display: flex }` silently un-hid every
   element marked hidden, and JS setting `el.hidden = true` had no visible effect. That
   shipped: the family Request Manager rendered ALL of a cover's request types expanded
   at once (23 of them on one real cover) instead of just the one you picked.
   !important because an author rule of equal specificity would otherwise win on source
   order alone, which is too fragile to rely on. */
[hidden] { display: none !important; }

* { margin: 0; }

html { -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--font);
  font-size: var(--text-base);
  line-height: 1.55;
  color: var(--gray-700);
  background: var(--surface-page);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  color: var(--gray-900);
  font-weight: 600;
  line-height: 1.25;
}

h1 { font-size: var(--text-2xl); letter-spacing: -0.02em; }
h2 { font-size: var(--text-xl); letter-spacing: -0.01em; }
h3 { font-size: var(--text-lg); }
h4 { font-size: var(--text-md); }

a {
  color: var(--brand-700);
  text-decoration: none;
}

a:hover { text-decoration: underline; }

img, svg { display: block; max-width: 100%; height: auto; }

/* Inline SVG icons (replacing the FontAwesome font kit). Scale with the
   surrounding text by default; keep square so nothing distorts. */
.icon {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  vertical-align: -0.15em;
}
.icon--lg { width: 1.5rem;  height: 1.5rem; }
.icon--xl { width: 2.25rem; height: 2.25rem; }

:focus-visible {
  outline: 2px solid var(--brand-600);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ==========================================================================
   3. App shell
   ========================================================================== */

.app {
  display: grid;
  grid-template-areas:
    "topbar  topbar"
    "sidebar main";
  grid-template-columns: var(--sidebar-w) 1fr;
  grid-template-rows: var(--topbar-h) 1fr;
  min-height: 100vh;
}

/* --- Topbar --------------------------------------------------------------- */

.topbar {
  grid-area: topbar;
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: 0 var(--space-5);
  background: #fff;
  border-bottom: 1px solid var(--gray-200);
}

.topbar__brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-weight: 700;
  font-size: var(--text-md);
  color: var(--gray-900);
  letter-spacing: -0.01em;
}

.topbar__brand:hover { text-decoration: none; }

.topbar__mark {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  background: var(--accent-gradient);
  color: #fff;
  font-size: var(--text-sm);
  font-weight: 700;
}

/* A cover's uploaded banner, or the HSRO logo when the family has no school.
   Capped on BOTH axes with width:auto, so the browser scales proportionally and nothing is
   ever distorted. The width cap matters because a wide strip crowds a narrow topbar. */
.topbar__logo {
  max-height: var(--topbar-item-h);
  max-width: 240px;
  width: auto;
  object-fit: contain;
}

@media (max-width: 640px) {
  .topbar__logo { max-width: 150px; }
}

.topbar__spacer { flex: 1; }

.topbar__cover {
  display: flex;
  align-items: center;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-lg);
  background: var(--gray-100);
  color: var(--gray-600);
  font-size: var(--text-sm);
  font-weight: 500;
  max-width: 320px;
}

.topbar__cover-info { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
/* Every line leads with an icon (house / envelope / phone); a fixed icon size keeps the icons —
   and the text after them — aligned in a single left column. */
.topbar__cover .icon { width: 0.85rem; height: 0.85rem; flex: none; }
.topbar__cover-name {
  display: flex; align-items: center; gap: var(--space-1);
  font-weight: 600; color: var(--gray-800); min-width: 0;
}
.topbar__cover-contact {
  display: flex; align-items: center; gap: var(--space-1);
  font-size: var(--text-xs); color: var(--gray-500); min-width: 0;
}
.topbar__cover-name > span, .topbar__cover-contact > span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.topbar__cover-contact:hover { text-decoration: underline; }

.topbar__user {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-sm);
  color: var(--gray-500);
}

/* Sign-out button stacks its label over the signed-in email, and stands the same height as
   the cover pill so the topbar's right edge reads as one row of equal-height elements. */
.topbar__signout { height: var(--topbar-item-h); }
.topbar__signout-text { display: inline-flex; flex-direction: column; align-items: flex-start; line-height: 1.15; }
.topbar__signout-email {
  font-size: var(--text-xs); font-weight: 400; opacity: 0.75;
  max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Hamburger — only visible once the sidebar collapses */
.topbar__toggle {
  display: none;
  padding: var(--space-2);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--gray-600);
  cursor: pointer;
}

/* --- Sidebar -------------------------------------------------------------- */

.sidebar {
  grid-area: sidebar;
  position: sticky;
  top: var(--topbar-h);
  align-self: start;
  height: calc(100vh - var(--topbar-h));
  overflow-y: auto;
  padding: var(--space-5) var(--space-3) var(--space-8);
  background: #fff;
  border-right: 1px solid var(--gray-200);
}

.sidebar__section + .sidebar__section { margin-top: var(--space-6); }

.sidebar__heading {
  padding: 0 var(--space-3);
  margin-bottom: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gray-400);
}

.sidebar__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--gray-600);
  font-size: var(--text-base);
  font-weight: 500;
  transition: background 0.12s, color 0.12s;
}

.sidebar__link:hover {
  background: var(--gray-100);
  color: var(--gray-900);
  text-decoration: none;
}

.sidebar__link[aria-current="page"] {
  background: var(--brand-50);
  color: var(--brand-700);
  font-weight: 600;
}

.sidebar__link .icon { color: var(--gray-400); }
.sidebar__link:hover .icon { color: var(--gray-600); }
.sidebar__link[aria-current="page"] .icon { color: var(--brand-600); }

/* A link disabled because the account is read-only: keeps the shape but explains itself. */
.sidebar__link--disabled {
  color: var(--gray-300);
  cursor: not-allowed;
  pointer-events: none;
}

.sidebar__link--disabled .icon { color: var(--gray-300); }

/* --- Main ----------------------------------------------------------------- */

.main {
  grid-area: main;
  min-width: 0; /* lets wide tables scroll instead of blowing out the grid */
  padding: var(--space-6);
}

.container { max-width: 1100px; margin-inline: auto; }

/* 1100px is a reading width — right for forms and prose, wrong for a wide data grid.
   Pages that are a grid set $page_wide (see head.php) and use the room the viewport
   actually has, rather than scrolling a table sideways inside a narrow column. */
.container--wide { max-width: 1600px; }

/* --- Mobile: sidebar becomes an off-canvas drawer -------------------------- */

@media (max-width: 960px) {
  .app {
    grid-template-areas: "topbar" "main";
    grid-template-columns: 1fr;
  }

  .topbar__toggle { display: block; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 60;
    width: min(var(--sidebar-w), 84vw);
    height: 100vh;
    padding-top: var(--space-5);
    box-shadow: var(--shadow-lg);
    transform: translateX(-100%);
    transition: transform 0.22s ease;
  }

  .sidebar[data-open="true"] { transform: translateX(0); }

  .scrim {
    position: fixed;
    inset: 0;
    z-index: 50;
    background: rgb(15 23 42 / 0.45);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.22s ease, visibility 0.22s;
  }

  .scrim[data-open="true"] { opacity: 1; visibility: visible; }

  .main { padding: var(--space-4); }
  .topbar__cover { display: none; }
}

/* ==========================================================================
   4. Components
   ========================================================================== */

/* --- Page header ---------------------------------------------------------- */

.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.page-header__title { margin-bottom: var(--space-1); }

.page-header__meta {
  color: var(--gray-500);
  font-size: var(--text-sm);
}

.page-header__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* --- Card ----------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
}

.card + .card { margin-top: var(--space-5); }

.card__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--gray-200);
}

.card__title {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--gray-900);
}

.card__body { padding: var(--space-5); }

/* Tables sit flush inside a card — no double padding. */
.card__body--flush { padding: 0; }

/* Collapsible card — a native <details> styled as a card whose header (a <summary>) is the
   toggle. Used where a secondary form should fold away until wanted (portfolio's Add Activity).
   No JS, keyboard-accessible; open state driven server-side (open when editing / on error). */
details.card > summary { cursor: pointer; list-style: none; }
details.card > summary::-webkit-details-marker { display: none; }   /* Safari/old Chrome */
details.card:not([open]) > summary { border-bottom: 0; }            /* no dangling rule when folded */
.card__chevron { display: inline-flex; color: var(--gray-500); transition: transform 0.15s ease; }
details.card[open] .card__chevron { transform: rotate(180deg); }

/* --- Definition list (family details, student meta) ----------------------- */

.details {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-5);
  font-size: var(--text-sm);
}

.details dt {
  color: var(--gray-500);
  font-weight: 500;
}

.details dd { color: var(--gray-800); }

/* --- Buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, box-shadow 0.12s;
}

.btn:hover { text-decoration: none; }
.btn:focus-visible { box-shadow: var(--focus-ring); outline: none; }

.btn--primary {
  background: var(--brand-600);
  color: #fff;
}
.btn--primary:hover { background: var(--brand-700); }

.btn--secondary {
  background: #fff;
  border-color: var(--gray-300);
  color: var(--gray-700);
}
.btn--secondary:hover { background: var(--gray-50); border-color: var(--gray-400); }

.btn--ghost { color: var(--gray-600); }
.btn--ghost:hover { background: var(--gray-100); }

.btn--danger {
  background: #fff;
  border-color: var(--danger-br);
  color: var(--danger);
}
.btn--danger:hover { background: var(--danger-bg); }

.btn--sm { padding: var(--space-1) var(--space-3); font-size: var(--text-xs); }

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* --- Icon toolbar (the per-student action row) ---------------------------- */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--gray-600);
  font-size: var(--text-sm);
  font-weight: 500;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}

.icon-btn:hover {
  background: var(--brand-50);
  border-color: var(--brand-200);
  color: var(--brand-700);
  text-decoration: none;
}

.icon-btn .icon { color: var(--gray-400); }
.icon-btn:hover .icon { color: var(--brand-600); }

.icon-btn--danger:hover .icon { color: var(--danger); }

/* Label collapses on small screens; the icon and tooltip carry it. */
@media (max-width: 620px) {
  .icon-btn__label { display: none; }
  .icon-btn { padding: var(--space-2); }
}

/* --- Table ---------------------------------------------------------------- */

/* Wide tables scroll inside their own container rather than pushing the page. */
.table-wrap { overflow-x: auto; }

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.table th {
  padding: var(--space-3) var(--space-4);
  background: var(--gray-50);
  border-bottom: 1px solid var(--gray-200);
  color: var(--gray-500);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
}

.table td {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--gray-100);
  color: var(--gray-700);
  vertical-align: middle;
}

.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover td { background: var(--gray-50); }

/* Zebra striping — opt-in per table. Rounded WHITE-pill rows, matching the .grade-row /
   list zebra so the look is consistent app-wide. A collapsed-border table ignores
   border-radius on cells, so a striped table switches to separate borders (spacing 0, so
   cells still touch) and drops the divider lines — the stripe itself separates the rows,
   exactly as the grade rows do. Every row's end cells are rounded (so hover reads as a
   pill on even rows too); odd rows carry the white fill. Hover sits AFTER the stripe so it
   keeps winning on odd rows (equal specificity, later source order). */
.table--striped { border-collapse: separate; border-spacing: 0; }
.table--striped td { border-bottom: 0; }
.table--striped tbody td:first-child { border-top-left-radius: var(--radius-lg); border-bottom-left-radius: var(--radius-lg); }
.table--striped tbody td:last-child  { border-top-right-radius: var(--radius-lg); border-bottom-right-radius: var(--radius-lg); }
.table--striped tbody tr:nth-child(odd) td { background: var(--surface-raised); }
.table--striped tbody tr:hover td { background: var(--gray-50); }

.report-filter { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-sm); color: var(--gray-600); cursor: pointer; }
/* Slight left/right inset so the rounded pills sit off the card edge, matching the
   .grade-list inset. Scoped to wraps that actually hold a striped table. */
.table-wrap:has(.table--striped) { padding-left: var(--space-2); padding-right: var(--space-2); }

/* Alignment modifiers, on a th OR a td.
   `.table th { text-align: left }` is (0,1,1) and these are (0,1,0), so the bare class
   LOST on every header — the cells right-aligned and the header stayed left, which is
   exactly the "numbers aren't lined up under the headers" on GPA Analytics. Qualifying
   with th/td matches (0,1,1) and, being later in the file, wins. Same family of bug as
   the [hidden] one: a general rule quietly beating a specific-looking modifier. */
.table th.table__num, .table td.table__num,
.table__num { text-align: right; font-variant-numeric: tabular-nums; }

.table th.table__center, .table td.table__center,
.table__center { text-align: center; }

/* Totals row */
.table tfoot td {
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--gray-200);
  background: var(--gray-50);
  color: var(--gray-900);
  font-weight: 600;
}

.table__actions {
  display: flex;
  gap: var(--space-1);
  justify-content: flex-end;
}

/* --- Badge ---------------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 2px var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
}

.badge--neutral { background: var(--gray-100); border-color: var(--gray-200); color: var(--gray-600); }
.badge--brand   { background: var(--brand-50); border-color: var(--brand-200); color: var(--brand-700); }

/* --- Alert ---------------------------------------------------------------- */

.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: var(--text-sm);
  margin-bottom: var(--space-5);
}

.alert .icon { margin-top: 2px; }
.alert__title { font-weight: 600; margin-bottom: 2px; }
.alert__body { flex: 1; }
.alert p { margin: 0; }

.alert--info    { background: var(--info-bg); border-color: var(--info-br); color: var(--info); }

/* Status colours shared by badges, alerts, and the danger icon-button hover — one definition each. */
.badge--success, .alert--success { background: var(--success-bg); border-color: var(--success-br); color: var(--success); }
.badge--warning, .alert--warning { background: var(--warning-bg); border-color: var(--warning-br); color: var(--warning); }
.badge--danger, .alert--danger, .icon-btn--danger:hover { background: var(--danger-bg); border-color: var(--danger-br); color: var(--danger); }

/* --- Forms ---------------------------------------------------------------- */

.field { margin-bottom: var(--space-4); }

.field__label {
  display: block;
  margin-bottom: var(--space-2);
  color: var(--gray-700);
  font-size: var(--text-sm);
  font-weight: 600;
}

.field__hint {
  margin-top: var(--space-2);
  color: var(--gray-500);
  font-size: var(--text-xs);
}

.field__error {
  margin-top: var(--space-2);
  color: var(--danger);
  font-size: var(--text-xs);
  font-weight: 500;
}

.input,
.select,
.textarea {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--gray-900);
  font: inherit;
  font-size: var(--text-base);
  transition: border-color 0.12s, box-shadow 0.12s;
}

.input:hover, .select:hover, .textarea:hover { border-color: var(--gray-400); }

/* A disabled field must LOOK disabled, or the user sees a normal white box and wonders why it
   won't accept typing. `readonly` gets the same treatment minus the cursor: it stays focusable
   and copyable, which is what a calculated field like Scheduled Days wants. */
.input:disabled, .select:disabled, .textarea:disabled,
.input[readonly] {
  background: var(--gray-100);
  color: var(--gray-500);
  border-color: var(--gray-200);
}

.input:disabled, .select:disabled, .textarea:disabled { cursor: not-allowed; }
.input:disabled:hover, .select:disabled:hover, .textarea:disabled:hover,
.input[readonly]:hover { border-color: var(--gray-200); }

.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--brand-500);
  box-shadow: var(--focus-ring);
}

.input[aria-invalid="true"] { border-color: var(--danger); }

.select {
  appearance: none;
  /* Bold selected value, per the design concept. */
  font-weight: 700;
  color: var(--gray-900);
  padding-right: var(--space-8);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
}

.textarea { min-height: 120px; resize: vertical; }

/* Multi-column form layout — collapses on mobile. */
.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--space-5);
}

.form-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.form-grid > .field--full { grid-column: 1 / -1; }

/* Line paired controls up in a grid row even when their labels wrap to different heights (e.g. the
   Background dropdowns on student_form): the grid stretches both cells to equal height, and pushing
   each label to the bottom carries its control with it — so the controls align AND each label sits
   right above its control, with the slack landing ABOVE the shorter label (a CSS leading <br>). */
.form-grid--align-end > .field { display: flex; flex-direction: column; }
.form-grid--align-end > .field > .field__label { margin-top: auto; }

@media (max-width: 720px) {
  .form-grid,
  .form-grid--3 { grid-template-columns: 1fr; }
}

/* The button row that ends every form. */
.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding-top: var(--space-5);
  margin-top: var(--space-2);
  border-top: 1px solid var(--gray-200);
}

.form-actions__spacer { flex: 1; }

/* A field group inside a card, with its own sub-heading. */
.fieldset { border: 0; padding: 0; }

.fieldset + .fieldset {
  margin-top: var(--space-6);
  padding-top: var(--space-6);
  border-top: 1px solid var(--gray-200);
}

.fieldset__legend {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-4);
  background: var(--brand-600);
  color: #fff;
  border-radius: var(--radius-sm);
  font-size: var(--text-md);
  font-weight: 600;
}

/* An inline control bar — e.g. the "View records for: [year]" selector. */
.control-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-5);
  background: #fff;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius);
}

.control-bar label {
  color: var(--gray-600);
  font-size: var(--text-sm);
  font-weight: 600;
}

.control-bar .select { width: auto; min-width: 220px; }

/* Compact inline filters (status + from/to dates on one row). */
.control-bar--filters .select { min-width: 0; }
.control-bar--filters .input { width: auto; }
.control-bar--filters .input[type="date"] { min-width: 9.5rem; }

/* --- Empty state ---------------------------------------------------------- */

.empty {
  padding: var(--space-10) var(--space-5);
  text-align: center;
}

.empty .icon {
  color: var(--gray-300);
  margin: 0 auto var(--space-4);
}

.empty__title {
  color: var(--gray-900);
  font-size: var(--text-lg);
  font-weight: 600;
  margin-bottom: var(--space-2);
}

.empty__body {
  max-width: 44ch;
  margin: 0 auto var(--space-5);
  color: var(--gray-500);
  font-size: var(--text-sm);
}

/* --- Auth screen ---------------------------------------------------------- */

.auth {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: var(--space-5);
  background:
    radial-gradient(1200px 600px at 50% -10%, var(--brand-50), transparent),
    var(--gray-50);
}

.auth__card {
  width: 100%;
  max-width: 400px;
  padding: var(--space-8);
  background: #fff;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.auth__brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
  text-align: center;
}

.auth__mark {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: var(--radius);
  background: var(--accent-gradient);
  color: #fff;
  font-size: var(--text-lg);
  font-weight: 700;
}

.auth__title { font-size: var(--text-xl); }

.auth__tagline { color: var(--gray-500); font-size: var(--text-sm); }

.auth__prompt { text-align: center; color: var(--gray-600); font-size: var(--text-sm); margin-bottom: var(--space-3); }

/* Role picker */
.segmented {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
  padding: var(--space-1);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-5);
}

.segmented input { position: absolute; opacity: 0; pointer-events: none; }

.segmented label {
  padding: var(--space-3);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--gray-700);
  font-size: var(--text-sm);
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, box-shadow 0.12s, border-color 0.12s;
}

.segmented label:hover { border-color: var(--brand-700); }

.segmented input:checked + label {
  background: var(--brand-50);
  border-color: var(--brand-700);
  color: var(--brand-700);
  box-shadow: var(--shadow-sm);
}

.segmented input:focus-visible + label { box-shadow: var(--focus-ring); }

.auth__footer {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--gray-200);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--gray-500);
}

/* Section divider inside the (wider) signup card. */
.auth__section {
  margin: var(--space-6) 0 var(--space-4);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--gray-200);
  font-size: var(--text-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--gray-500);
}

.auth__optional {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  color: var(--gray-400);
}

/* --- Footer --------------------------------------------------------------- */

.footer {
  margin-top: var(--space-10);
  padding-top: var(--space-5);
  border-top: 1px solid var(--gray-200);
  color: var(--gray-400);
  font-size: var(--text-xs);
  text-align: center;
}

.footer a { color: var(--gray-500); }

/* --- Attendance grid ------------------------------------------------------ */

/* Day-code palette. Kept distinct from the semantic tokens so the grid reads on
   its own terms: attended/excused (which count) lean green/blue; the rest are
   muted so a month of school days looks calm, not alarming. */
:root {
  /* Warm & Friendly pastel key. The warm end (red / amber / orange) is already taken
     by Did-not-attend, Excused, and the terracotta accent, so Vacation is a soft
     plum — clearly distinct from both the amber "Excused" and the green "Attended",
     and separable from the magenta "Sick". */
  --att-attended:  #1b7a43;  --att-attended-bg:  #e4f3e9;
  --att-excused:   #b7791f;  --att-excused-bg:   #fbf0de;
  --att-absent:    #c0392b;  --att-absent-bg:    #fbe7e6;
  --att-holiday:   #2a5bb8;  --att-holiday-bg:   #e7eefb;
  --att-sick:      #a93e86;  --att-sick-bg:      #f9eaf4;
  --att-vacation:  #7e46a0;  --att-vacation-bg:  #efe7f7;
}

.att-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

/* Legend doubles as the "brush" picker: click a code, then paint cells. */
.att-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.att-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2) var(--space-1) var(--space-1);
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--gray-700);
  cursor: pointer;
  user-select: none;
}

.att-chip:hover { background: var(--surface-raised); border-color: var(--gray-200); }

.att-chip[aria-pressed="true"] {
  background: var(--surface-raised);
  border-color: var(--brand-400);
  box-shadow: var(--focus-ring);
}

/* Legend swatch — a mini version of a filled cell: pastel bg + the code letter in
   its foreground colour, so the key reads the same as the grid. */
.att-swatch {
  display: inline-grid;
  place-items: center;
  width: 24px; height: 24px;
  border-radius: 7px;
  border: 1px solid rgb(80 60 40 / 0.08);
  font-size: var(--text-xs);
  font-weight: 800;
}
.att-chip__label { padding-right: var(--space-1); }

.att-chip[data-brush="Y"] .att-swatch { background: var(--att-attended-bg); color: var(--att-attended); }
.att-chip[data-brush="E"] .att-swatch { background: var(--att-excused-bg);  color: var(--att-excused); }
.att-chip[data-brush="N"] .att-swatch { background: var(--att-absent-bg);   color: var(--att-absent); }
.att-chip[data-brush="H"] .att-swatch { background: var(--att-holiday-bg);  color: var(--att-holiday); }
.att-chip[data-brush="S"] .att-swatch { background: var(--att-sick-bg);     color: var(--att-sick); }
.att-chip[data-brush="V"] .att-swatch { background: var(--att-vacation-bg); color: var(--att-vacation); }
.att-chip[data-brush=""]  .att-swatch { background: var(--surface-raised);  color: var(--gray-400); }

/* "Apply to all students" — sits in the controls row (right), per the concept. */
.att-apply {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--gray-700);
  cursor: pointer;
}
.att-apply input { width: 1rem; height: 1rem; accent-color: var(--brand-500); }

/* Controls row as a warm tinted band (the concept's #F5EEE1 strip). */
.control-bar--band {
  background: var(--surface-band);
  border-color: transparent;
  padding: var(--space-4) var(--space-5);
}

/* "Pre-fill all weekdays" shortcut — a soft-accent chip with a filled terracotta
   check, per the concept. */
.att-prefill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius);
  background: #f7eadf;
  color: #8a5a3f;
  font-size: var(--text-sm);
  font-weight: 700;
  cursor: pointer;
}
.att-prefill:hover { background: var(--brand-100); }
.att-prefill__check {
  display: grid;
  place-items: center;
  width: 18px; height: 18px;
  border-radius: 5px;
  border: 2px solid currentColor;   /* empty box until the toggle is on */
  background: transparent;
}
.att-prefill__check .icon { width: 12px; height: 12px; visibility: hidden; }
.att-prefill[aria-pressed="true"] .att-prefill__check {
  border-color: var(--brand-500);
  background: var(--brand-500);
  color: #fff;
}
.att-prefill[aria-pressed="true"] .att-prefill__check .icon { visibility: visible; }

.att-grid-wrap { overflow-x: auto; padding: var(--space-2); border: 1px solid var(--gray-200); border-radius: var(--radius-lg); }

/* Separated cells with a small gutter, so each day reads as its own rounded tile
   (per the design concept) rather than a bordered spreadsheet. */
.att-grid { border-collapse: separate; border-spacing: 4px; font-size: var(--text-xs); }

.att-grid th {
  width: 30px;
  padding: var(--space-1) 0;
  background: transparent;
  color: var(--gray-500);
  font-size: 11px;
  font-weight: 700;
  text-align: center;
}

.att-grid th.att-month-head {
  position: sticky;
  left: 0;
  z-index: 2;
  width: 92px;
  min-width: 92px;
  text-align: left;
  padding-left: var(--space-2);
  background: var(--surface);
}

.att-grid td.att-month {
  position: sticky;
  left: 0;
  z-index: 1;
  width: 92px;
  min-width: 92px;
  padding: 0 var(--space-2);
  background: var(--surface);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--gray-600);
  white-space: nowrap;
}

.att-cell {
  width: 30px; height: 30px;
  padding: 0;
  border: 0;
  border-radius: 7px;
  background: var(--surface-raised);
  text-align: center;
}

.att-cell input {
  width: 100%; height: 100%;
  border: 0;
  border-radius: 7px;
  background: transparent;
  text-align: center;
  font: inherit;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--gray-700);
  cursor: pointer;
  caret-color: transparent;
}

.att-cell input:focus {
  outline: 2px solid var(--brand-500);
  outline-offset: -2px;
  border-radius: 7px;
}

/* Weekend + out-of-year tiles are de-emphasized but still editable. */
.att-cell--weekend { background: var(--gray-100); }
.att-cell--out     { background: var(--gray-300); }
.att-cell--empty   { visibility: hidden; }

/* Value colouring, applied by JS via data-code (and inline for no-JS load). */
.att-cell[data-code="Y"] { background: var(--att-attended-bg); }
.att-cell[data-code="E"] { background: var(--att-excused-bg); }
.att-cell[data-code="N"] { background: var(--att-absent-bg); }
.att-cell[data-code="H"] { background: var(--att-holiday-bg); }
.att-cell[data-code="S"] { background: var(--att-sick-bg); }
.att-cell[data-code="V"] { background: var(--att-vacation-bg); }
.att-cell[data-code="Y"] input { color: var(--att-attended); }
.att-cell[data-code="E"] input { color: var(--att-excused); }
.att-cell[data-code="N"] input { color: var(--att-absent); }
.att-cell[data-code="H"] input { color: var(--att-holiday); }
.att-cell[data-code="S"] input { color: var(--att-sick); }
.att-cell[data-code="V"] input { color: var(--att-vacation); }

/* Live totals */
.att-totals {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: center;
  padding: var(--space-4);
  margin-top: var(--space-4);
  background: var(--brand-50);
  border: 1px solid var(--brand-200);
  border-radius: var(--radius);
}

.att-total__big {
  font-size: var(--text-2xl);
  font-weight: 700;
  color: var(--brand-700);
  font-variant-numeric: tabular-nums;
}

.att-total__label { color: var(--gray-600); font-size: var(--text-sm); }
.att-breakdown { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-left: auto; }
.att-breakdown span { font-size: var(--text-xs); color: var(--gray-600); font-variant-numeric: tabular-nums; }

/* --- EZ grade grid --------------------------------------------------------- */

.ez-table td { vertical-align: top; }

.ez-cell {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

/* Compact selects: the grade menu takes the room, credits stays narrow. */
.ez-select { padding: var(--space-1) var(--space-2); font-size: var(--text-sm); }
.ez-cell .ez-select:first-child { flex: 1; min-width: 68px; }
.ez-cell .ez-select:last-child  { width: 68px; flex: none; }
.ez-num { font-weight: 700; }
.ez-letter { min-width: 1.75em; text-align: center; font-weight: 700; color: var(--gray-900); }

/* Start-of-year "Set Up Subjects" grid — keep 15 rows dense. */
.ez-add-table td { padding: var(--space-1) var(--space-2); vertical-align: middle; }
.ez-add-table .select,
.ez-add-table .input { padding: var(--space-1) var(--space-2); font-size: var(--text-sm); }
.ez-add-table .select { padding-right: var(--space-6); }

/* --- Grading-scale editor -------------------------------------------------- */

.grade-table th { text-align: center; }
.grade-table td { text-align: center; }
.grade-num { font-weight: 600; color: var(--gray-900); font-variant-numeric: tabular-nums; }

.grade-input {
  width: 4.75rem;
  margin: 0 auto;
  padding: var(--space-1) var(--space-2);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.grade-select {
  width: 5.5rem;
  margin: 0 auto;
  padding-top: var(--space-1);
  padding-bottom: var(--space-1);
}

/* An inline checkbox + explanatory text (the Honors toggle). */
.check {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  cursor: pointer;
}
.check input[type="checkbox"] {
  width: 1.1rem;
  height: 1.1rem;
  margin-top: 3px;
  flex: none;
  accent-color: var(--brand-500);
}
.check input[type="checkbox"]:disabled { accent-color: var(--gray-300); }
.check__text { font-size: var(--text-sm); color: var(--gray-600); line-height: 1.5; }

/* --- School news items ----------------------------------------------------- */

.news-item {
  padding: var(--space-3);
  border-radius: var(--radius-lg);   /* rounded rows, consistent with .grade-row / .table--striped */
}
/* Zebra: this list isn't a <table>, so it stripes the article rows directly. Odd rows
   tinted to match the rest; every row is rounded (even ones invisibly). */
.news-item:nth-child(odd) {
  background: var(--surface-raised);
}

.news-item__head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: var(--space-1);
}

.news-item__title {
  margin: 0;
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--gray-900);
}

/* Compact preview line — title + date + first line only, to keep rows short. */
.news-item__snippet {
  color: var(--gray-600);
  font-size: var(--text-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- School reports: stat tiles + report grid ------------------------------ */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-4);
}

.stat-tile {
  padding: var(--space-4);
  border: 1px solid var(--gray-200);
  border-left-width: 3px;
  border-radius: var(--radius-sm);
  background: #fff;
}
.stat-tile__value { font-size: var(--text-2xl); font-weight: 700; color: var(--gray-900); font-variant-numeric: tabular-nums; line-height: 1.1; }
.stat-tile__label { margin-top: var(--space-1); font-size: var(--text-xs); color: var(--gray-500); text-transform: uppercase; letter-spacing: 0.04em; }
.stat-tile--success { border-left-color: var(--success); }
.stat-tile--warning { border-left-color: var(--warning); }
.stat-tile--neutral { border-left-color: var(--gray-300); }
.stat-tile--brand   { border-left-color: var(--brand-500); }

.report-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-3);
}

.report-tile {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding: var(--space-4);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-sm);
  background: #fff;
}
.report-tile--soon { opacity: 0.75; }
.report-tile__title { font-weight: 600; color: var(--gray-800); }
.report-tile__desc { margin-top: 2px; font-size: var(--text-sm); color: var(--gray-500); }

/* --- Family dashboard: student picker + gradient record header ------------- */

.students { display: flex; flex-direction: column; gap: var(--space-4); }

.picker-label {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gray-500);
}

.picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--space-3);
}

.picker__card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-raised);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-lg);
  cursor: pointer;
  text-align: left;
  font: inherit;
  transition: border-color .12s, box-shadow .12s, background .12s;
}
.picker__card:hover { border-color: var(--brand-300); box-shadow: var(--shadow-sm); }
.picker__card.is-active {
  border-color: var(--brand-500);
  box-shadow: inset 0 0 0 1px var(--brand-500);
  background: var(--brand-50);
}

.avatar {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  border-radius: var(--radius);
  background: var(--brand-100);
  color: var(--brand-700);
  font-weight: 800;
  font-size: var(--text-sm);
}

.picker__meta { display: flex; flex-direction: column; min-width: 0; }
.picker__name { font-weight: 700; color: var(--gray-800); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.picker__sub { font-size: var(--text-xs); color: var(--gray-500); }

/* One record at a time once JS enhances the picker; with JS off, all records show. */
[data-student-picker][data-enhanced] .student-record { display: none; }
[data-student-picker][data-enhanced] .student-record.is-active { display: block; }

.student-record { overflow: hidden; }   /* clip the gradient header to the card radius */

.record-header {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-5);
  background: var(--accent-gradient);
  color: #fff;
}
.record-header__avatar {
  flex: none;
  display: grid; place-items: center;
  width: 48px; height: 48px;
  border-radius: var(--radius);
  background: rgb(255 255 255 / 0.2);
  color: #fff; font-weight: 800; font-size: var(--text-md);
}
.record-header__id { flex: 1; min-width: 0; }
.record-header__name { font-size: var(--text-lg); font-weight: 800; }
.record-header__meta { font-size: var(--text-sm); color: rgb(255 255 255 / 0.85); }

.record-stats { display: flex; gap: var(--space-5); }
.record-stat { text-align: center; }
.record-stat__value { font-size: var(--text-xl); font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; }
.record-stat__label { font-size: var(--text-xs); letter-spacing: 0.06em; text-transform: uppercase; color: rgb(255 255 255 / 0.8); }

.record-header__action {
  flex: none;
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 0.18);
  color: #fff; font-size: var(--text-sm); font-weight: 700;
  text-decoration: none;
}
.record-header__action:hover { background: rgb(255 255 255 / 0.28); text-decoration: none; }

.record-header__actions { display: flex; gap: var(--space-2); flex: none; }
.record-header__action--danger:hover { background: rgb(120 20 15 / 0.55); }

@media (max-width: 600px) {
  .record-header { flex-wrap: wrap; }
  .record-stats { gap: var(--space-4); }
}

/* --- Dashboard two-column layout (records + school-news aside) -------------- */

.dash { display: flex; gap: var(--space-5); align-items: flex-start; }
.dash__main { flex: 1; min-width: 0; }
.dash__side { width: 300px; flex: none; display: flex; flex-direction: column; gap: var(--space-4); }

/* --- Right rail: How-to videos + Help resources --------------------------------
   The Warm & Friendly concept puts both in ONE tinted card under School News
   (Dashboard Redesign.dc.html:384-396). Its literal values are all existing tokens:
   #F5EEE1 = --surface-band, #e7ddc9 = --gray-200, 18px = --radius-card. */
.card--band { background: var(--surface-band); }

.rail__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-base);
  font-weight: 800;
  margin-bottom: var(--space-3);
}
.rail__title--sm { font-size: var(--text-sm); margin-bottom: var(--space-2); }
.rail__title .icon { color: var(--brand-500); }

.rail__rule { border: 0; border-top: 1px solid var(--gray-200); margin: var(--space-4) 0; }

.video-list, .help-list { list-style: none; margin: 0; padding: 0; }
.video-list { display: flex; flex-direction: column; gap: var(--space-2); }

.video-link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--gray-700);
  text-decoration: none;
  border-radius: var(--radius-sm);
}
.video-link:hover { color: var(--brand-700); }
.video-link:hover .video-link__play { transform: scale(1.08); }

/* The concept's terracotta play chip. flex-none so a two-line label cannot squash it. */
.video-link__play {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: var(--brand-500);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  line-height: 1;
  transition: transform 0.12s ease;
}

.help-list a {
  display: block;
  padding: var(--space-1) 0;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--brand-700);
  text-decoration: none;
}
.help-list a:hover { text-decoration: underline; }

/* --- Type-ahead ----------------------------------------------------------------
   A suggestion panel anchored UNDER its field. The native <datalist> it replaces drew
   its popup wherever the browser chose — beside the field, in practice.

   The panel is absolutely positioned against .typeahead (which JS wraps around the
   input), so it overlays whatever follows instead of shoving the form down as the user
   types. z-index sits above form chrome but below the video dialog's top layer, which
   the browser handles itself. */
.typeahead { position: relative; }

.typeahead__list {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  z-index: 20;
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  max-height: 17rem;
  overflow-y: auto;
  background: var(--surface-raised);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg, 0 10px 30px rgb(0 0 0 / 0.14));
}

.typeahead__item {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--gray-700);
  cursor: pointer;
  /* Long titles are common (one real name runs 100 chars) — keep rows one line. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The typed run. Everything else is the completion — the inverse of a plain list, and the
   thing that makes a suggestion scannable. */
.typeahead__item strong { color: var(--gray-900); font-weight: 700; }

.typeahead__item:hover,
.typeahead__item.is-active { background: var(--surface-band); }

/* --- Pager ---------------------------------------------------------------------
   Plain links, so a page is bookmarkable and Back works. Rendered only when there is
   more than one page (see pager() in components.php). */
.pager {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-5);
}

.pager__count,
.pager__page {
  font-size: var(--text-sm);
  color: var(--gray-600);
}

.pager__page { font-weight: 600; }

.pager__links {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

/* The ends of the range: present, so the control does not resize as you page, but inert. */
.is-disabled {
  opacity: 0.45;
  pointer-events: none;
}

/* --- Lesson plans: clamped rows -------------------------------------------------
   The clamp hangs off [data-enhanced], which app.js sets — so it exists only when the
   JS that can undo it does. See the note there. */
.lp__table[data-enhanced="true"] .lp__detail {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  white-space: pre-wrap;
}

.lp__table[data-enhanced="true"] tr.is-expanded .lp__detail {
  -webkit-line-clamp: unset;
  line-clamp: unset;
  overflow: visible;
}

/* Not [data-enhanced]: the no-JS fallback still needs newlines to survive. */
.lp__detail { white-space: pre-wrap; }

.lp__table tr.is-clampable { cursor: pointer; }

.lp__more {
  display: inline-flex;
  align-items: center;
  margin-top: var(--space-1);
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand-700);
  font: inherit;
  font-size: var(--text-xs);
  font-weight: 700;
  cursor: pointer;
}

.lp__more:hover { text-decoration: underline; }

/* --- Quick View ----------------------------------------------------------------
   The grid is 14 columns wide: the whole record on one screen is the promise, so every
   column stays and .table-wrap scrolls rather than anything being dropped. The year is a
   band heading instead of a column. */
.qv__year {
  padding: var(--space-3) var(--space-5);
  background: var(--surface-band);
  font-weight: 800;
  font-size: var(--text-sm);
}

/* Density: 14 columns of real data, so trim the cell padding the app's default table
   uses and drop a step in type size. */
.qv__grid th,
.qv__grid td {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
}

/* Widths: a plain auto-layout table — every column shrinks to its content, and the free-text
   columns absorb whatever is left so a long description grows WIDE rather than tall. The goal
   is no horizontal scrolling.
 *
 * The narrow columns carry .qv__min: `width: 1%` + nowrap is the auto-layout idiom for
 * "shrink to fit" — the 1% is never honoured (the content floors it), it just tells the
 * layout to give this column nothing spare. What is left then goes to the un-sized
 * columns: Subject, Textbook and the three .qv__prose ones.
 *
 * No min/max width on the prose columns, and no pre-wrap: both fought the row-height goal.
 * Newlines collapse to spaces — same text, fewer lines. */
.qv__grid { table-layout: auto; }

/* The HEADERS were setting the column widths, not the data. `.table th` is nowrap +
   uppercase + letter-spacing, which made "HISTORY CREATED" 142px wide to hold a cell of
   "Jul 17, 2026" — the nine narrow columns were claiming 941px of a 951px table on header
   text alone, and the prose columns got whatever was left (so they went tall). Let the
   headers wrap onto two lines and drop the tracking: the column falls back to its DATA
   width, which is the point of .qv__min. */
.qv__grid th {
  white-space: normal;
  text-transform: none;
  letter-spacing: 0;
  vertical-align: bottom;
}

.qv__grid td.qv__min {
  width: 1%;
  white-space: nowrap;
}

/* Prose reads better from the top once a neighbouring cell is several lines tall. */
.qv__grid td { vertical-align: top; }

/* A standards cell holds tokens like `CCSS.MATH.CONTENT.HSS.IC.B.4` — one unbreakable
   28-character word, which becomes the column's min-content and a 212px floor it can
   never go under. Let those break so the column is sized by the text, not by its longest
   token. */
.qv__prose { overflow-wrap: break-word; }

/* --- How-to video player -------------------------------------------------------
   Isolates the video from YouTube's own page, in a <dialog>: black, chrome-free, nothing
   around the video but a title and a close button. 16:9, because the videos are widescreen. */
.video-modal {
  width: min(90vw, 960px);
  /* Centred both ways. A modal <dialog> is inset:0 in the top layer and the UA centres
     it with `dialog { margin: auto }` — but our own `* { margin: 0 }` reset (line 136)
     wins over the UA rule and pinned it to the top-left. Restore it explicitly.
     Same trap as [hidden]: a blanket author rule silently undoing a UA default. */
  margin: auto;
  max-height: calc(100vh - 2 * var(--space-5));
  padding: 0;
  border: 0;
  border-radius: var(--radius-card);
  background: #000;
  color: #fff;
  overflow: hidden;
}
.video-modal::backdrop { background: rgb(0 0 0 / 0.7); }

.video-modal__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
}

.video-modal__title { font-size: var(--text-base); font-weight: 700; color: #fff; }

.video-modal__close {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: #fff;
  cursor: pointer;
}
.video-modal__close:hover { background: rgb(255 255 255 / 0.15); }

/* aspect-ratio letterboxes the video to 16:9. */
.video-modal__frame { aspect-ratio: 16 / 9; }
.video-modal__frame iframe { display: block; width: 100%; height: 100%; border: 0; }

/* --- Confirmation modal ----------------------------------------------------
   Replaces the browser's native confirm() so a destructive action can explain its impact in
   our own words. Built by app.js; shown with dialog.showModal() (top layer + backdrop). */
.confirm-modal {
  width: min(32rem, calc(100vw - 2rem));
  margin: auto;                 /* centre in the top layer */
  padding: var(--space-6);
  border: 0;
  border-radius: var(--radius-lg);
  background: #fff;
  color: var(--gray-800);
  box-shadow: var(--shadow-lg);
}
.confirm-modal::backdrop { background: rgb(0 0 0 / 0.5); }

.confirm-modal__title {
  margin: 0 0 var(--space-3);
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--gray-900);
}
.confirm-modal--danger .confirm-modal__title { color: var(--danger); }

.confirm-modal__message p {
  margin: 0 0 var(--space-2);
  line-height: 1.5;
  color: var(--gray-700);
}
.confirm-modal__message p:last-child { margin-bottom: 0; }

.confirm-modal__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-5);
}

@media (max-width: 920px) {
  .dash { flex-direction: column; }
  .dash__side { width: 100%; }
}

/* --- Concept-style subject rows -------------------------------------------- */

.grade-list { padding: var(--space-2); }

/* One row per subject: name/meta, the period grade tiles, and total credits. */
.grade-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3);
  border-radius: var(--radius-lg);
}
.grade-row:nth-child(odd) { background: var(--surface-raised); }   /* zebra: alternate white */
.grade-row:hover { background: var(--surface-band); }

.grade-row__subject { flex: 1; min-width: 0; }
.grade-row__name { font-weight: 700; color: var(--gray-900); }
.grade-row__meta { margin-top: 1px; font-size: var(--text-xs); color: var(--gray-500); }

.grade-row__chips { display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: flex-end; }

/* A period tile holding the grade plus its own edit / delete icons. */
.grade-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 3px 4px 3px 10px;
  background: var(--gray-100);
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--gray-800);
  white-space: nowrap;
}
.grade-chip__period { color: var(--gray-500); font-weight: 600; }
.grade-chip__grade { margin-right: var(--space-1); }

.grade-chip__delform { display: inline-flex; margin: 0; }
.grade-chip__btn {
  display: inline-grid;
  place-items: center;
  width: 22px; height: 22px;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: 6px;
  color: var(--gray-500);
  cursor: pointer;
  text-decoration: none;
}
.grade-chip__btn .icon { width: 13px; height: 13px; }
.grade-chip__btn:hover { background: var(--brand-100); color: var(--brand-700); }
.grade-chip__btn--del:hover { background: var(--danger-bg); color: var(--danger); }

.grade-row__credits {
  width: 56px;
  flex: none;
  text-align: right;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--gray-700);
  font-variant-numeric: tabular-nums;
}

.grade-total {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--gray-200);
  background: var(--surface-band);
}
.grade-total__label { color: var(--gray-600); font-size: var(--text-sm); }
.grade-total__value { font-size: var(--text-lg); font-weight: 800; color: var(--brand-600); font-variant-numeric: tabular-nums; }

/* --- Curriculum research tool ("What Others Teach") ------------------------ */

.research { display: flex; gap: var(--space-5); align-items: flex-start; flex-wrap: wrap; }
.research__subjects { width: 320px; flex: none; }
.research__books { flex: 1; min-width: 0; }

@media (max-width: 820px) {
  .research__subjects, .research__books { width: 100%; flex: auto; }
}

.research-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  color: var(--gray-700);
  text-decoration: none;
  border-radius: var(--radius-lg);   /* rounded pills, consistent with .grade-row / .table--striped */
}
/* Zebra the Top-subjects rows (odd = white on the cream card). Placed BEFORE :hover /
   .is-active so those later, equal-specificity rules still win. */
.research-row:nth-child(odd) { background: var(--surface-raised); }
.research-row:hover { background: var(--surface-band); text-decoration: none; }
.research-row.is-active { background: var(--brand-50); color: var(--brand-700); font-weight: 700; }

.research-row__rank {
  width: 24px; flex: none;
  text-align: center;
  color: var(--gray-400);
  font-size: var(--text-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.research-row.is-active .research-row__rank { color: var(--brand-500); }
.research-row__name { flex: 1; min-width: 0; }
.research-row__caret { flex: none; display: inline-flex; color: var(--brand-500); }
.research-row__caret .icon { width: 15px; height: 15px; }

/* --- GPA Analytics chart (native, no external chart lib) -------------------
   Series colours are the validated CVD-safe categorical set (data-viz guidance),
   deliberately independent of the warm brand chrome. Bars are zero-based; every
   bar is value-labelled, which satisfies the low-contrast "relief rule". */

/* .gpa-legend, .gpa-key, .gpa-swatch, .gpa-group__name, .gpa-fill and .gpa-table summary carry the
   identical rules of their .chart-* twins and are grouped onto those (chart section). Only the
   GPA-specific pieces (series grid, three-colour bars, per-subject banding) live here. */
.gpa-swatch--student  { background: #2a78d6; }
.gpa-swatch--state    { background: #1baf7a; }
.gpa-swatch--national { background: #eda100; }

.gpa-chart { display: flex; flex-direction: column; gap: var(--space-4); }

/* Alternating band per subject: each .gpa-group is one subject (its name + the three bars),
   banded as a unit so adjacent subjects read apart. Both parities are tinted (white vs. warm
   cream) so every subject is a visible band, alternating one to the next — not one banded and
   one blank (the groups sit in a gapped flex column, so an untinted row would read as a gutter). */
.gpa-group { padding: var(--space-3); border-radius: var(--radius-lg); }
.gpa-group:nth-child(odd)  { background: var(--surface-raised); }
.gpa-group:nth-child(even) { background: var(--surface-band); }

.gpa-series {
  display: grid;
  grid-template-columns: 42px 1fr 46px;
  align-items: center;
  gap: var(--space-3);
  padding: 2px 0;
}
.gpa-series__tag { font-size: var(--text-xs); color: var(--gray-500); font-weight: 700; }
.gpa-track { height: 14px; background: var(--gray-100); border-radius: var(--radius-full); overflow: hidden; }
.gpa-fill--student  { background: #2a78d6; }
.gpa-fill--state    { background: #1baf7a; }
.gpa-fill--national { background: #eda100; }
.gpa-series__val { text-align: right; font-weight: 700; font-size: var(--text-sm); color: var(--gray-800); font-variant-numeric: tabular-nums; }
.gpa-series__val--na { color: var(--gray-400); }

.gpa-table { margin-top: var(--space-4); }

@media (max-width: 560px) {
  .grade-row { flex-wrap: wrap; }
  .grade-row__chips { justify-content: flex-start; }
}

/* Native charts — server-rendered CSS bars, no gstatic. Bar colours are set inline per bar
   from lib/chart.php so an unset var can't blank a fill. */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--space-5);
  align-items: start;   /* top-align cards of unequal height, not stretch/bottom */
}
/* Cancel the stacked-card top margin (`.card + .card`) inside the side-by-side grid,
   which otherwise pushed the second card down out of top alignment. */
.dash-grid > .card { margin-top: 0; }

.chart { display: flex; flex-direction: column; gap: var(--space-3); }
.chart-row {
  display: grid;
  grid-template-columns: minmax(84px, 150px) 1fr minmax(44px, auto);
  align-items: center;
  gap: var(--space-3);
}
.chart-row__label {
  font-size: var(--text-sm); color: var(--gray-700); font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chart-track { height: 16px; background: var(--gray-100); border-radius: var(--radius-full); overflow: hidden; }
.chart-fill, .gpa-fill { height: 100%; border-radius: var(--radius-full); min-width: 2px; }
.chart-row__val {
  text-align: right; font-weight: 700; font-size: var(--text-sm);
  color: var(--gray-800); font-variant-numeric: tabular-nums;
}
.chart-row__val--na { color: var(--gray-400); font-weight: 600; }

/* Grouped bars (average GPA by grade level) */
.chart--grouped { gap: var(--space-4); }
.chart-group__name, .gpa-group__name { font-weight: 700; color: var(--gray-900); font-size: var(--text-sm); margin-bottom: var(--space-1); }
.chart-legend, .gpa-legend { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-bottom: var(--space-4); }
.chart-key, .gpa-key { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--gray-700); }
.chart-swatch, .gpa-swatch { width: 12px; height: 12px; border-radius: 3px; flex: none; }
.chart-swatch--line { height: 3px; border-radius: 2px; }

/* Native SVG line chart */
.chart-line-wrap { width: 100%; overflow-x: auto; }
.chart-line { width: 100%; height: auto; display: block; min-width: 320px; }
.chart-line__grid { stroke: var(--gray-200); stroke-width: 1; }
.chart-line__ylabel, .chart-line__xlabel { fill: var(--gray-500); font-size: 10px; font-variant-numeric: tabular-nums; }
.chart-line__series { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }

.chart-note { font-size: var(--text-xs); color: var(--gray-500); margin-top: var(--space-3); }
.chart-numbers { margin-top: var(--space-3); }
.chart-numbers summary, .gpa-table summary { cursor: pointer; font-size: var(--text-sm); font-weight: 600; color: var(--brand-700); }
.chart-numbers[open] summary, .gpa-table[open] summary { margin-bottom: var(--space-3); }

/* Request Manager section — content + a right-side sub-nav rail. */
.rm-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 220px;
  gap: var(--space-6);
  align-items: start;
}
.rm-layout__main { min-width: 0; }
.rm-rail {
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-card);
  padding: var(--space-4);
  position: sticky;
  top: var(--space-5);
}
.rm-rail__title {
  display: flex; align-items: center; gap: var(--space-2);
  font-weight: 700; color: var(--gray-900); font-size: var(--text-sm);
  margin-bottom: var(--space-3);
}
.rm-rail__nav { display: flex; flex-direction: column; gap: 2px; }
.rm-rail__link {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
  color: var(--gray-700); font-size: var(--text-sm); text-decoration: none;
}
.rm-rail__link:hover { background: var(--gray-100); }
.rm-rail__link.is-active { background: var(--brand-50); color: var(--brand-700); font-weight: 600; }
.rm-rail__subhead { margin-top: var(--space-4); margin-bottom: var(--space-2); font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--gray-500); }
.rm-rail__link--soon { color: var(--gray-400); cursor: default; }
.rm-rail__link--soon:hover { background: none; }

@media (max-width: 900px) {
  .rm-layout { grid-template-columns: 1fr; }
  .rm-rail { position: static; }
}

/* Active filter chip (e.g. Request Manager list filtered to one request type). */
.filter-chip {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-1) var(--space-3); border-radius: var(--radius-full);
  background: var(--gray-100); color: var(--gray-700); font-size: var(--text-sm);
}
.filter-chip a { color: var(--gray-500); text-decoration: none; font-weight: 700; line-height: 1; }
.filter-chip a:hover { color: var(--danger); }

/* ==========================================================================
   5. Utilities
   ========================================================================== */

.stack > * + * { margin-top: var(--space-5); }
.muted { color: var(--gray-500); }
.strong { font-weight: 600; color: var(--gray-900); }
.text-danger { color: var(--danger); }
.nowrap { white-space: nowrap; }
.text-right { text-align: right; }
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.mb-3 { margin-bottom: var(--space-3); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ==========================================================================
   6. Print — transcripts and reports are printed constantly in this app
   ========================================================================== */

@media print {
  .topbar,
  .sidebar,
  .scrim,
  .toolbar,
  .control-bar,
  .page-header__actions,
  .footer { display: none !important; }

  .app { display: block; }
  .main { padding: 0; }
  body { background: #fff; font-size: 11pt; }

  .card {
    border: 0;
    box-shadow: none;
    break-inside: avoid;
  }

  .table th { background: #fff; }
  a { color: inherit; text-decoration: none; }
}

/* --- Transcript document --------------------------------------
   The transcript is a DOCUMENT people print and hand to a college or a state
   office, so it is styled as paper inside the app shell rather than as another
   dashboard card: tighter type, a rule under the letterhead, and print rules
   that drop the app chrome so what prints is the document alone. */
.transcript { font-size: 0.95rem; }

.transcript__masthead {
  display: flex;
  justify-content: space-between;
  gap: var(--space-5);
  flex-wrap: wrap;
  padding-bottom: var(--space-4);
  margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
}

.transcript__title { margin: 0 0 var(--space-1); font-size: 1.35rem; }
.transcript__school,
.transcript__student-meta { text-align: right; line-height: 1.5; }
.transcript__table { font-size: 0.9rem; }

.transcript__footer {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--space-5);
  flex-wrap: wrap;
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 2px solid var(--border);
}

/* Label/value pairs, right-aligned under the table. */
.transcript__totals {
  display: grid;
  grid-template-columns: auto auto;
  gap: var(--space-1) var(--space-3);
  margin: 0;
  text-align: right;
}
.transcript__totals dt { color: var(--text-muted); }
.transcript__totals dd { margin: 0; font-variant-numeric: tabular-nums; }

@media print {
  /* Print the document, not the app. */
  .sidebar, .topbar, .page-header--print-hide, .flash, .nav { display: none !important; }
  .card { border: none !important; box-shadow: none !important; background: #fff !important; }
  .transcript { font-size: 11pt; }
  .transcript__table { font-size: 10pt; }
  a[href]::after { content: none !important; }
}

/* AI transcript narrative — sits under the document, clearly a generated addendum. */
.transcript__narrative {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}
.transcript__narrative-title { margin: 0 0 var(--space-2); font-size: 1rem; }
.transcript__narrative p { margin: 0 0 var(--space-3); }

/* ---------- Impersonation banner ----------------------------------------- */
/* Shown on every customer page when an admin has "opened as" this account (set by
   admin/impersonate.php). A solid amber bar so it is unmistakable. */
.impersonation-bar {
  display: flex; align-items: center; gap: var(--space-2);
  background: var(--warning); color: #fff;
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm); font-weight: 600;
}
.impersonation-bar .icon { color: #fff; }
.impersonation-bar__text strong { font-weight: 800; }
.impersonation-bar__exit {
  margin-left: auto; display: inline-flex; align-items: center; gap: var(--space-1);
  color: #fff; text-decoration: underline; white-space: nowrap;
}
.impersonation-bar__exit:hover { opacity: .85; }
.impersonation-bar__exit .icon { color: #fff; }

/* Advisory email-field hint (assets/js/email-check.js). */
.email-hint { min-height: 0; }
.email-hint--warn { color: var(--warning); font-size: var(--text-sm); margin-top: var(--space-1); }
.email-hint--ok   { color: var(--success); font-size: var(--text-sm); margin-top: var(--space-1); }
