/* ============================================================
   Smoke Signal Solutions Classroom — Theme System
   "Field protocol, modernized" — signage-style display type,
   clinical neutrals, per-level accent palettes, dark/light.
   To re-theme for a different classroom, swap the accent block.
   ============================================================ */

/* ============================================================
   ACCENT PALETTES — one per EMS level
   Default is EMT. Applied dynamically via data-level attribute
   on <html> or via user preference.
   ============================================================ */

/* EMT (Ember) — default.
   The Ember look (2026-09): the same palette as the iPad/iPhone app, so a
   student moving between the two sees one brand. --accent is the deeper
   Ember (white text on it reads at 5.3:1); the logo flame (#FF4D3D) is
   3.3:1 on white, so it stays an icon and fill colour, never text.
   --accent-light is the dark-mode link red (6.3:1 on charcoal);
   --accent-dark is the light-mode one (5.6:1 on ash). */
:root,
[data-level="emt"] {
  --accent:            #C8321F;
  --accent-light:      #FF6A4D;
  --accent-subtle:     #FBE7E3;
  --accent-dark:       #B92D1C;
  --accent-text:       #5C150B;
  --accent-focus:      rgba(200, 50, 31, 0.25);
  --accent-tint:       rgba(200, 50, 31, 0.1);
  --accent-tint-light: rgba(200, 50, 31, 0.05);
  --dark-deepest:      #16171A;
  --dark-mid:          #1F2125;
  --dark-light:        #2A2D33;
  --color-bg-card-rgb: 31, 33, 37;
  --color-bg-input-dark: #111215;
}

/* EMR (Teal) */
[data-level="emr"] {
  --accent:            #0694A2;
  --accent-light:      #5EEAD4;
  --accent-subtle:     #D5F5F6;
  --accent-dark:       #036672;
  --accent-text:       #014751;
  --accent-focus:      rgba(6, 148, 162, 0.25);
  --accent-tint:       rgba(6, 148, 162, 0.1);
  --accent-tint-light: rgba(6, 148, 162, 0.05);
  --dark-deepest:      #0a1a1a;
  --dark-mid:          #142d2d;
  --dark-light:        #1f3d3d;
  --color-bg-card-rgb: 20, 45, 45;
  --color-bg-input-dark: #081414;
}

/* AEMT (Green) */
[data-level="aemt"] {
  --accent:            #2E7D32;
  --accent-light:      #97C459;
  --accent-subtle:     #EAF3DE;
  --accent-dark:       #3B6D11;
  --accent-text:       #27500A;
  --accent-focus:      rgba(46, 125, 50, 0.25);
  --accent-tint:       rgba(46, 125, 50, 0.1);
  --accent-tint-light: rgba(46, 125, 50, 0.05);
  --dark-deepest:      #0a1a0a;
  --dark-mid:          #142d14;
  --dark-light:        #1f3d1f;
  --color-bg-card-rgb: 20, 45, 20;
  --color-bg-input-dark: #080f08;
}

/* Paramedic (Blue) */
[data-level="paramedic"] {
  --accent:            #185FA5;
  --accent-light:      #85B7EB;
  --accent-subtle:     #E6F1FB;
  --accent-dark:       #0C447C;
  --accent-text:       #042C53;
  --accent-focus:      rgba(24, 95, 165, 0.25);
  --accent-tint:       rgba(24, 95, 165, 0.1);
  --accent-tint-light: rgba(24, 95, 165, 0.05);
  --dark-deepest:      #0a0e1a;
  --dark-mid:          #14202d;
  --dark-light:        #1f2f3d;
  --color-bg-card-rgb: 20, 32, 45;
  --color-bg-input-dark: #080b14;
}

/* Critical Care (Gold) */
[data-level="critical_care"] {
  --accent:            #BA7517;
  --accent-light:      #EF9F27;
  --accent-subtle:     #FAEEDA;
  --accent-dark:       #854F0B;
  --accent-text:       #633806;
  --accent-focus:      rgba(186, 117, 23, 0.25);
  --accent-tint:       rgba(186, 117, 23, 0.1);
  --accent-tint-light: rgba(186, 117, 23, 0.05);
  --dark-deepest:      #1a140a;
  --dark-mid:          #2d2214;
  --dark-light:        #3d301f;
  --color-bg-card-rgb: 45, 34, 20;
  --color-bg-input-dark: #140e08;
}

/* --- Dark Theme (default) — backgrounds derived from active accent palette --- */
:root {

  --color-success-green: #3ECF9A;
  --color-warning-yellow: #FFB547;
  --color-danger-red: #ef4444;
  --color-info-blue: #4DA3FF;

  --color-text-primary: #F4F2EF;
  --color-text-secondary: #C9C6C1;
  --color-text-muted: rgba(244, 242, 239, 0.62);
  --color-text-dark: #16171A;

  --color-bg-body: var(--dark-deepest);
  --color-bg-card: rgba(var(--color-bg-card-rgb), 0.85);
  --color-bg-card-header: var(--dark-light);
  --color-bg-input: var(--color-bg-input-dark);
  --color-border: rgba(255, 255, 255, 0.12);

  --gradient-accent: linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%);
  --gradient-dark: linear-gradient(135deg, var(--dark-mid) 0%, var(--dark-light) 100%);

  --shadow-sm: 0 1px 2px rgba(0,0,0,0.35);
  --shadow-md: 0 2px 4px rgba(0,0,0,0.3), 0 8px 24px rgba(0,0,0,0.35);
  --shadow-lg: 0 4px 8px rgba(0,0,0,0.35), 0 16px 40px rgba(0,0,0,0.4);

  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 18px;

  --transition-fast: 0.15s ease;
  --transition-normal: 0.3s ease;

  /* Type system: signage display / standards-document body / equipment mono */
  --font-display: "Barlow Condensed", "Barlow Semi Condensed", "Arial Narrow", sans-serif;
  --font-body: "Atkinson Hyperlegible", "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;

  /* Bridge into Bootstrap 5.3 */
  --bs-body-font-family: var(--font-body);
  --bs-border-radius: var(--radius-sm);
  --bs-border-radius-lg: var(--radius-md);
}

/* --- Reading preferences (student-chosen, see /settings/) ---
   Set as data-font / data-textsize on <html> by the inline script in base.html.
   No attribute = the default type system above, so non-adopters see no change.
   --font-mono is deliberately never overridden: stat tiles, module codes and
   the test timer depend on its tabular figures lining up. */
[data-font="system"] {
  --font-display: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
[data-font="serif"] {
  --font-display: Georgia, "Iowan Old Style", "Times New Roman", serif;
  --font-body: Georgia, "Iowan Old Style", "Times New Roman", serif;
}
[data-font="hyper"] {
  --font-display: "Atkinson Hyperlegible", "Barlow Condensed", sans-serif;
  --font-body: "Atkinson Hyperlegible", "Public Sans", sans-serif;
}

/* Every font-size in this app is rem-based, so scaling the root scales the
   whole layout with it. */
[data-textsize="large"] { font-size: 112.5%; }
[data-textsize="larger"] { font-size: 125%; }

/* --- Reading spacing (student-chosen, see /settings/) ---
   Set as data-spacing on <html> beside data-font above. Line height, letter
   spacing and word spacing are the part of the dyslexia work with the
   strongest evidence behind it — stronger than any particular typeface.

   The three values are declared on :root first so the unset case is a genuine
   no-op: --read-lh resolves to the line-height Bootstrap already gives body,
   and letter/word spacing are already normal. --font-mono is never overridden
   here either, for the reason given above, and — the part a typeface swap did
   not have to worry about — the spacing is kept off everything that renders in
   it: tracking a column of tabular figures is what makes a running timer
   change width as it counts. */
:root {
  --read-lh: var(--bs-body-line-height, 1.5);
  --read-ls: normal;
  --read-ws: normal;
}
[data-spacing="comfortable"] {
  --read-lh: 1.75;
  --read-ls: 0.035em;
  --read-ws: 0.08em;
}
[data-spacing="wide"] {
  --read-lh: 2.0;
  --read-ls: 0.06em;
  --read-ws: 0.16em;
}

/* Body copy carries the rhythm; everything a student reads inherits it from
   here. Kept in this block rather than folded into the body rule further down,
   so the whole preference stays one unit to read, change or delete. */
body {
  line-height: var(--read-lh);
  letter-spacing: var(--read-ls);
  word-spacing: var(--read-ws);
}

/* The two long-form columns set a line-height of their own (1.7 and 1.75), so
   inheriting is not enough — the preference has to be pushed into them.
   Scoped to data-spacing so a student who set nothing still gets the column at
   exactly the measure it was designed at. */
[data-spacing] .prose,
[data-spacing] .reading-body {
  line-height: var(--read-lh);
}

/* What the rhythm must not reach: chrome, and anything on --font-mono. Letter
   spacing widens buttons and pills past the labels they were sized for, and
   destroys the tabular alignment the test timer, the module-code chip and the
   gradebook column heads depend on. Word spacing is listed with it because
   nothing else in this app declares it, so chrome would inherit it unopposed.

   :where() holds the rule at one-class specificity — the same trick, for the
   same reason, as the button-sheen block further down. The tracking a
   component sets for itself later in this file (.btn 0.01em, .badge 0.02em,
   0.12em on the uppercase mono labels) still wins; all this stops is the
   inherited value those elements would otherwise pick up from body.

   .form-control is deliberately narrowed to inputs rather than listed whole.
   The class is on 47 textareas in this app — short answers, discussion posts,
   scenario narratives — and those are long-form text the student writes and
   then re-reads. Stripping the spacing there would remove the preference from
   the writing surfaces it helps most, which is the opposite of what this block
   exists to protect. Single-line inputs still need it: they are sized to their
   content the way buttons are. The mono writing surface is handled separately
   by .nb-write below.

   It is spelled :where(input).form-control, not input.form-control, because
   :is() takes the specificity of its most specific argument — one id-less
   element+class would lift this whole list from (0,1,0) to (0,1,1) and start
   beating the component tracking the paragraph above promises still wins.
   :where() contributes nothing, so the list stays at exactly one class. */
:where([data-spacing]) :is(
    .slim-navbar, .shift-bar, .mobile-tabbar, .nav-link, .dropdown-item,
    .breadcrumb, .btn, .badge, .table, :where(input).form-control, .form-select,
    .stat-label, .stat-value, .stat-hero-value, .stat-link,
    .module-code, .section-count, .page-eyebrow, .hero-eyebrow, .fn-ref,
    .test-timer, .skill-timer, .drop-zone-label,
    .nb-caps, .nb-time, .nb-ring-pct, .nb-ring-v, .nb-bar-v, .nb-total-v,
    .nb-day-w, .nb-entry-v, .nb-kicker, .nb-write,
    code, kbd, pre, samp) {
  letter-spacing: normal;
  word-spacing: normal;
}

/* Line height is the one value allowed to carry into the rest of the page: it
   changes rhythm, not width. The three fixed bars are the exception, because
   every offset that clears them is a hard-coded pixel value (.shift-bar's
   top: 45px, .page-body's margin-top, the sticky table header's top: 56px), so
   a bar that grows with the text slides under the page instead of over it. */
:where([data-spacing]) :is(.slim-navbar, .shift-bar, .mobile-tabbar) {
  line-height: var(--bs-body-line-height, 1.5);
}

/* --- Light Theme Overrides --- */
[data-theme="light"] {
  --navy-dark: #F7F5F2;
  --navy-mid: #ffffff;
  --navy-light: #EDE8E1;

  /* #FFC107 is legible on dark but washes out as text on white — darken the
     amber for light mode (dots/fills below re-lighten where it's a background). */
  --color-warning-yellow: #8A5A00;
  --color-success-green: #1F7A5C;

  --color-text-primary: #16171A;
  --color-text-secondary: #4A4E55;
  --color-text-muted: rgba(22, 23, 26, 0.58);
  --color-text-dark: #16171A;

  --color-bg-body: #F7F5F2;
  --color-bg-card: #ffffff;
  --color-bg-card-header: var(--accent-subtle);
  --color-bg-input: #ffffff;
  --color-border: rgba(22, 35, 46, 0.12);

  --gradient-navy: linear-gradient(135deg, #eef1f4 0%, #e3e8ee 100%);

  --shadow-sm: 0 1px 2px rgba(16, 24, 32, 0.06);
  --shadow-md: 0 2px 4px rgba(16, 24, 32, 0.05), 0 8px 24px rgba(16, 24, 32, 0.08);
  --shadow-lg: 0 4px 8px rgba(16, 24, 32, 0.06), 0 16px 40px rgba(16, 24, 32, 0.1);
}

/* --- Dark Theme Re-base (2026-08 UI refresh) ---
   Surfaces are neutral charcoal instead of accent-tinted blacks; the level
   accent survives as the body::before glow and interactive states only.
   base.html always stamps data-theme, so this reliably wins over the
   accent-derived defaults above. */
[data-theme="dark"] {
  --dark-deepest: #16171A;
  --dark-mid: #1F2125;
  --dark-light: #2A2D33;
  --color-bg-body: #16171A;
  --color-bg-card: #1F2125;
  --color-bg-card-header: #2A2D33;
  --color-bg-input: #111215;
  --color-border: rgba(255, 255, 255, 0.10);
}

/* ============================================================
   BASE ELEMENTS
   ============================================================ */
body {
  background: var(--color-bg-body);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  transition: background var(--transition-normal), color var(--transition-normal);
}

a { color: var(--accent-light); }
a:hover { color: #ffffff; }
[data-theme="light"] a { color: var(--accent-dark); }
[data-theme="light"] a:hover { color: var(--accent-text); }

h1, h2, h3, h4, h5, h6 {
  color: var(--color-text-primary);
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
}
hr { border-color: var(--color-border); }

/* Big stat numbers read as signage */
.display-1, .display-2, .display-3, .display-4, .display-5, .display-6 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
}

.text-accent { color: var(--accent) !important; }
.text-secondary { color: var(--color-text-secondary) !important; }

/* Bootstrap's semantic text colors are tuned for dark backgrounds; on the light
   theme they drop below readable contrast. Re-point them at the themed vars. */
[data-theme="light"] .text-warning { color: var(--color-warning-yellow) !important; }
[data-theme="light"] .text-success { color: var(--color-success-green) !important; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* ============================================================
   NAVBAR — flat surface bar, quiet links, accent underline on
   the current page (2026-08 UI refresh; was a solid accent bar)
   ============================================================ */
.slim-navbar {
  background: var(--color-bg-card) !important;
  border-bottom: 1px solid var(--color-border);
  padding: 0.35rem 0;
  box-shadow: none;
  transition: background var(--transition-normal);
  z-index: 1030;
}

[data-theme="light"] .slim-navbar {
  background: rgba(255, 255, 255, 0.88) !important;
  border-bottom: 1px solid var(--color-border);
  box-shadow: none;
}

.slim-navbar .navbar-brand {
  background: none;
  padding: 0.2rem 0.5rem;
}

/* Logo follows the theme now that the bar is a neutral surface */
.logo-dark { display: inline; }
.logo-light { display: none; }
[data-theme="light"] .logo-dark { display: none; }
[data-theme="light"] .logo-light { display: inline; }

.slim-navbar .nav-link {
  color: var(--color-text-secondary) !important;
  background: transparent !important;
  border: none !important;
  border-radius: 8px !important;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: 0.35rem 0.9rem !important;
  transition: background var(--transition-fast), color var(--transition-fast);
  box-shadow: none;
  margin-right: 0.3rem;
  position: relative;
}
.slim-navbar .nav-link:hover {
  color: var(--color-text-primary) !important;
  background: var(--accent-tint) !important;
}
.slim-navbar .nav-link:active {
  background: var(--accent-tint) !important;
}
/* Current page: accent underline (class set by a tiny script in base.html) */
.slim-navbar .nav-link.nav-current {
  color: var(--color-text-primary) !important;
}
.slim-navbar .nav-link.nav-current::after {
  content: "";
  position: absolute;
  left: 0.9rem;
  right: 0.9rem;
  bottom: -1px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
}

.slim-navbar .navbar-text {
  color: var(--color-text-secondary) !important;
  font-size: 0.85rem;
}

/* Logout button: quiet outline chip */
.slim-navbar .nav-logout-btn {
  color: var(--color-text-secondary) !important;
  background: transparent !important;
  border: 1px solid var(--color-border) !important;
  border-radius: 999px !important;
  padding: 0.3rem 1rem !important;
  font-weight: 600;
  letter-spacing: 0.01em;
  transition: background var(--transition-fast), border-color var(--transition-fast),
              color var(--transition-fast);
  box-shadow: none;
}
.slim-navbar .nav-logout-btn:hover {
  color: var(--color-text-primary) !important;
  border-color: var(--accent) !important;
  background: var(--accent-tint) !important;
}

/* Solid primary buttons keep normal accent styling on the neutral bar */
.slim-navbar .btn-primary { border-radius: 999px; }

/* Log In (logged-out navbar): neutral outline that warms on hover */
.slim-navbar .btn-outline-light {
  color: var(--color-text-secondary);
  border-color: var(--color-border);
  border-radius: 999px;
}
.slim-navbar .btn-outline-light:hover {
  background: var(--accent-tint);
  border-color: var(--accent);
  color: var(--color-text-primary);
}

.slim-navbar .navbar-toggler {
  border-color: var(--color-border);
}

/* Level select on the surface bar */
.slim-navbar .form-select {
  background-color: var(--color-bg-input) !important;
  border-color: var(--color-border) !important;
  color: var(--color-text-primary) !important;
}
.slim-navbar .form-select:focus {
  box-shadow: 0 0 0 0.2rem var(--accent-focus) !important;
}

/* ============================================================
   THEME TOGGLE BUTTON
   ============================================================ */
#themeToggle {
  background: transparent;
  border: 1px solid var(--color-border);
  color: var(--color-text-secondary);
  padding: 0.2rem 0.5rem;
  border-radius: 999px;
  cursor: pointer;
  transition: all 0.2s ease;
  font-size: 0.9rem;
  line-height: 1;
}
#themeToggle:hover {
  background: var(--accent-tint);
  border-color: var(--accent);
  color: var(--color-text-primary);
}

/* ============================================================
   CARDS
   ============================================================ */
.card {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  color: var(--color-text-primary);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  transition: background var(--transition-normal), border-color var(--transition-normal);
}

.card.border-accent {
  border: 2px solid var(--accent);
}

.card-header {
  background: var(--color-bg-card-header);
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text-primary);
  border-top-left-radius: var(--radius-md) !important;
  border-top-right-radius: var(--radius-md) !important;
}

.card-body { color: var(--color-text-primary); }

.card-title { font-family: var(--font-display); font-weight: 600; letter-spacing: 0; }

/* Module cards: section-colored left rail, lift on hover.
   Light selector included: the [data-theme="light"] .card shorthand border
   below would otherwise reset border-left. */
.module-card-wrap .card,
[data-theme="light"] .module-card-wrap .card {
  border-left: 3px solid var(--sec, var(--accent));
  transition: transform var(--transition-fast), box-shadow var(--transition-fast),
              border-color var(--transition-fast);
}
.module-card-wrap .card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-left-color: var(--sec, var(--accent));
}

/* Generic card hover lift (activity grids etc.) */
.row.g-4 > div > .card {
  transition: transform var(--transition-fast), box-shadow var(--transition-fast),
              background var(--transition-normal), border-color var(--transition-fast);
}
.row.g-4 > div > .card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

[data-theme="light"] .card {
  background: #ffffff;
  border: 1px solid var(--color-border);
  color: #16232e;
  box-shadow: var(--shadow-sm);
}
[data-theme="light"] .card-header {
  background: var(--accent-subtle);
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  color: #16232e;
}
[data-theme="light"] .card-body { color: #16232e; }

/* ============================================================
   SECTION HEADERS — protocol-book index tabs
   ============================================================ */
.module-section h4 {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 1rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-secondary);
  border-left: 3px solid var(--sec, var(--accent));
  padding-left: 0.75rem;
}
.module-section h4 .bi { color: var(--sec, var(--accent)); }

/* Section color coding: each curriculum section carries its own hue for
   wayfinding (data-sec index set in _modules_dashboard.html). Hues chosen
   mid-tone so they read on both themes. */
.module-section { --sec: var(--accent); }
.module-section[data-sec="1"] { --sec: #B45309; }
.module-section[data-sec="2"] { --sec: #2E7D32; }
.module-section[data-sec="3"] { --sec: #0694A2; }
.module-section[data-sec="4"] { --sec: #185FA5; }
.module-section[data-sec="5"] { --sec: #7C3AED; }
.module-section[data-sec="6"] { --sec: #BE185D; }
.module-section[data-sec="7"] { --sec: #4D7C0F; }
.module-section h4::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--color-border);
  margin-left: 0.75rem;
}

/* ============================================================
   BUTTONS
   ============================================================ */
.btn {
  font-weight: 600;
  letter-spacing: 0.01em;
  border-radius: 8px;
}

.btn-primary,
[data-theme="light"] .btn-primary {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
  color: #fff !important;
}
.btn-primary:hover,
[data-theme="light"] .btn-primary:hover {
  background: var(--accent-dark) !important;
  border-color: var(--accent-dark) !important;
  color: #fff !important;
}

.btn-outline-primary,
[data-theme="light"] .btn-outline-primary {
  color: var(--accent);
  border-color: var(--accent);
  background: transparent;
}
.btn-outline-primary:hover,
[data-theme="light"] .btn-outline-primary:hover {
  background: var(--accent);
  color: #fff;
}

/* Accent discipline (2026-08 UI refresh): buttons inside cards stay quiet so
   red can mean "this is THE action". Full accent returns on hover. */
.card .btn-primary,
[data-theme="light"] .card .btn-primary {
  background: var(--accent-tint) !important;
  border-color: transparent !important;
  color: var(--accent) !important;
}
[data-theme="light"] .card .btn-primary { color: var(--accent-dark) !important; }
.card .btn-primary:hover,
[data-theme="light"] .card .btn-primary:hover {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
  color: #fff !important;
}
.card .btn-outline-primary,
[data-theme="light"] .card .btn-outline-primary {
  color: var(--color-text-secondary);
  border-color: var(--color-border);
}
.card .btn-outline-primary:hover,
[data-theme="light"] .card .btn-outline-primary:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.btn-outline-secondary {
  border-color: var(--color-border);
  color: var(--color-text-secondary);
}
/* Neutral at rest, level accent on hover — same promise as .card
   .btn-outline-primary: color means "you are about to press this". */
.btn-outline-secondary:hover {
  background: var(--accent-tint);
  color: var(--accent);
  border-color: var(--accent);
}
[data-theme="light"] .btn-outline-secondary {
  border-color: rgba(0, 0, 0, 0.2);
  color: #46586a;
}
[data-theme="light"] .btn-outline-secondary:hover {
  background: var(--accent-tint);
  color: var(--accent-dark);
  border-color: var(--accent);
}

/* Bootstrap's warning and info outlines are yellow and cyan text on white —
   1.4:1 and 1.7:1, unreadable. Light mode darkens the text (Bootstrap's
   warning text-emphasis, and cyan-700) and the border; hover still fills with
   the bright color. Measured after: 7+ and 4.5+ on the page background. */
[data-theme="light"] .btn-outline-warning {
  --bs-btn-color: #664d03;
  --bs-btn-border-color: #cc9a06;
}
[data-theme="light"] .btn-outline-info {
  --bs-btn-color: #087990;
  --bs-btn-border-color: #0aa2c0;
}

/* Toggle buttons (btn-check) — read as physically pushed in when active */
.btn-toggle {
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  transition: all var(--transition-fast);
}
.btn-check:checked + .btn-toggle {
  background: var(--accent-tint) !important;
  border-color: var(--accent) !important;
  color: var(--accent) !important;
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.35);
  transform: translateY(1px);
}
[data-theme="light"] .btn-check:checked + .btn-toggle {
  background: var(--accent-subtle) !important;
  color: var(--accent-dark) !important;
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.15);
}
.btn-check:focus-visible + .btn-toggle {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ============================================================
   FORMS & INPUTS
   ============================================================ */
.form-control, .form-select {
  background: var(--color-bg-input);
  border: 1px solid var(--color-border);
  color: var(--color-text-primary);
  border-radius: 8px;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.form-control:focus, .form-select:focus {
  background: var(--color-bg-input);
  border-color: var(--accent);
  color: var(--color-text-primary);
  box-shadow: 0 0 0 0.2rem var(--accent-focus);
}
.form-control::placeholder { color: var(--color-text-muted); }

[data-theme="light"] .form-control,
[data-theme="light"] .form-select {
  background: #ffffff;
  border: 1px solid rgba(22, 35, 46, 0.15);
  color: #16232e;
}
[data-theme="light"] .form-control:focus,
[data-theme="light"] .form-select:focus {
  background: #ffffff;
  border-color: var(--accent);
  color: #16232e;
  box-shadow: 0 0 0 0.2rem var(--accent-focus);
}
[data-theme="light"] .form-control::placeholder {
  color: rgba(22, 35, 46, 0.4);
}

/* ============================================================
   LIST GROUPS
   ============================================================ */
.list-group-item {
  background: var(--color-bg-card);
  border-color: var(--color-border);
  color: var(--color-text-primary);
}
.list-group-item:hover {
  background: var(--dark-mid);
}

[data-theme="light"] .list-group-item {
  background: #ffffff;
  border-color: rgba(22, 35, 46, 0.08);
  color: #16232e;
}
[data-theme="light"] .list-group-item:hover {
  background: var(--accent-tint-light);
}

/* ============================================================
   BADGES
   ============================================================ */
/* Badges read as stencilled equipment tags, not capsules: mono caps, a
   short rule down the left in the tag's own colour, a whisper of tint
   behind. Bootstrap's coloured variants (.bg-*, .text-bg-*) are remapped
   the same way, so the 100-odd badges in the templates change together
   and colour stays a hint under a legible label (2026-09 Ember look). */
.badge {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: max(0.68em, 0.72rem);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border-radius: 3px;
  padding: 0.32em 0.6em 0.28em 0.55em;
  border-left: 3px solid currentColor;
  line-height: 1.2;
  vertical-align: middle;
}
.badge.bg-secondary, .badge.text-bg-secondary {
  background: rgba(255, 255, 255, 0.07) !important;
  color: var(--color-text-secondary) !important;
}
.badge.bg-success, .badge.text-bg-success {
  background: rgba(62, 207, 154, 0.14) !important;
  color: var(--color-success-green) !important;
}
.badge.bg-warning, .badge.text-bg-warning, .badge.bg-warning-subtle {
  background: rgba(255, 181, 71, 0.14) !important;
  color: var(--color-warning-yellow) !important;
}
.badge.bg-danger, .badge.text-bg-danger {
  background: rgba(239, 68, 68, 0.14) !important;
  color: #FF7B6B !important;
}
.badge.bg-info, .badge.text-bg-info {
  background: rgba(77, 163, 255, 0.14) !important;
  color: var(--color-info-blue) !important;
}
.badge.bg-primary, .badge.text-bg-primary {
  background: var(--accent-tint) !important;
  color: var(--accent-light) !important;
}
[data-theme="light"] .badge.bg-secondary, [data-theme="light"] .badge.text-bg-secondary {
  background: rgba(22, 23, 26, 0.06) !important;
  color: var(--color-text-secondary) !important;
}
[data-theme="light"] .badge.bg-danger, [data-theme="light"] .badge.text-bg-danger {
  color: #B3261E !important;
}
[data-theme="light"] .badge.bg-info, [data-theme="light"] .badge.text-bg-info {
  color: #1A4FB3 !important;
}
[data-theme="light"] .badge.bg-primary, [data-theme="light"] .badge.text-bg-primary {
  color: var(--accent-dark) !important;
}

/* ============================================================
   BREADCRUMBS
   ============================================================ */
.breadcrumb-item.active { color: var(--color-text-muted); }
.breadcrumb-item + .breadcrumb-item::before { color: var(--color-text-muted); }

[data-theme="light"] .breadcrumb-item.active { color: rgba(22, 35, 46, 0.5); }

/* ============================================================
   PROGRESS BAR
   ============================================================ */
.progress {
  background: var(--dark-mid);
  border-radius: 999px;
}
[data-theme="light"] .progress {
  background: #e3e8ee;
}
.progress-bar {
  background: linear-gradient(90deg, var(--accent-dark), var(--accent)) !important;
  border-radius: 999px;
  box-shadow: 0 0 8px var(--accent-focus);
  transition: width 0.3s;
}
.progress-bar.bg-success {
  background: linear-gradient(90deg, #0d9668, var(--color-success-green)) !important;
  box-shadow: 0 0 8px rgba(16, 185, 129, 0.35);
}

/* ============================================================
   APP FEEL — view transitions, press feedback, toasts
   ============================================================ */

/* Cross-fade between page loads (MPA View Transitions; no-op where unsupported) */
@view-transition {
  navigation: auto;
}
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.75s;
}
@media (prefers-reduced-motion: reduce) {
  @view-transition {
    navigation: none;
  }
}

/* Buttons + nav chips compress on press */
.btn,
.slim-navbar .nav-link {
  transition: transform 0.08s ease, background var(--transition-fast),
              border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.btn:active,
.slim-navbar .nav-link:active {
  transform: scale(0.96);
}

/* Every button answers the pointer: it lifts, and a sheen sweeps across once.
   hover:hover keeps phones from sticking in the hover look after a tap; the
   reduced-motion rule near the top of this file flattens the motion. btn-link
   stays a link. :where() gives position/overflow zero specificity, so any
   positioning class (position-fixed on the flag launcher) still wins. The
   Google and Apple sign-in buttons are brand-styled links, not .btn, and
   join in by name. */
@media (hover: hover) {
  :where(.btn:not(.btn-link), .google-signin-btn, .apple-signin-btn) {
    position: relative;
    overflow: hidden;
  }
  :where(.btn:not(.btn-link), .google-signin-btn, .apple-signin-btn)::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(110deg, transparent 30%, rgba(255, 255, 255, 0.35) 50%, transparent 70%);
    transform: translateX(-120%);
  }
  .btn:not(.btn-link):not(:disabled):not(.disabled):hover,
  .google-signin-btn:hover,
  .apple-signin-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
  }
  .btn:not(.btn-link):not(:disabled):not(.disabled):hover::before,
  .google-signin-btn:hover::before,
  .apple-signin-btn:hover::before {
    transform: translateX(120%);
    transition: transform 0.6s ease;
  }
  /* Same specificity as the hover rule, declared after it, so a press still
     compresses instead of staying lifted. */
  .btn:not(.btn-link):not(:disabled):not(.disabled):active,
  .google-signin-btn:active,
  .apple-signin-btn:active {
    transform: scale(0.96);
  }
}

/* "Extra games and practice" under the overall grade. The card rules above
   quiet every accent button inside a card on purpose; this one is the
   exception, because it is the thing to reach for when the grade is
   disappointing. It is built from the level accent, so it is red in an EMT
   class, green in AEMT and blue in Paramedic without a per-level rule. The
   lift and sheen come from the hover block above; only the shadow is
   restated here, at the same specificity, so the accent glow deepens
   instead of being swapped for the generic grey one. */
.btn-games,
.card .btn-games,
[data-theme="light"] .card .btn-games {
  color: #fff;
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: 0.6rem 1rem;
  border: 0;
  background: linear-gradient(160deg, var(--accent-light) -40%, var(--accent) 45%, var(--accent-dark) 100%);
  box-shadow: 0 2px 0 var(--accent-text),
              0 6px 16px var(--accent-focus),
              inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
.btn-games:hover,
.btn-games:focus-visible,
.card .btn-games:hover,
[data-theme="light"] .btn-games:hover,
[data-theme="light"] .card .btn-games:hover {
  color: #fff;
  background: linear-gradient(160deg, var(--accent-light) -30%, var(--accent) 40%, var(--accent-dark) 100%);
}
.btn-games:not(.btn-link):not(:disabled):not(.disabled):hover {
  transform: translateY(-2px);
  box-shadow: 0 3px 0 var(--accent-text),
              0 10px 24px var(--accent-focus),
              inset 0 1px 0 rgba(255, 255, 255, 0.45);
}

/* Toasts — app-style notifications, bottom right */
.app-toast {
  background: var(--color-bg-card);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-info-blue);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  backdrop-filter: blur(8px);
}
.app-toast .toast-body { font-weight: 500; }
.app-toast .bi { color: var(--color-info-blue); }
.app-toast-success { border-left-color: var(--color-success-green); }
.app-toast-success .bi { color: var(--color-success-green); }
.app-toast-warning { border-left-color: var(--color-warning-yellow); }
.app-toast-warning .bi { color: var(--color-warning-yellow); }
.app-toast-error, .app-toast-danger { border-left-color: var(--color-danger-red); }
.app-toast-error .bi, .app-toast-danger .bi { color: var(--color-danger-red); }
[data-theme="light"] .app-toast { background: #ffffff; }

/* Navbar avatar chip */
.nav-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent-tint);
  border: 1px solid var(--accent-focus);
  color: var(--accent);
  display: inline-grid;
  place-items: center;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  user-select: none;
}

/* Mobile bottom tab bar */
.mobile-tabbar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1030;
  display: flex;
  background: var(--color-bg-card);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--color-border);
}
[data-theme="light"] .mobile-tabbar { background: rgba(255,255,255,0.92); }
.mobile-tabbar .tab-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 0.5rem 0 calc(0.5rem + env(safe-area-inset-bottom));
  color: var(--color-text-muted);
  font-size: 0.65rem;
  font-weight: 600;
  text-decoration: none;
}
.mobile-tabbar .tab-item .bi { font-size: 1.25rem; line-height: 1; }
.mobile-tabbar .tab-item.active,
.mobile-tabbar .tab-item:hover { color: var(--accent); }
[data-theme="light"] .mobile-tabbar .tab-item.active { color: var(--accent-dark); }
@media (max-width: 767.98px) {
  /* rem, not px: the tabbar's own height is rem-based, so a fixed value here
     lets the bar cover content once a student picks a larger text size. */
  body { padding-bottom: 4.5rem; }
}

/* Command palette */
.cmdk-overlay {
  position: fixed;
  inset: 0;
  z-index: 1090;
  background: rgba(0,0,0,0.5);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding-top: 14vh;
}
.cmdk-panel {
  width: min(560px, 92vw);
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
[data-theme="light"] .cmdk-panel { background: #ffffff; }
.cmdk-input {
  width: 100%;
  border: none;
  outline: none;
  background: transparent;
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: 1rem;
  padding: 0.9rem 1.1rem;
  border-bottom: 1px solid var(--color-border);
}
.cmdk-input::placeholder { color: var(--color-text-muted); }
.cmdk-list { max-height: 46vh; overflow-y: auto; padding: 0.4rem; }
.cmdk-item {
  padding: 0.55rem 0.8rem;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.92rem;
  color: var(--color-text-secondary);
}
.cmdk-item.active {
  background: var(--accent-tint);
  color: var(--color-text-primary);
}
.cmdk-list:empty::after {
  content: "No matches";
  display: block;
  padding: 0.8rem;
  color: var(--color-text-muted);
  font-size: 0.85rem;
}

/* Skeleton shimmer placeholders */
.skeleton {
  position: relative;
  overflow: hidden;
  background: rgba(128,128,128,0.15);
  border-radius: 8px;
}
.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.08), transparent);
  animation: shimmer 1.2s infinite;
}
[data-theme="light"] .skeleton::after {
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.7), transparent);
}
@keyframes shimmer {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

/* Streak pill */
.streak-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.3rem 0.8rem;
  border-radius: 999px;
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
}
[data-theme="light"] .streak-pill { background: #ffffff; }
.streak-pill .bi-fire {
  color: #ff9f1c;
  animation: flicker 1.6s ease-in-out infinite;
}
.streak-dot {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--color-warning-yellow);
}
/* As a filled shape (not text) the bright amber still reads well on white. */
[data-theme="light"] .streak-dot { background: #f0a202; }
.streak-label {
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  margin-left: 0.25rem;
}
@keyframes flicker {
  0%, 100% { transform: scale(1); opacity: 1; }
  50%      { transform: scale(1.15); opacity: 0.8; }
}

/* Locked module cards: frosted content, lock overlay, footer stays usable */
.card-locked { position: relative; overflow: hidden; }
.card-locked .card-body { filter: blur(3px); opacity: 0.6; pointer-events: none; }
.lock-overlay {
  position: absolute;
  inset: 0 0 3rem 0;
  display: grid;
  place-items: center;
  z-index: 2;
  font-size: 1.5rem;
  color: var(--color-text-secondary);
  pointer-events: none;
}

/* Completion bar slices pop in left-to-right */
@keyframes sliceIn {
  from { transform: scaleY(0); opacity: 0; }
}

/* Completion bar celebration pulse */
.bar-celebrate { animation: goldPulse 1.2s ease-in-out 3; }
@keyframes goldPulse {
  0%, 100% { box-shadow: 0 0 0 2px #ffd24a, 0 0 12px rgba(255,210,74,0.6); }
  50%      { box-shadow: 0 0 0 3px #ffd24a, 0 0 26px rgba(255,210,74,0.95); }
}

/* ============================================================
   AMBIENT — faint accent glow at top of every page
   ============================================================ */
body::before {
  content: "";
  position: fixed;
  inset: 0 0 auto 0;
  height: 420px;
  background: radial-gradient(60% 100% at 50% 0%, var(--accent-tint), transparent 70%);
  pointer-events: none;
  z-index: -1;
}

/* ============================================================
   GLASSY NAVBAR — content scrolls under a blurred surface bar
   ============================================================ */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .slim-navbar {
    background: color-mix(in srgb, var(--color-bg-card) 85%, transparent) !important;
    -webkit-backdrop-filter: blur(10px) saturate(1.5);
    backdrop-filter: blur(10px) saturate(1.5);
  }
  [data-theme="light"] .slim-navbar {
    background: rgba(255, 255, 255, 0.82) !important;
  }
}

/* ============================================================
   CARD ENTRANCE — subtle staggered rise on load
   (prefers-reduced-motion rule above collapses this to instant)
   ============================================================ */
@keyframes cardRise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
#grade-dashboard .card,
.module-card-wrap .card {
  animation: cardRise 0.4s ease backwards;
}
.module-card-wrap:nth-child(1) .card { animation-delay: 0.04s; }
.module-card-wrap:nth-child(2) .card { animation-delay: 0.08s; }
.module-card-wrap:nth-child(3) .card { animation-delay: 0.12s; }
.module-card-wrap:nth-child(4) .card { animation-delay: 0.16s; }
.module-card-wrap:nth-child(5) .card { animation-delay: 0.20s; }
.module-card-wrap:nth-child(6) .card { animation-delay: 0.24s; }

/* ============================================================
   STAT BAND — bento dashboard header
   ============================================================ */
.stat-label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--color-text-muted);
  margin-bottom: 0.25rem;
}
.stat-hero-value {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 3.75rem;
  line-height: 1;
  letter-spacing: -0.02em;
}
.stat-grid {
  /* Same auto-fit/minmax tile-grid pattern used elsewhere in this project
     (.rev-tiles, settings.html, mistakes/host.html, adventure/board.html):
     columns are however many fit at minmax(140px, 1fr), not a fixed count,
     so the tile count (4 today, 5 now) doesn't dictate a hardcoded column
     number that stops matching the actual number of tiles. */
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1rem 1.5rem;
}
.stat-value {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.6rem;
  line-height: 1.1;
}
.stat-cell.stat-soon { opacity: 0.5; }
.stat-link {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  margin-top: 0.4rem;
  text-decoration: none;
}

/* Mute zero-state hero number until data exists */
.stat-hero-value.text-secondary { opacity: 0.45; }

/* Half-width hero: the grade card gives up half its column to the online
   lecture card, and "100.0%" at 3.75rem does not fit what is left. 2.5rem
   fit it to the pixel with nothing spare, so this is a size down from that --
   a 100% student is exactly who should not see their grade clipped. */
.stat-hero-value--half { font-size: 2.25rem; }

/* ============================================================
   ACTIVITY ICON TILES — glyphs sit in tinted rounded squares
   ============================================================ */
.activity-icon {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 10px;
  background: var(--accent-tint);
  border: 1px solid var(--accent-focus);
}
.activity-icon .bi {
  font-size: 1.25rem;
  color: var(--accent);
  line-height: 1;
}
[data-theme="light"] .activity-icon {
  background: var(--accent-subtle);
  border-color: var(--accent-focus);
}
[data-theme="light"] .activity-icon .bi { color: var(--accent-dark); }

/* Completed activity: tile goes success-green */
.activity-icon-done {
  background: rgba(16, 185, 129, 0.14);
  border-color: rgba(16, 185, 129, 0.4);
}
.activity-icon-done .bi,
[data-theme="light"] .activity-icon-done .bi {
  color: var(--color-success-green);
}
[data-theme="light"] .activity-icon-done {
  background: rgba(16, 185, 129, 0.1);
  border-color: rgba(16, 185, 129, 0.35);
}

/* ============================================================
   MODULE CARDS v2 — mono code chip + completion ring
   ============================================================ */
.module-code {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--accent);
  background: var(--accent-tint);
  border: 0;
  border-left: 3px solid var(--accent);
  border-radius: 3px;
  padding: 0.18rem 0.5rem 0.15rem 0.45rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space: nowrap;
}
.progress-ring {
  --p: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: conic-gradient(var(--accent) calc(var(--p) * 1%), var(--dark-mid) 0);
  display: grid;
  place-items: center;
  flex: 0 0 auto;
}
.progress-ring::before {
  content: "";
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--dark-mid);
}
[data-theme="light"] .progress-ring {
  background: conic-gradient(var(--accent) calc(var(--p) * 1%), #e3e8ee 0);
}
[data-theme="light"] .progress-ring::before { background: #ffffff; }

/* Section header pass-count sits after the rule line */
.module-section h4::after { order: 1; }
.module-section h4 .section-count {
  order: 2;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  text-transform: none;
}

/* ============================================================
   LANDING HERO (2026-09 Ember look) — the mark as a watermark, the
   classroom on a laptop with the app on a phone in front, on a panel that
   follows the theme: charcoal at night, ash by day. Two columns from
   768px. The devices are photographic frames (static/img/*-frame-*.png,
   keyed to transparency with the screens cut out); the screenshots sit
   behind the openings at measured positions.
   ============================================================ */
.hero {
  position: relative;
  padding: 4rem 0 0;
  isolation: isolate;
  --sign-ink: #F4F2EF;
  --sign-muted: #C9C6C1;
  --sign-red: #FF6A4D;
  --sign-bg-a: #16171A;
  --sign-bg-b: #1B1D21;
  --sign-glow: rgba(200, 50, 31, 0.28);
  --sign-rule: rgba(244, 242, 239, 0.2);
  --sign-tag-bg: rgba(255, 255, 255, 0.06);
  --sign-outline: rgba(244, 242, 239, 0.45);
  --sign-outline-hover: rgba(244, 242, 239, 0.1);
  --sign-grain: 0.35;
  color: var(--sign-ink);
}
[data-theme="light"] .hero {
  --sign-ink: #16171A;
  --sign-muted: #4A4E55;
  --sign-red: #B92D1C;
  --sign-bg-a: #F7F5F2;
  --sign-bg-b: #F1EEEA;
  --sign-glow: rgba(200, 50, 31, 0.16);
  --sign-rule: rgba(22, 23, 26, 0.18);
  --sign-tag-bg: rgba(22, 23, 26, 0.06);
  --sign-outline: rgba(22, 23, 26, 0.4);
  --sign-outline-hover: rgba(22, 23, 26, 0.06);
  --sign-grain: 0.55;
}
.hero .text-secondary { color: var(--sign-muted) !important; }
/* The full-bleed panel and the devices' off-screen start must not hand the
   landing page a sideways scrollbar. Clip is not a scroll container, so
   nothing else about the page changes; scoped to pages that have a hero. */
body:has(.hero) { overflow-x: clip; }
/* Grain + a warm glow behind the devices. The noise is an inline SVG so it
   costs no request; opacity keeps it a texture, never a pattern. */
.hero::before {
  content: "";
  position: absolute;
  inset: -3rem -50vw 0 -50vw;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(55% 60% at 72% 40%, var(--sign-glow) 0%, transparent 70%),
    linear-gradient(180deg, var(--sign-bg-a) 0%, var(--sign-bg-b) 100%),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.5 0 0 0 0 0.5 0 0 0 0 0.5 0 0 0 0.35 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-blend-mode: normal, normal, soft-light;
}
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(300px, 1.05fr);
  gap: 2rem 2.5rem;
  align-items: center;
}
@media (max-width: 767.98px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); }
  /* Stacked: the stage sizes itself from the laptop, the phone tucks into the corner.
     These selectors outrank the desktop rules below, which come later in the file. */
  .hero-grid .hero-copy, .hero-grid .hero-stage { min-width: 0; }
  .hero-grid .hero-stage { min-height: 0; aspect-ratio: 1 / 0.86; margin-top: 1rem; }
  .hero-stage .hero-laptop-wrap { right: 0; width: 94%; }
  .hero-stage .hero-phone-wrap { left: 0; bottom: 0; width: 28%; }
}
.hero-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--sign-red);
  margin-bottom: 1rem;
}
.hero-eyebrow::before {
  content: "";
  width: 2rem;
  height: 3px;
  background: var(--sign-red);
  border-radius: 2px;
}
.hero .hero-title,
[data-theme="light"] .hero .hero-title {
  color: var(--sign-ink);
}
.hero-title {
  font-size: clamp(2.75rem, 6.5vw, 5rem);
  line-height: 0.98;
  letter-spacing: -0.015em;
  margin-bottom: 1rem;
}
.hero-lead {
  font-size: 1.1rem;
  max-width: 520px;
  line-height: 1.55;
}
/* The four promises in the lead, as the same stencil tags used everywhere. */
.hero-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.25rem;
}
.hero-tags .badge,
[data-theme="light"] .hero-tags .badge {
  font-size: 0.72rem;
  color: var(--sign-muted) !important;
  background: var(--sign-tag-bg) !important;
}
.hero .btn-outline-primary {
  color: var(--sign-ink);
  border-color: var(--sign-outline);
}
.hero .btn-outline-primary:hover {
  background: var(--sign-outline-hover);
  color: var(--sign-ink);
  border-color: var(--sign-ink);
}
.hero-actions {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 1.75rem;
}
/* Course offers under the hero as a quiet ticket row: label on the left,
   prices in mono, the whole line still a real buy button. */
.hero-offers {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  margin-top: 1.75rem;
  padding-top: 1rem;
  border-top: 1px dashed var(--sign-rule);
}
.hero-offers-label {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sign-muted);
  opacity: 0.8;
  margin-right: 0.25rem;
}
.offer-link {
  background: none;
  border: 0;
  padding: 0.25rem 0;
  color: var(--sign-muted);
  font-weight: 600;
  font-size: 0.95rem;
  border-bottom: 2px solid transparent;
  transition: color var(--transition-fast), border-color var(--transition-fast);
}
.offer-link:hover { color: var(--sign-ink); border-bottom-color: var(--sign-red); }
.offer-price {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--sign-red);
  margin-left: 0.35rem;
}

/* --- The stage: watermark, laptop, phone ------------------------------ */
.hero-stage {
  position: relative;
  min-height: 440px;
  perspective: 1400px;
}
/* The mark as a watermark: flame in Ember, letters in the panel's ink. */
.hero-mark {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  opacity: 0.34;
  transform: translate(-46%, -16%) scale(1.15);
  pointer-events: none;
}
.hero-mark-two-tone {
  position: relative;
  height: clamp(240px, 28vw, 360px);
  aspect-ratio: 146 / 239;
}
.hero-mark-two-tone span {
  position: absolute;
  inset: 0;
  -webkit-mask: url("../img/logo_white.f1974dfdff4a.svg") center / contain no-repeat;
  mask: url("../img/logo_white.f1974dfdff4a.svg") center / contain no-repeat;
}
.hero-mark-two-tone .mark-flame { background: var(--accent); clip-path: inset(0 0 53.5% 0); }
.hero-mark-two-tone .mark-ink { background: var(--sign-ink); clip-path: inset(46.5% 0 0 0); }

/* Theme picks one frame set; the other is not in layout at all. */
.hero-device-light { display: none !important; }
[data-theme="light"] .hero-device-dark { display: none !important; }
[data-theme="light"] .hero-device-light { display: block !important; }

/* A device: a frame photograph on top (z 2) and a screen layer positioned
   in its opening. Screens clip their picture; the picture is aligned top
   so a slightly-off aspect trims the bottom, never the header. */
.hero-device { position: relative; }
.hero-device-frame {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: 2; pointer-events: none; user-select: none;
}
.hero-device-screen {
  position: absolute; overflow: hidden; background: #16171A;
}
[data-theme="light"] .hero-device-screen { background: #F7F5F2; }
.hero-device-screen img {
  display: block; width: 100%; height: 100%; object-fit: cover; object-position: top;
}

/* Laptop: the classroom website, sitting right and a little high. */
.hero-laptop-wrap {
  position: absolute;
  right: -4%;
  top: 0;
  width: 100%;
  will-change: transform, opacity;
  animation: hero-laptop-in 1s cubic-bezier(0.16, 1, 0.3, 1) 0.15s both;
  filter: drop-shadow(0 30px 40px rgba(0, 0, 0, 0.45));
}
[data-theme="light"] .hero-laptop-wrap { filter: drop-shadow(0 24px 36px rgba(22, 23, 26, 0.28)); }
.hero-laptop.hero-device-dark { aspect-ratio: 1461 / 1114; }
.hero-laptop.hero-device-dark .hero-device-screen { left: 10.61%; top: 2.42%; width: 78.78%; height: 71.1%; border-radius: 0.6% / 0.9%; }
.hero-laptop.hero-device-light { aspect-ratio: 1600 / 1116; }
.hero-laptop.hero-device-light .hero-device-screen { left: 10.75%; top: 2.51%; width: 78.5%; height: 75.09%; border-radius: 0.6% / 0.9%; }
@keyframes hero-laptop-in {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* The frame is one photograph, split at the hinge into a base and a lid so the
   lid can swing open. Both layers fill the device box; clip-path decides which
   half each shows, and the lid pivots on the hinge line. */
.hero-laptop { perspective: 1600px; }
.hero-laptop-base, .hero-laptop-lid { position: absolute; inset: 0; }
.hero-laptop-lid {
  transform-origin: 50% var(--hinge);
  will-change: transform;
  animation: hero-lid-open 1.5s cubic-bezier(0.22, 0.9, 0.25, 1) 0.45s both;
}
.hero-laptop-lid .hero-device-frame { clip-path: inset(0 0 calc(100% - var(--hinge)) 0); }
.hero-laptop-base .hero-device-frame { clip-path: inset(var(--hinge) 0 0 0); }
.hero-laptop.hero-device-dark { --hinge: 77.8%; }
.hero-laptop.hero-device-light { --hinge: 81.8%; }
@keyframes hero-lid-open {
  from { transform: rotateX(-84deg); }
  to   { transform: rotateX(0deg); }
}
/* The screen wakes as the lid comes up. */
.hero-laptop .hero-device-screen img {
  opacity: 0;
  animation: hero-wake 0.6s ease-out 1.25s both;
}
@keyframes hero-wake { to { opacity: 1; } }

/* Phone: the app, in front, bottom left, arriving from off-screen right. */
.hero-phone-wrap {
  position: absolute;
  left: 3%;
  bottom: -2%;
  width: 25%;
  will-change: transform, opacity;
  animation: hero-phone-in 1.1s cubic-bezier(0.16, 1, 0.3, 1) 1.5s both;
}
@keyframes hero-phone-in {
  from { opacity: 0; transform: translate3d(64px, 20px, 0) rotate(3deg); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotate(0deg); }
}
.hero-phone {
  transform: rotate(-5deg) translateZ(0);
  will-change: transform;
  animation: hero-float 8s ease-in-out 3.2s infinite;
  filter: drop-shadow(0 26px 34px rgba(0, 0, 0, 0.5)) drop-shadow(0 0 50px var(--sign-glow));
}
.hero-phone.hero-device-dark { aspect-ratio: 893 / 1903; }
.hero-phone.hero-device-dark .hero-device-screen { left: 4.9%; top: 2.0%; width: 90.4%; height: 96.1%; border-radius: 15.3% / 6.75%; }
.hero-phone.hero-device-light { aspect-ratio: 884 / 1859; }
.hero-phone.hero-device-light .hero-device-screen { left: 4.95%; top: 2.0%; width: 90.1%; height: 96.1%; border-radius: 13.9% / 6.2%; }
/* Light sweep: a soft, narrow band across the phone's glass, once it lands. */
.hero-phone .hero-device-screen::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  background: linear-gradient(112deg, transparent 38%, rgba(255, 255, 255, 0.07) 50%, transparent 62%);
  transform: translateX(-140%);
  will-change: transform;
  animation: hero-sweep 1.9s cubic-bezier(0.4, 0, 0.2, 1) 2.7s 1 both;
}
@keyframes hero-sweep { to { transform: translateX(140%); } }
@keyframes hero-float {
  0%, 100% { transform: rotate(-5deg) translate3d(0, 0, 0); }
  50% { transform: rotate(-5deg) translate3d(0, -6px, 0); }
}

/* Entrance choreography: the copy rises row by row before the devices. */
.hero-copy > * {
  opacity: 0;
  will-change: transform, opacity;
  animation: hero-rise 0.7s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.hero-copy > :nth-child(1) { animation-delay: 0.05s; }
.hero-copy > :nth-child(2) { animation-delay: 0.15s; }
.hero-copy > :nth-child(3) { animation-delay: 0.28s; }
.hero-copy > :nth-child(4) { animation-delay: 0.38s; }
.hero-copy > :nth-child(5) { animation-delay: 0.48s; }
.hero-copy > :nth-child(6) { animation-delay: 0.6s; }
@keyframes hero-rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
.hero-mark { animation: hero-fade 1.2s ease-out 0.4s both; }
@keyframes hero-fade { from { opacity: 0; } to { opacity: 0.3; } }
@media (prefers-reduced-motion: reduce) {
  .hero-phone, .hero-phone-wrap, .hero-laptop-wrap, .hero-laptop-lid, .hero-laptop .hero-device-screen img,
  .hero-copy > *, .hero-mark { animation: none; }
  .hero-copy > *, .hero-laptop .hero-device-screen img { opacity: 1; }
  .hero-mark { opacity: 0.34; }
  .hero-phone .hero-device-screen::after { display: none; }
}
.hero-ekg {
  display: block;
  width: 100%;
  height: 80px;
  margin-top: 0.5rem;
  overflow: visible;
  opacity: 0.9;
}
.hero-ekg path {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: ekgDraw 2.2s ease-out 1.6s forwards;
  filter: drop-shadow(0 0 6px var(--accent-focus));
}
@keyframes ekgDraw {
  to { stroke-dashoffset: 0; }
}

/* ============================================================
   SHARED PAGE FURNITURE — applies app-wide without markup changes
   ============================================================ */

/* Breadcrumbs read as a quiet trail, not a link list */
.breadcrumb {
  font-size: 0.8rem;
  letter-spacing: 0.01em;
  margin-bottom: 0.75rem;
}
.breadcrumb a { text-decoration: none; }
.breadcrumb a:hover { text-decoration: underline; }

/* Page header block: title + optional actions on the right */
.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--color-border);
}
.page-head h1, .page-head h2, .page-head h3, .page-head h4 { margin-bottom: 0.15rem; }
/* Once the head wraps on a phone, a right-aligned stat block would float
   mid-row; it reads as part of the column instead. */
@media (max-width: 575.98px) {
  .page-head > .text-end { text-align: left !important; }
}
.page-head .page-sub {
  color: var(--color-text-secondary);
  font-size: 0.9rem;
  margin: 0;
}
.page-eyebrow {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--color-text-muted);
  display: block;
  margin-bottom: 0.2rem;
}

/* Tables — quiet grid, sticky header, hover row (gradebooks, rosters, results) */
.table {
  --bs-table-bg: transparent;
  color: var(--color-text-primary);
  border-color: var(--color-border);
}
.table > thead th {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-text-muted);
  border-bottom: 1px solid var(--color-border);
  background: transparent;
  white-space: nowrap;
}
.table > tbody > tr { border-color: var(--color-border); }
.table > tbody > tr:hover > * { background: var(--accent-tint-light); }
.table td, .table th { border-color: var(--color-border); }
.table-sticky thead th {
  position: sticky;
  top: 56px;          /* clears the fixed navbar when the PAGE is the scroller */
  z-index: 2;
  background: var(--color-bg-body);
}
/* Inside a scroll box the sticky viewport is that box, not the page, so the
   navbar offset would shove the header down onto the first row instead. */
.table-responsive .table-sticky thead th,
.tbl-scroll .table-sticky thead th {
  top: 0;
}
/* Wide tables scroll inside their own box instead of the page */
.table-responsive { border-radius: var(--radius-md); }

/* Readable prose column — long-form readings, study guides, policies */
.prose {
  max-width: 68ch;
  font-size: 1.02rem;
  line-height: 1.7;
}
.prose h2, .prose h3, .prose h4 {
  margin-top: 2rem;
  margin-bottom: 0.6rem;
  letter-spacing: -0.005em;
}
.prose h4 { font-size: 1.15rem; }
.prose p { margin-bottom: 1.1rem; }
.prose ul, .prose ol { margin-bottom: 1.1rem; }
.prose li { margin-bottom: 0.35rem; }
.prose img { max-width: 100%; height: auto; border-radius: var(--radius-md); }
.prose strong { color: var(--color-text-primary); }

/* Empty states — an invitation to act, not a shrug */
.empty-state {
  text-align: center;
  padding: 3rem 1.5rem;
  color: var(--color-text-secondary);
}
/* Direct child only — icons inside a CTA button here must stay inline-sized. */
.empty-state > .bi {
  font-size: 2.25rem;
  color: var(--accent);
  opacity: 0.55;
  display: block;
  margin-bottom: 0.75rem;
}
.empty-state h5 { margin-bottom: 0.35rem; }
.empty-state p { font-size: 0.9rem; margin-bottom: 1rem; }

/* Settings / form sections */
.form-section { margin-bottom: 2rem; }
.form-section > h5,
.form-section > h6 {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.85rem;
  color: var(--color-text-secondary);
  border-left: 3px solid var(--accent);
  padding-left: 0.7rem;
  margin-bottom: 0.9rem;
}
.form-label { font-weight: 600; font-size: 0.9rem; }
.form-text { color: var(--color-text-muted); }

/* Nav tabs — underline style instead of folder tabs */
.nav-tabs {
  border-bottom: 1px solid var(--color-border);
  gap: 0.25rem;
}
.nav-tabs .nav-link {
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  color: var(--color-text-secondary);
  font-weight: 600;
  padding: 0.5rem 0.9rem;
}
.nav-tabs .nav-link:hover { border-bottom-color: var(--accent-light); color: var(--color-text-primary); }
.nav-tabs .nav-link.active {
  background: transparent;
  color: var(--accent);
  border-bottom-color: var(--accent);
}
[data-theme="light"] .nav-tabs .nav-link.active { color: var(--accent-dark); }

/* Alerts — flat, accent-edged instead of pastel blocks */
.alert {
  border: 1px solid var(--color-border);
  border-left-width: 3px;
  border-radius: var(--radius-md);
  background: var(--color-bg-card);
  color: var(--color-text-primary);
}
[data-theme="light"] .alert { background: #ffffff; }
.alert-success { border-left-color: var(--color-success-green); }
.alert-warning { border-left-color: var(--color-warning-yellow); }
.alert-danger, .alert-error { border-left-color: var(--color-danger-red); }
.alert-info, .alert-primary { border-left-color: var(--color-info-blue); }
.alert-secondary { border-left-color: var(--color-text-muted); }

/* Modals + dropdowns inherit the card language */
.modal-content {
  background: var(--color-bg-card);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}
[data-theme="light"] .modal-content { background: #ffffff; }
.modal-header, .modal-footer { border-color: var(--color-border); }
.dropdown-menu {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}
[data-theme="light"] .dropdown-menu { background: #ffffff; }
.dropdown-item { color: var(--color-text-primary); }
.dropdown-item:hover { background: var(--accent-tint); color: var(--color-text-primary); }
.dropdown-item.active { background: var(--accent); color: #fff; }

/* ============================================================
   ACTIVITY-SPECIFIC STYLES
   ============================================================ */

/* Reading */
.reading-section {
  border-left: 3px solid var(--accent);
  padding-left: 1.5rem;
  margin-bottom: 2rem;
}
.prompt-box {
  background: var(--dark-mid);
  border-radius: var(--radius-md);
  padding: 1.25rem;
  margin-top: 1rem;
}
[data-theme="light"] .prompt-box {
  background: #f0f2f5;
}
.model-answer-box {
  background: rgba(16, 185, 129, 0.1);
  border: 1px solid var(--color-success-green);
  border-radius: var(--radius-sm);
  padding: 1rem;
  margin-top: 0.75rem;
}

/* Matching game */
.match-card { cursor: pointer; transition: all 0.2s; user-select: none; }
.match-card:hover { border-color: var(--accent) !important; }
.match-card.selected { border-color: var(--accent) !important; background: var(--accent-tint); }
.match-card.correct { border-color: var(--color-success-green) !important; background: rgba(16, 185, 129, 0.15); }
.match-card.wrong { border-color: var(--color-danger-red) !important; animation: shake 0.3s; }
@keyframes shake { 0%,100%{transform:translateX(0)} 25%{transform:translateX(-5px)} 75%{transform:translateX(5px)} }

/* Flashcards */
.flashcard { min-height: 220px; cursor: pointer; transition: transform 0.15s; }
.flashcard:hover { transform: scale(1.01); }
.flashcard .card-body { display: flex; align-items: center; justify-content: center; text-align: center; padding: 2rem; }
.flashcard-front { font-size: 1.2rem; font-weight: 600; }
.flashcard-back { font-size: 1.1rem; }

/* Labeling game */
.hotspot-item.correct input { border-color: var(--color-success-green) !important; background: rgba(16, 185, 129, 0.15) !important; }
.hotspot-item.wrong input { border-color: var(--color-danger-red) !important; background: rgba(239, 68, 68, 0.15) !important; }

/* Short answer */
.sa-question {
  border-left: 3px solid var(--accent);
  padding-left: 1.5rem;
  margin-bottom: 2rem;
}

/* Quiz buttons */
.quiz-option {
  border-color: var(--color-border);
  color: var(--color-text-primary);
  text-align: left;
}
.quiz-option:hover:not(:disabled) {
  border-color: var(--accent);
  background: var(--accent-tint);
  color: var(--color-text-primary);
}
[data-theme="light"] .quiz-option {
  border-color: rgba(22, 35, 46, 0.15);
  color: #16232e;
}
[data-theme="light"] .quiz-option:hover:not(:disabled) {
  border-color: var(--accent);
  background: var(--accent-tint-light);
  color: #16232e;
}

/* An open shift that has run far past what its kind ever should — 14 hours for
   most, 50 for a ride. The border carries the warning on its own; the pulse is
   what makes a student who stopped reading the card look at it again.

   The global prefers-reduced-motion rule above collapses the animation, and
   the keyframes are written so that leaves the solid red border standing
   rather than a half-faded frame. */
.card.shift-overrun {
  border-color: var(--bs-danger, #dc3545);
  animation: shift-overrun-pulse 1.6s ease-in-out infinite;
}
@keyframes shift-overrun-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.55); }
  50%      { box-shadow: 0 0 0 6px rgba(220, 53, 69, 0); }
}

/* ============================================================
   SHIFT BAR — the running shift, on every page

   Ending a shift used to mean navigating back to the dashboard and finding
   the Modules tab, because the sign-out modal lived in the card that renders
   there. This strip sits under the navbar so the exit follows the student
   into a module, a quiz, or a flashcard deck.
   ============================================================ */
.shift-bar {
  position: fixed;
  top: 45px;                 /* clears .slim-navbar: 0.35rem padding + content */
  left: 0;
  right: 0;
  z-index: 1029;             /* under the navbar, over everything else */
  background: var(--accent, #0d6efd);
  color: #fff;
  padding: 0.3rem 0;
  font-size: 0.85rem;
  border-bottom: 1px solid rgba(0, 0, 0, 0.2);
}

.shift-bar .btn {
  --bs-btn-padding-y: 0.15rem;
  --bs-btn-padding-x: 0.5rem;
  --bs-btn-font-size: 0.8rem;
}

.shift-bar-note {
  opacity: 0.85;
}

/* A student who forgot to sign out is not reading the bar, so past the warn
   window it has to be the thing that catches their eye. Same pulse the
   dashboard card uses, so the two never look like different alarms. */
.shift-bar-overrun {
  background: var(--bs-danger, #dc3545);
  animation: shift-bar-pulse 2s ease-in-out infinite;
}

@keyframes shift-bar-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.78; }
}

@media (prefers-reduced-motion: reduce) {
  .shift-bar-overrun { animation: none; }
}

/* The content offset. Was a hard-coded margin-top:60px inline on the
   container, which had no way to know the bar was there. */
.page-body {
  margin-top: 60px;
  padding-top: 1rem;
}

.page-body-shift {
  margin-top: 100px;
}

/* ============================================================
   FOOTNOTES
   `[^1]` in reading markdown. The native popover attribute does the
   open/close — click-outside dismiss and Esc come free, and the card
   sits in the top layer so no z-index fight with the shift bar or the
   read-aloud panel. Only the placement is ours (base.html).
   ============================================================ */
.fn-ref {
  display: inline-block;
  min-width: 1.5em;
  margin-left: 0.15em;
  padding: 0 0.45em;
  /* The edge is load-bearing: on the light theme the pill's fill is a pale
     accent tint that all but disappears against white. */
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-bg-card-header);
  color: var(--color-text-secondary);
  font-family: var(--font-mono);
  font-size: 0.72em;
  font-weight: 600;
  line-height: 1.6;
  vertical-align: 0.35em;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.fn-ref:hover,
.fn-ref:focus-visible {
  background: var(--accent);
  color: #fff;
}

.fn-pop {
  position: fixed;
  /* The UA sheet centres popovers with `inset: 0; margin: auto`. Clearing
     only the margin parks the card in the top-left corner until the script
     moves it, one frame later — visibly. `inset: auto` starts it at its
     static position, right beside its marker. */
  inset: auto;
  margin: 0;
  max-width: min(32rem, calc(100vw - 2rem));
  padding: 0.85rem 1.1rem;
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--color-bg-card);
  color: var(--color-text-secondary);
  box-shadow: var(--shadow-lg);
  font-size: 0.95rem;
  line-height: 1.55;
}

/* The light-dismiss surface stays invisible: a footnote is an aside, not a
   modal, and dimming the page loses the sentence you were reading. */
.fn-pop:popover-open { display: block; }

.fn-pop::backdrop { background: transparent; }

/* ============================================================
   FIELD NOTEBOOK — the shift logging and reporting screens
   (2026-09-06). Replaces the Bootstrap list-group/card-header
   stacks on shift.html, history.html, progress.html,
   writing.html and paperwork.html.

   The premise: a shift is a timeline the student fills in as it
   happens, not a form submitted at the end. Patients hang off a
   spine in the order they occurred; progress is a ring, not a
   fraction; a piece of writing gets the whole page with the
   instructor's comment set in the margin.

   Every colour here comes from an existing token, so all five
   accent palettes and both themes follow without a second block.
   ============================================================ */

/* --- page header ------------------------------------------- */
.nb-head {
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 0.25rem;
}
.nb-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.75rem;
  letter-spacing: 0.005em;
  margin: 0.3rem 0 0;
}
.nb-sub {
  color: var(--color-text-muted);
  font-size: 0.85rem;
  margin: 0.2rem 0 0;
}
.nb-caps {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.nb-live { color: var(--color-success-green); }

/* --- the timeline spine ------------------------------------ */
/* The gutter arithmetic is load-bearing: the spine sits at the
   centre of the nodes, which are 9px wide at left:-20px inside a
   56px pad — 56 - 20 + 4.5 rounds to 40. Change one, change all
   three or the line drifts off the dots. */
.nb-spine {
  position: relative;
  padding: 1rem 0 0 56px;
}
.nb-spine::before {
  content: "";
  position: absolute;
  left: 40px;
  top: 1.4rem;
  bottom: 1.6rem;
  width: 1px;
  background: var(--color-border);
}
.nb-ev {
  position: relative;
  padding-bottom: 1.1rem;
}
.nb-time {
  position: absolute;
  left: -56px;
  top: 0.05rem;
  width: 32px;
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.7rem;
  color: var(--color-text-muted);
}
.nb-node {
  position: absolute;
  left: -20px;
  top: 0.35rem;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--color-bg-body);
  box-shadow: 0 0 0 2px var(--accent);
}
.nb-node.is-done {
  background: var(--color-success-green);
  box-shadow: 0 0 0 2px var(--color-success-green);
}
.nb-node.is-owed { box-shadow: 0 0 0 2px var(--color-warning-yellow); }
.nb-ev-t { font-weight: 600; font-size: 0.95rem; }
.nb-ev-m {
  color: var(--color-text-muted);
  font-size: 0.78rem;
  margin-top: 0.05rem;
}
/* The student's own bedside jot, quoted the way a note in a
   notebook margin is — it is evidence, not prose to be read. */
.nb-note {
  margin-top: 0.4rem;
  font-size: 0.82rem;
  color: var(--color-text-secondary);
  line-height: 1.55;
  border-left: 2px solid var(--color-border);
  padding-left: 0.6rem;
}
.nb-note p:last-child { margin-bottom: 0; }

/* --- skill chips ------------------------------------------- */
.nb-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.5rem;
}
.nb-tag {
  font-size: 0.72rem;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  color: var(--color-text-secondary);
  white-space: nowrap;
}
.nb-tag.is-signed {
  border-color: var(--color-success-green);
  color: var(--color-success-green);
}
.nb-tag.is-rejected {
  color: var(--color-text-muted);
  text-decoration: line-through;
}
.nb-tag.is-owed {
  border-color: var(--color-warning-yellow);
  color: var(--color-warning-yellow);
}
.nb-tag.is-back {
  border-color: var(--color-info-blue);
  color: var(--color-info-blue);
}
.nb-tag.is-red {
  border-color: var(--accent);
  color: var(--accent);
}
a.nb-tag { text-decoration: none; }
a.nb-tag:hover { background: var(--accent-tint); }

/* --- the add node ------------------------------------------ */
/* The last node on the spine is the control, so adding a patient
   reads as continuing the timeline rather than filling in a form
   that happens to sit underneath one. */
.nb-add {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  padding: 0 0 0.4rem;
  border: 0;
  background: none;
  color: var(--accent);
  font-weight: 600;
  font-size: 0.9rem;
  text-align: left;
  text-decoration: none;
}
.nb-add .nb-node {
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--accent);
}
.nb-add:hover { color: var(--accent-dark); }
[data-theme="light"] .nb-add:hover { color: var(--accent-dark); }
/* The control is a <summary>, so the browser's own disclosure triangle has to
   go — it lands on top of the spine node. Both selectors are needed: WebKit
   ignores list-style on summary and uses the pseudo-element instead. */
summary.nb-add {
  cursor: pointer;
  list-style: none;
}
summary.nb-add::-webkit-details-marker { display: none; }
summary.nb-add::marker { content: ""; }

/* --- progress rings ---------------------------------------- */
.nb-rings {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  padding: 0.9rem 0 0.2rem;
}
.nb-ring { text-align: center; flex: 1 1 84px; }
.nb-ring svg { display: block; margin: 0 auto 0.35rem; }
.nb-ring-track { stroke: var(--color-border); }
.nb-ring-fill { stroke: var(--accent); }
.nb-ring-fill.is-met { stroke: var(--color-success-green); }
.nb-ring-pct {
  fill: var(--color-text-primary);
  font-family: var(--font-mono);
  font-size: 15px;
}
.nb-ring-v {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.85rem;
}
.nb-ring-l {
  font-size: 0.72rem;
  color: var(--color-text-muted);
  margin-top: 0.05rem;
  line-height: 1.3;
}

/* --- the shift chooser ------------------------------------- */
/* Each kind is one card and the whole card is the control, rather than a
   list row with a small icon at the far right: the tap target on a phone was
   the icon, and the progress that decides which kind you pick was set in the
   same grey as everything else. */
.nb-kinds {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: 1fr;
  /* Equal rows: these are peer choices, and a card that is shorter because
     nobody set a target for that kind reads as the lesser option. */
  grid-auto-rows: 1fr;
  margin-top: 1.1rem;
}
@media (min-width: 640px) {
  .nb-kinds { grid-template-columns: 1fr 1fr; }
}
.nb-kind {
  display: grid;
  gap: 0.3rem;
  align-content: start;
  width: 100%;
  padding: 1rem 1.1rem;
  text-align: left;
  color: var(--color-text-primary);
  text-decoration: none;
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-fast),
              transform var(--transition-fast),
              box-shadow var(--transition-fast);
}
a.nb-kind, a.nb-kind:hover, a.nb-kind:focus-visible {
  color: var(--color-text-primary);
  text-decoration: none;
}
.nb-kind:hover,
.nb-kind:focus-visible {
  color: var(--color-text-primary);
  border-color: var(--accent);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}
.nb-kind-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
}
.nb-kind-name {
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: 0.005em;
}
.nb-kind-go {
  flex: none;
  color: var(--accent);
  font-size: 1.15rem;
  line-height: 1;
}
[data-theme="light"] .nb-kind-go { color: var(--accent-dark); }
.nb-kind .nb-bar { margin-top: 0.25rem; }

/* --- target bars ------------------------------------------- */
/* A ring is the wrong primitive for twenty targets a student has barely
   started: at 0/20 every one of them draws the same empty grey donut, which
   says less than the fraction it replaced. Bars read at any completion,
   including none, and stack into a column you can scan. The ring is kept for
   the one figure per section that summarises them. */
.nb-sec {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 1.6rem 0 0.6rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--color-border);
}
.nb-sec .nb-month {
  margin: 0;
  padding: 0;
  border: 0;
}
/* The section's ring sits inline with its own figure rather than stacked
   above it: at 60px tall with the count underneath it made the header twice
   the height of the rule below, so the bars it summarises read as a separate
   block instead of its contents. */
.nb-sec .nb-ring {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.nb-sec .nb-ring svg { width: 40px; height: 40px; margin: 0; }

.nb-bars {
  display: grid;
  gap: 0.85rem 2rem;
  grid-template-columns: 1fr;
}
@media (min-width: 640px) {
  .nb-bars { grid-template-columns: 1fr 1fr; }
}
.nb-bar-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0.15rem 0.6rem;
}
.nb-bar-l { font-size: 0.86rem; min-width: 0; }
.nb-bar-v {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.82rem;
  color: var(--color-text-secondary);
  white-space: nowrap;
}
.nb-bar-row.is-met .nb-bar-v { color: var(--color-success-green); }
.nb-bar {
  grid-column: 1 / -1;
  height: 5px;
  border-radius: 3px;
  background: var(--color-border);
  overflow: hidden;
}
.nb-bar span {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--accent);
}
.nb-bar-row.is-met .nb-bar span { background: var(--color-success-green); }

/* --- month-grouped history --------------------------------- */
/* The page opens on its own headline rather than straight into the list —
   "how many hours do I have" is the question that brings a student here, and
   it used to be answerable only by adding the column up by eye. */
.nb-totals {
  display: flex;
  gap: 2.5rem;
  padding: 1rem 0 0.2rem;
}
.nb-total-v {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 2rem;
  line-height: 1.1;
}

.nb-month {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 1.4rem 0 0.3rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--color-border);
}
.nb-entry {
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--color-border);
}
.nb-entry:last-child { border-bottom: 0; }
.nb-day { text-align: center; flex: none; width: 34px; }
.nb-day-d {
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 600;
  line-height: 1;
}
.nb-day-w {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  color: var(--color-text-muted);
}
.nb-entry-b { flex: 1; min-width: 0; }
.nb-entry-r { flex: none; text-align: right; }
.nb-entry-v {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.05rem;
}
.nb-entry-v.is-void {
  color: var(--color-text-muted);
  text-decoration: line-through;
}

/* --- one piece of writing, the whole page ------------------ */
/* A section of the paperwork page: one patient, or the shift summary. A rule
   between blocks rather than a card apiece — five stacked cards on a busy
   shift is five borders competing with the one thing that matters, which is
   the box the student types in. */
.nb-block {
  padding: 1.2rem 0 0.4rem;
  border-top: 1px solid var(--color-border);
  margin-top: 1.2rem;
}
.nb-block:first-of-type { border-top: 0; }

.nb-kicker {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--accent);
}
[data-theme="light"] .nb-kicker { color: var(--accent-text); }
.nb-q {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 600;
  line-height: 1.15;
  margin: 0.3rem 0 0.1rem;
  text-wrap: balance;
}
/* The instructor's words set as a margin note on a manuscript,
   above the box rather than beside it — reading the comment after
   writing the rewrite is reading it too late. */
.nb-margin {
  border-left: 2px solid var(--color-info-blue);
  padding: 0.35rem 0 0.35rem 0.7rem;
  margin: 0.9rem 0;
  font-size: 0.86rem;
  font-style: italic;
  color: var(--color-text-secondary);
}
.nb-margin.is-mine { border-left-color: var(--color-border); }
.nb-margin-who {
  font-style: normal;
  font-weight: 600;
  color: var(--color-text-primary);
}
.nb-margin p:last-child { margin-bottom: 0; }
/* A narrative is a document: mono, roomy lines, dark paper. */
textarea.nb-write {
  font-family: var(--font-mono);
  font-size: 0.88rem;
  line-height: 1.75;
  border-radius: var(--radius-md);
}
.nb-actions {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-top: 0.75rem;
  flex-wrap: wrap;
}

/* ============================================================
   INSTRUCTOR TOOL GROUPS — the 28 tool cards folded into six
   <details>. The summary is the card header; the marker is
   replaced by a chevron that turns when the group is open.
   ============================================================ */
.tool-groups { display: flex; flex-direction: column; gap: 10px; }
.tool-group {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.tool-group > summary {
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.7rem 1rem;
  background: var(--color-bg-card-header);
  color: var(--color-text-primary);
  font-family: var(--font-display); font-weight: 600; font-size: 1.15rem;
  cursor: pointer; user-select: none; list-style: none;
}
.tool-group > summary::-webkit-details-marker { display: none; }
.tool-group > summary::marker { content: ""; }
.tool-group > summary:focus-visible { outline: 2px solid var(--accent-light); outline-offset: -2px; }
.tool-group-icon { color: var(--accent); font-size: 1.3rem; }
.tool-group-sub {
  font-family: var(--font-body); font-weight: 400; font-size: 0.85rem;
  color: var(--color-text-secondary);
}
.tool-group-count, .tool-group-wait {
  font-family: var(--font-mono); font-size: 0.75rem;
  border-radius: 999px; padding: 0.1rem 0.6rem;
}
.tool-group-count { color: var(--color-text-secondary); background: var(--accent-tint); }
.tool-group-wait { color: #f5b451; background: rgba(245, 180, 81, 0.16); }
[data-theme="light"] .tool-group-wait { color: #b45309; background: rgba(180, 83, 9, 0.12); }
.tool-group-chev { margin-left: auto; color: var(--color-text-secondary); transition: transform var(--transition-fast); }
.tool-group[open] > summary .tool-group-chev { transform: rotate(90deg); }
@media (max-width: 575px) { .tool-group-sub { display: none; } }

/* Instructor Duties bar (#106): every queue waiting on the instructor, one
   amber button each — the same chip colour as the group headers' "N waiting". */
.duty-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  margin-bottom: 10px;
}
.duty-bar-title {
  font-family: var(--font-display); font-weight: 600; font-size: 0.95rem;
  color: var(--color-text-secondary); margin-right: 0.25rem;
}
.duty-btn {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.35rem 0.85rem; border-radius: 999px;
  color: #f5b451; background: rgba(245, 180, 81, 0.16);
  border: 1px solid rgba(245, 180, 81, 0.35);
  font-size: 0.9rem; text-decoration: none;
  transition: background var(--transition-fast);
}
.duty-btn:hover, .duty-btn:focus-visible { color: #f5b451; background: rgba(245, 180, 81, 0.28); }
.duty-count { font-family: var(--font-mono); font-weight: 700; }
.duty-clear { color: var(--color-text-secondary); font-size: 0.9rem; }
[data-theme="light"] .duty-btn { color: #b45309; background: rgba(180, 83, 9, 0.12); border-color: rgba(180, 83, 9, 0.3); }
[data-theme="light"] .duty-btn:hover, [data-theme="light"] .duty-btn:focus-visible { color: #b45309; background: rgba(180, 83, 9, 0.2); }

/* ============================================================
   AI PATIENT INTERVIEW — the encounter screen (interview_play.html)
   One stage: the scene (video, segment track, partner's monitor) and the
   conversation. Phones pin the scene to the top and the question box to
   the bottom. Element ids are the script's; these classes are the look.
   ============================================================ */
.iv-encounter {
  --iv-screen: #0B0C0E;
  --iv-panel: var(--color-bg-card);
  --iv-line: var(--color-border);
  --iv-ink: var(--color-text-primary);
  --iv-muted: var(--color-text-muted);
  --iv-you: var(--accent);
  --iv-patient-bg: rgba(255, 255, 255, 0.06);
  --iv-monitor-bg: rgba(0, 0, 0, 0.22);
  --iv-monitor-ink: #3ECF9A;
  padding-bottom: 1rem;
}
[data-theme="light"] .iv-encounter {
  --iv-you: var(--accent-dark);
  --iv-patient-bg: #F1EEEA;
  --iv-monitor-bg: #16171A;
  --iv-monitor-ink: #3ECF9A;
}
.iv-label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--iv-muted);
}
.iv-tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.25rem 0.55rem;
  border-radius: 3px;
  border-left: 3px solid var(--iv-you);
  background: var(--accent-tint);
  color: var(--iv-ink);
  white-space: nowrap;
}
.iv-tag-quiet { border-left-color: var(--iv-muted); background: var(--iv-patient-bg); color: var(--iv-muted); }
.iv-tag:empty { display: none; }

/* The phase rail's pills take the stencil edge like every other tag. */
.iv-encounter nav[aria-label="Case progress"] { margin-bottom: 0.75rem !important; }
.iv-encounter nav[aria-label="Case progress"] .badge { border-radius: 3px !important; }

/* Head */
.iv-head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem;
  margin-bottom: 1rem;
}
.iv-eyebrow { display: block; color: var(--iv-you); font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; }
.iv-title { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.75rem, 3vw, 2.4rem); line-height: 1; margin: 0.15rem 0 0; }
.iv-head-right { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; justify-content: flex-end; }

/* Grid */
.iv-grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(320px, 5fr);
  gap: 1.25rem;
  align-items: start;
}

/* Scene */
.iv-screen {
  position: relative;
  background: var(--iv-screen);
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 16 / 9;
  box-shadow: var(--shadow-md), 0 0 0 1px rgba(255, 255, 255, 0.06) inset;
}
.iv-screen video, .iv-screen mux-player { display: block; width: 100%; height: 100%; object-fit: contain; background: var(--iv-screen); }
.iv-screen mux-player { --media-accent-color: var(--accent); aspect-ratio: 16 / 9; }
.iv-screen-note { position: absolute; inset: 0; display: grid; place-items: center; padding: 1.5rem; text-align: center; color: #F4F2EF; }
.iv-scene-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.75rem 0.25rem 0;
}
.iv-scene-hint { color: var(--iv-muted); font-size: 0.9rem; }
.iv-track { display: flex; gap: 1.25rem; list-style: none; margin: 0; padding: 0; }
.iv-track li { display: flex; align-items: center; gap: 0.4rem; color: var(--iv-muted); font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; }
.iv-track-dot { width: 10px; height: 10px; border-radius: 50%; border: 2px solid currentColor; }
.iv-track li.is-done { color: var(--color-success-green); }
.iv-track li.is-done .iv-track-dot { background: currentColor; }
.iv-track li.is-now { color: var(--iv-you); }
.iv-track li.is-now .iv-track-dot { background: currentColor; box-shadow: 0 0 0 4px var(--accent-tint); }
.iv-ghost {
  border: 1px solid var(--iv-line); background: transparent; color: var(--iv-ink);
  font-weight: 600; font-size: 0.85rem; padding: 0.4rem 0.75rem; border-radius: var(--radius-sm);
  transition: border-color var(--transition-fast), background var(--transition-fast);
}
.iv-ghost:hover { border-color: var(--iv-you); background: var(--accent-tint-light); }

/* Partner's monitor */
.iv-monitor {
  margin-top: 1rem;
  border: 1px solid var(--iv-line);
  border-radius: var(--radius-lg);
  background: var(--iv-panel);
  overflow: hidden;
}
.iv-monitor-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.75rem 1rem; flex-wrap: wrap; }
.iv-crew-actions { display: flex; gap: 0.5rem; }
.iv-crew-btn {
  display: inline-flex; align-items: center; gap: 0.4rem;
  border: 1px solid var(--iv-you); color: var(--iv-you); background: transparent;
  font-weight: 700; font-size: 0.85rem; padding: 0.45rem 0.8rem; border-radius: var(--radius-sm);
  transition: background var(--transition-fast), color var(--transition-fast), opacity var(--transition-fast);
}
.iv-crew-btn:hover:not(:disabled) { background: var(--iv-you); color: #fff; }
.iv-crew-btn:disabled { opacity: 0.45; }
.iv-readout { border-top: 1px solid var(--iv-line); padding: 0.85rem 1rem; }
.iv-pending { display: flex; align-items: center; gap: 0.5rem; color: var(--iv-muted); font-size: 0.85rem; margin-bottom: 0.5rem; }
.iv-pending:last-child { margin-bottom: 0; }
.iv-count { font-family: var(--font-mono); color: var(--iv-ink); }
.iv-pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--iv-you); animation: iv-pulse 1.1s ease-in-out infinite; }
@keyframes iv-pulse { 0%, 100% { opacity: 0.35; transform: scale(0.8); } 50% { opacity: 1; transform: scale(1.15); } }
.iv-vitals { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 0.5rem; margin: 0; }
.iv-vitals:empty { display: none; }
.iv-vital {
  background: var(--iv-monitor-bg); border-radius: var(--radius-sm); padding: 0.55rem 0.7rem;
  display: flex; flex-direction: column; gap: 0.15rem; min-width: 0;
}
.iv-vital dt { font-family: var(--font-mono); font-size: 0.68rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(244, 242, 239, 0.6); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.iv-vital dd { margin: 0; font-family: var(--font-mono); font-size: 1.05rem; font-weight: 700; color: var(--iv-monitor-ink); letter-spacing: 0.02em; }
.iv-strip { background: #fff; border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--iv-line); }
.iv-strip img { display: block; width: 100%; }
.iv-read { margin-top: 0.4rem; font-size: 0.9rem; display: flex; gap: 0.5rem; align-items: baseline; flex-wrap: wrap; }

/* Conversation */
.iv-talk { min-width: 0; }
.iv-panel {
  display: flex; flex-direction: column;
  border: 1px solid var(--iv-line); border-radius: var(--radius-lg);
  background: var(--iv-panel); overflow: hidden;
}
.iv-talk-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.85rem 1rem; border-bottom: 1px solid var(--iv-line); flex-wrap: wrap; }
.iv-talk-who { display: flex; align-items: center; gap: 0.65rem; }
.iv-avatar { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; background: var(--accent-tint); color: var(--iv-you); font-size: 1.2rem; }
.iv-talk-name { font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; line-height: 1; }
.iv-talk-sub { color: var(--iv-muted); font-size: 0.8rem; }
.iv-rapport { min-width: 180px; flex: 1 1 180px; max-width: 260px; }
.iv-rapport-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.35rem; gap: 0.5rem; }
.iv-encounter .vibe-bar { height: 6px; border-radius: 999px; background: linear-gradient(90deg, #C8321F, #FFB547 50%, #3ECF9A); opacity: 0.9; }
.iv-encounter .vibe-needle {
  position: relative; width: 14px; height: 14px; border-radius: 50%;
  background: var(--iv-panel); border: 2px solid var(--iv-ink);
  margin-top: -10px; left: calc(60% - 7px); transition: left 0.6s ease;
}
.iv-log {
  flex: 1 1 auto; overflow-y: auto; padding: 1rem;
  min-height: 340px; max-height: min(56vh, 640px);
  display: flex; flex-direction: column; gap: 0.6rem;
  scroll-behavior: smooth;
}
.iv-msg { display: flex; flex-direction: column; gap: 0.15rem; max-width: 86%; }
.iv-msg-student { align-self: flex-end; align-items: flex-end; }
.iv-msg-patient { align-self: flex-start; align-items: flex-start; }
.iv-who { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--iv-muted); padding: 0 0.25rem; }
.iv-bubble {
  display: inline-block; padding: 0.55rem 0.85rem; border-radius: 16px;
  font-size: 0.97rem; line-height: 1.45; text-align: left; white-space: normal;
}
.iv-msg-student .iv-bubble { background: var(--iv-you); color: #fff; border-bottom-right-radius: 5px; }
.iv-msg-patient .iv-bubble { background: var(--iv-patient-bg); color: var(--iv-ink); border: 1px solid var(--iv-line); border-bottom-left-radius: 5px; }
.iv-crew-note { align-self: center; font-size: 0.8rem; color: var(--iv-muted); font-style: italic; text-align: center; padding: 0.15rem 0.75rem; }
.iv-typing { align-self: flex-start; display: inline-flex; gap: 4px; padding: 0.6rem 0.85rem; border-radius: 16px; background: var(--iv-patient-bg); border: 1px solid var(--iv-line); }
.iv-typing span { width: 6px; height: 6px; border-radius: 50%; background: var(--iv-muted); animation: iv-typing 1.2s ease-in-out infinite; }
.iv-typing span:nth-child(2) { animation-delay: 0.15s; }
.iv-typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes iv-typing { 0%, 60%, 100% { transform: translateY(0); opacity: 0.4; } 30% { transform: translateY(-4px); opacity: 1; } }
.iv-composer { border-top: 1px solid var(--iv-line); padding: 0.75rem 1rem 1rem; background: var(--iv-panel); }
.iv-compose-row { display: flex; gap: 0.5rem; }
.iv-input { border-radius: 999px; padding: 0.65rem 1.1rem; }
.iv-send { flex-shrink: 0; border-radius: 999px; display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.55rem 1rem; white-space: nowrap; }
.iv-advance {
  width: 100%; margin-top: 0.6rem; font-weight: 700;
  background: var(--color-success-green); color: #0B2A1E; border: 0;
  padding: 0.7rem 1rem; border-radius: var(--radius-sm);
  transition: opacity var(--transition-fast), transform var(--transition-fast);
}
.iv-advance:hover:not(:disabled) { color: #0B2A1E; transform: translateY(-1px); }
.iv-advance:disabled { opacity: 0.4; }
.iv-err { margin-top: 0.6rem; font-size: 0.85rem; color: var(--color-warning-yellow); }
.iv-err a { color: inherit; font-weight: 700; }

/* Briefing */
.iv-briefing {
  border: 1px solid var(--iv-you); border-radius: var(--radius-lg); padding: 1.25rem 1.25rem 1.1rem;
  background: var(--iv-panel); box-shadow: 0 0 0 4px var(--accent-tint);
}
.iv-briefing-title { font-family: var(--font-display); font-weight: 700; font-size: 1.5rem; line-height: 1.1; margin: 0.5rem 0 0.75rem; }
.iv-briefing p { margin-bottom: 0.6rem; }
.iv-briefing-note { color: var(--iv-muted); font-size: 0.9rem; margin-bottom: 1rem !important; }
.iv-cta { width: 100%; font-weight: 700; padding: 0.7rem 1rem; }

/* Phones and small tablets: scene pinned on top, conversation scrolls under
   it, question box pinned above the keyboard (and above the tab bar). */
@media (max-width: 991.98px) {
  .iv-grid { grid-template-columns: minmax(0, 1fr); gap: 0.75rem; }
  .iv-head { margin-bottom: 0.6rem; }
  .iv-head-right { justify-content: flex-start; }
  /* The scene dissolves into the grid so only the video pins; the segment
     track and the partner's monitor scroll away under it with the chat. */
  .iv-scene { display: contents; }
  .iv-screen { position: sticky; top: 60px; z-index: 5; border-radius: var(--radius-md); box-shadow: var(--shadow-lg); }
  .iv-scene-bar { padding-top: 0.5rem; }
  .iv-track-label { display: none; }
  .iv-track { gap: 0.6rem; }
  .iv-monitor { margin-top: 0; }
  .iv-scene-bar { padding-top: 0.25rem; }
  .iv-monitor-head { padding: 0.6rem 0.75rem; }
  .iv-readout { padding: 0.6rem 0.75rem; }
  .iv-vitals { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .iv-panel { border: 0; background: transparent; overflow: visible; }
  .iv-talk-head { padding: 0.5rem 0.25rem 0.75rem; }
  .iv-log { min-height: 40vh; max-height: none; overflow: visible; padding: 0.5rem 0.25rem 0.75rem; }
  .iv-msg { max-width: 92%; }
  .iv-composer {
    position: sticky; bottom: 0; z-index: 6;
    margin: 0 -12px; padding: 0.6rem 12px calc(0.6rem + env(safe-area-inset-bottom));
    border-top: 1px solid var(--iv-line);
  }
  .iv-send-text { display: none; }
  .iv-send { padding: 0.55rem 0.9rem; }
}
@media (max-width: 767.98px) {
  /* Above the mobile tab bar, which is 4.5rem tall (body padding). */
  .iv-composer { bottom: 4.5rem; }
}
@media (prefers-reduced-motion: reduce) {
  .iv-pulse, .iv-typing span { animation: none; }
  .iv-encounter .vibe-needle { transition: none; }
  .iv-log { scroll-behavior: auto; }
}

/* ---- Case pages after the interview: differential, treatments, report,
   narrative, results, and the practice menu. Same language as the
   encounter screen; the rail is the spine. ---- */
.iv-case {
  --iv-panel: var(--color-bg-card);
  --iv-line: var(--color-border);
  --iv-ink: var(--color-text-primary);
  --iv-muted: var(--color-text-muted);
  --iv-you: var(--accent);
  --iv-patient-bg: rgba(255, 255, 255, 0.06);
  --iv-monitor-bg: rgba(0, 0, 0, 0.22);
  --iv-monitor-ink: #3ECF9A;
  --iv-good: var(--color-success-green);
  --iv-okay: var(--color-warning-yellow);
  --iv-poor: #FF6A4D;
  max-width: 72rem; margin: 0 auto; padding-bottom: 1.5rem;
}
[data-theme="light"] .iv-case {
  --iv-you: var(--accent-dark);
  --iv-patient-bg: #F1EEEA;
  --iv-monitor-bg: #16171A;
  --iv-poor: #B92D1C;
}
.iv-head-sub { color: var(--iv-muted); max-width: 60ch; margin: 0.5rem 0 0; }

/* Rail */
.iv-rail { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }
.iv-rail-steps { display: flex; align-items: center; gap: 0; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; row-gap: 0.4rem; }
.iv-rail-step { display: flex; align-items: center; gap: 0.45rem; color: var(--iv-muted); font-family: var(--font-mono); font-size: 0.7rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; }
.iv-rail-step + .iv-rail-step::before { content: ""; width: 1.5rem; height: 1px; background: var(--iv-line); margin: 0 0.5rem; }
.iv-rail-num { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; border: 1.5px solid currentColor; font-size: 0.68rem; line-height: 1; }
.iv-rail-step.is-now { color: var(--iv-you); }
.iv-rail-step.is-now .iv-rail-num { background: var(--iv-you); color: #fff; border-color: var(--iv-you); box-shadow: 0 0 0 4px var(--accent-tint); }
.iv-rail-step.is-done { color: var(--iv-good); }
.iv-rail-step.is-done .iv-rail-num { background: var(--iv-good); color: #0B2A1E; border-color: var(--iv-good); }
.iv-rail-skip { margin: 0; }
.iv-ghost-sm { font-size: 0.8rem; padding: 0.3rem 0.65rem; }
a.iv-ghost { display: inline-block; text-decoration: none; }

/* Work + side */
.iv-case-grid { display: grid; grid-template-columns: minmax(0, 7fr) minmax(300px, 5fr); gap: 1.25rem; align-items: start; }
.iv-work { border: 1px solid var(--iv-line); border-radius: var(--radius-lg); background: var(--iv-panel); padding: 1.25rem; }
.iv-work-lead { color: var(--iv-muted); margin-bottom: 1rem; max-width: 64ch; }
.iv-work-hint { color: var(--iv-muted); font-size: 0.85rem; margin-bottom: 0.5rem; }
.iv-work .btn-link { color: var(--iv-you); font-weight: 600; }
.iv-textarea { border-radius: var(--radius-md); padding: 0.85rem 1rem; line-height: 1.5; resize: vertical; }
.iv-textarea-mono { font-family: var(--font-mono); font-size: 0.9rem; }
.iv-work-foot { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-top: 0.75rem; flex-wrap: wrap; }
.iv-cta { margin-top: 0.75rem; }
.iv-advance-auto { width: auto; margin-top: 0; padding-inline: 1.25rem; }
.iv-err-box { margin-top: 0.75rem; padding: 0.6rem 0.85rem; border-radius: var(--radius-sm); background: rgba(255, 106, 77, 0.12); color: var(--iv-poor); font-size: 0.9rem; }
.iv-err-box a { color: inherit; font-weight: 700; }
.iv-side { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
.iv-side-panel { border: 1px solid var(--iv-line); border-radius: var(--radius-lg); background: var(--iv-panel); overflow: hidden; }
.iv-side-head { padding: 0.7rem 1rem; border-bottom: 1px solid var(--iv-line); }
.iv-side-findings { padding: 0.75rem 1rem; border-bottom: 1px solid var(--iv-line); }
.iv-vitals-compact { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 0.4rem; }
.iv-vitals-compact .iv-vital { padding: 0.4rem 0.55rem; }
.iv-vitals-compact .iv-vital dd { font-size: 0.95rem; }
.iv-side-log { max-height: 60vh; overflow-y: auto; padding: 0.85rem 1rem; display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.92rem; }
.iv-side-log .iv-bubble { font-size: 0.9rem; padding: 0.45rem 0.7rem; }
.iv-side-log-open { max-height: none; }
.iv-side-empty { color: var(--iv-muted); margin: 0; }
.iv-side-foot { padding: 0.6rem 1rem; border-top: 1px solid var(--iv-line); color: var(--iv-muted); font-size: 0.82rem; }
.iv-notes { margin: 0; padding: 0.5rem 1rem 0.75rem 2.25rem; font-size: 0.92rem; }
.iv-notes li { padding: 0.3rem 0; border-bottom: 1px dashed var(--iv-line); }
.iv-notes li:last-child { border-bottom: 0; }
.iv-notes li::marker { color: var(--iv-you); font-family: var(--font-mono); font-weight: 700; }
.iv-weights { list-style: none; margin: 0; padding: 0.35rem 1rem 0.5rem; font-size: 0.92rem; }
.iv-weights li { display: flex; justify-content: space-between; gap: 1rem; padding: 0.35rem 0; border-bottom: 1px dashed var(--iv-line); }
.iv-weights li:last-child { border-bottom: 0; }
.iv-weights li span:last-child { font-family: var(--font-mono); color: var(--iv-muted); }
.iv-pending-text { font-style: italic; }

/* Radio report recorder */
.iv-rec { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.5rem; flex-wrap: wrap; }
.iv-rec-btn { display: inline-flex; align-items: center; gap: 0.4rem; border: 1px solid var(--iv-poor); color: var(--iv-poor); background: transparent; font-weight: 700; padding: 0.5rem 0.9rem; border-radius: 999px; transition: background var(--transition-fast), color var(--transition-fast); }
.iv-rec-btn:hover { background: var(--iv-poor); color: #fff; }
.iv-rec-btn.is-recording { background: var(--iv-poor); color: #fff; animation: iv-rec 1.2s ease-in-out infinite; }
@keyframes iv-rec { 0%, 100% { box-shadow: 0 0 0 0 rgba(200, 50, 31, 0.35); } 50% { box-shadow: 0 0 0 8px rgba(200, 50, 31, 0); } }
.iv-rec-timer { font-family: var(--font-mono); color: var(--iv-muted); }
.iv-rec-preview { height: 36px; flex: 1 1 200px; }

/* Results */
.iv-scorecard { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 1.5rem; align-items: center; border: 1px solid var(--iv-line); border-radius: var(--radius-lg); background: var(--iv-panel); padding: 1.5rem; margin-bottom: 1.25rem; }
.iv-score-hero { position: relative; display: grid; place-items: center; width: 200px; height: 200px; margin: 0 auto; }
.iv-ring { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.iv-ring circle { fill: none; stroke-width: 9; }
.iv-ring-track { stroke: var(--iv-line); }
.iv-ring-fill { stroke: var(--iv-good); stroke-linecap: round; stroke-dasharray: calc(var(--pct) * 3.267) 326.7; transition: stroke-dasharray 1s ease-out; }
.iv-ring-fill.is-okay { stroke: var(--iv-okay); }
.iv-ring-fill.is-poor { stroke: var(--iv-poor); }
.iv-score-num { font-family: var(--font-display); font-weight: 700; font-size: 3.4rem; line-height: 1; display: flex; align-items: flex-start; }
.iv-score-num small { font-size: 1.3rem; margin-top: 0.4rem; color: var(--iv-muted); }
.iv-score-caption { position: absolute; bottom: 36px; font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--iv-muted); }
.iv-breakdown { display: flex; flex-direction: column; gap: 0.6rem; }
.iv-break-row { display: grid; grid-template-columns: minmax(140px, 1.2fr) minmax(0, 2fr) 56px 90px; gap: 0.75rem; align-items: center; }
.iv-break-name { display: flex; flex-direction: column; line-height: 1.2; }
.iv-break-name span { color: var(--iv-muted); font-size: 0.8rem; }
.iv-break-bar { height: 8px; border-radius: 999px; background: var(--iv-patient-bg); overflow: hidden; }
.iv-break-bar span { display: block; height: 100%; border-radius: 999px; background: var(--iv-good); }
.iv-break-bar span.is-okay { background: var(--iv-okay); }
.iv-break-bar span.is-poor { background: var(--iv-poor); }
.iv-break-score { font-family: var(--font-mono); font-weight: 700; text-align: right; }
.iv-break-weight { font-family: var(--font-mono); font-size: 0.75rem; color: var(--iv-muted); }
.iv-section { border: 1px solid var(--iv-line); border-radius: var(--radius-lg); background: var(--iv-panel); padding: 1.25rem; margin-bottom: 1rem; }
.iv-section-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 0.75rem; }
.iv-section-head h2 { font-family: var(--font-display); font-weight: 700; font-size: 1.4rem; margin: 0; }
.iv-subhead { font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; margin: 1.25rem 0 0.5rem; }
.iv-score-tag { font-family: var(--font-mono); font-weight: 700; font-size: 0.85rem; padding: 0.25rem 0.6rem; border-radius: 3px; border-left: 3px solid currentColor; background: var(--iv-patient-bg); color: var(--iv-good); white-space: nowrap; }
.iv-score-tag.is-okay { color: var(--iv-okay); }
.iv-score-tag.is-poor { color: var(--iv-poor); }
.iv-score-tag-sm { font-size: 0.72rem; padding: 0.15rem 0.45rem; }
.iv-criteria { list-style: none; margin: 0 0 0.75rem; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.iv-criteria li { display: grid; grid-template-columns: minmax(120px, 1fr) 44px minmax(0, 3fr); gap: 0.75rem; align-items: baseline; padding: 0.4rem 0; border-bottom: 1px dashed var(--iv-line); font-size: 0.95rem; }
.iv-criterion { font-weight: 700; }
.iv-criterion-score { font-family: var(--font-mono); font-weight: 700; text-align: right; }
.iv-criterion-note { color: var(--iv-muted); }
.iv-feedback { padding: 0.85rem 1rem; border-radius: var(--radius-md); background: var(--iv-patient-bg); }
.iv-feedback p:last-child { margin-bottom: 0; }
.iv-rated { list-style: none; margin: 0 0 0.75rem; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.iv-rated li { display: flex; gap: 0.6rem; align-items: flex-start; }
.iv-rated-mark { color: var(--iv-muted); font-size: 1.05rem; line-height: 1.3; }
.iv-rated li.is-good .iv-rated-mark { color: var(--iv-good); }
.iv-rated li.is-okay .iv-rated-mark { color: var(--iv-okay); }
.iv-rated li.is-poor .iv-rated-mark { color: var(--iv-poor); }
.iv-rated-note { color: var(--iv-muted); font-size: 0.88rem; }
.iv-answer { font-family: inherit; font-size: 0.95rem; white-space: pre-wrap; margin: 0 0 0.75rem; padding: 0.85rem 1rem; border-radius: var(--radius-md); background: var(--iv-patient-bg); color: var(--iv-ink); }
.iv-answer-mono { font-family: var(--font-mono); font-size: 0.88rem; }
.iv-notes-list { margin: 0 0 0.75rem; padding-left: 1.25rem; font-size: 0.92rem; }
.iv-notes-list li { margin-bottom: 0.25rem; }
.iv-flag { margin-top: 0.5rem; }
.iv-flag summary { cursor: pointer; color: var(--iv-muted); font-size: 0.85rem; list-style: none; }
.iv-flag summary::-webkit-details-marker { display: none; }
.iv-flag summary:hover { color: var(--iv-ink); }
.iv-flag-form { margin-top: 0.6rem; }
.iv-flag-foot { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-top: 0.5rem; flex-wrap: wrap; }
.iv-full-transcript { border: 1px solid var(--iv-line); border-radius: var(--radius-lg); background: var(--iv-panel); padding: 0.75rem 1rem; margin-bottom: 1rem; }
.iv-full-transcript summary { cursor: pointer; font-weight: 700; }
.iv-results-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; }

/* Practice menu and case list */
/* Interview budget meter: one cell per interview, lit when spent. */
.meter { display: flex; gap: 3px; height: 14px; }
.meter span { flex: 1; border-radius: 2px; background: var(--iv-patient-bg, var(--color-bg-input)); border: 1px solid var(--iv-line, var(--color-border)); }
.meter span.on { background: var(--iv-you, var(--accent)); border-color: var(--iv-you, var(--accent)); }
.meter.low span.on { background: var(--iv-okay, var(--color-warning-yellow)); border-color: var(--iv-okay, var(--color-warning-yellow)); }
.iv-stats { display: grid; grid-template-columns: minmax(200px, 1fr) minmax(0, 2fr); gap: 1rem; margin-bottom: 1.25rem; }
.iv-stat { border: 1px solid var(--iv-line); border-radius: var(--radius-lg); background: var(--iv-panel); padding: 1rem 1.1rem; display: flex; flex-direction: column; gap: 0.35rem; }
.iv-stat-row { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.iv-stat-num { font-family: var(--font-display); font-weight: 700; font-size: 2.2rem; line-height: 1; color: var(--iv-good); }
.iv-stat-num.is-okay { color: var(--iv-okay); }
.iv-stat-num.is-poor { color: var(--iv-poor); }
.iv-stat-num.is-empty { color: var(--iv-muted); }
.iv-stat-sub { color: var(--iv-muted); font-size: 0.85rem; }
.iv-stat-flag { font-size: 0.8rem; font-weight: 700; color: var(--iv-okay); }
.iv-stat-flag.is-poor { color: var(--iv-poor); }
.iv-stat .meter { margin-top: 0.4rem; }
.iv-cats { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 0.75rem; margin-bottom: 1.5rem; }
.iv-cats form { margin: 0; }
.iv-cat {
  display: flex; align-items: center; gap: 0.9rem; width: 100%; text-align: left;
  padding: 0.9rem 1rem; border: 1px solid var(--iv-line); border-radius: var(--radius-lg);
  background: var(--iv-panel); color: var(--iv-ink);
  transition: border-color var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast);
}
.iv-cat:hover:not(:disabled) { border-color: var(--iv-you); transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.iv-cat:hover:not(:disabled) .iv-cat-go { transform: translateX(3px); color: var(--iv-you); }
.iv-cat:disabled { opacity: 0.5; }
.iv-cat-icon { width: 46px; height: 46px; border-radius: var(--radius-md); display: grid; place-items: center; background: var(--accent-tint); color: var(--iv-you); font-size: 1.35rem; flex-shrink: 0; }
.iv-cat-body { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; flex: 1; }
.iv-cat-name { font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; line-height: 1.15; }
.iv-cat-count { color: var(--iv-muted); font-size: 0.82rem; }
.iv-cat-go { color: var(--iv-muted); transition: transform var(--transition-fast), color var(--transition-fast); }
.iv-recent-list { list-style: none; margin: 0.5rem 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 0.5rem; }
.iv-recent-list li { display: flex; justify-content: space-between; align-items: center; gap: 0.75rem; padding: 0.6rem 0.85rem; border: 1px solid var(--iv-line); border-radius: var(--radius-md); background: var(--iv-panel); }
.iv-recent-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.iv-recent-actions { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; }
.iv-case-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.iv-case-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.85rem 1.1rem; border: 1px solid var(--iv-line); border-radius: var(--radius-lg); background: var(--iv-panel); flex-wrap: wrap; }
.iv-case-row-body { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.iv-case-row-name { font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; }
.iv-case-row-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

@media (max-width: 991.98px) {
  .iv-case-grid { grid-template-columns: minmax(0, 1fr); }
  .iv-scorecard { grid-template-columns: 1fr; justify-items: center; }
  .iv-break-row { grid-template-columns: minmax(0, 1fr) 56px; }
  .iv-break-bar { grid-column: 1 / -1; order: 3; }
  .iv-break-weight { display: none; }
  .iv-stats { grid-template-columns: 1fr; }
}
@media (max-width: 575.98px) {
  .iv-head { flex-wrap: wrap; }
  .iv-head-right { flex-basis: 100%; justify-content: flex-start; }
  .iv-work { padding: 1rem; }
  .iv-section { padding: 1rem; }
  .iv-criteria li { grid-template-columns: minmax(0, 1fr) 44px; }
  .iv-criterion-note { grid-column: 1 / -1; }
  .iv-rail-step .iv-rail-label { display: none; }
  .iv-rail-step.is-now .iv-rail-label { display: inline; }
  .iv-rail-step + .iv-rail-step::before { width: 0.75rem; margin: 0 0.3rem; }
}
@media (pointer: coarse) {
  .iv-ghost, .iv-ghost-sm, .iv-crew-btn, .iv-rec-btn, .iv-score-tag { min-height: 36px; display: inline-flex; align-items: center; }
}
@media (prefers-reduced-motion: reduce) {
  .iv-rec-btn.is-recording { animation: none; }
  .iv-ring-fill { transition: none; }
}
