/* ==========================================================================
   PULL Design System V2
   Plan: /PULL_CSS_V2_PLAN.md   Inventory: /docs/css-migration/MIGRATION.md
   Lint: php tools/lint-css.php (must pass before any commit)

   Load order (see docs/css-migration/LAYERING.md):
     base   = Bootstrap 5.3.3 (grid + utilities only, stock, unmodified)
     legacy = empty (pull.css, lesson.css and arcade.css are retired; kept as a slot)
     v2     = this file (wins over legacy without specificity tricks)
   This file is loaded with a plain <link>, NOT @import ... layer(v2):
   it declares its own layer below. Importing it into layer(v2) would nest
   everything one level deeper (v2.v2).

   Rules: no color literals outside the two token blocks, no !important,
   dark mode only by overriding tokens, scale tokens for spacing / radius /
   font-size / shadow / motion, role-based class names, selector depth <= 2.

   Breakpoints (media queries cannot read custom properties; the lint
   enforces this list, mobile-first min-width only):
     sm 576px · md 768px · lg 992px · xl 1200px · xxl 1400px
     (Bootstrap's set, so v2 and Bootstrap responsive classes agree.
      Approved 2026-10-12; replaces the plan's 640/900/1200.)
   ========================================================================== */

@layer base, legacy, v2;

@layer v2 {

  /* ------------------------------------------------------------------------
     TOKENS: light (default)
     ------------------------------------------------------------------------ */
  :root,
  [data-theme="light"] {
    /* Surfaces */
    --page: #f7f9fa;
    --surface: #ffffff;
    --surface-2: #f7f9fa;          /* Arcade: inset / hover surface = page tone */
    --surface-3: #f1f5f9;
    --field-bg: #ffffff;
    --header-bg: #ffffff;
    --code-bg: #0f172a;            /* terminal panels stay dark in both themes */
    --code-text: #f8fafc;
    --toast-bg: #0f172a;           /* toasts stay dark in both themes */
    --toast-text: #ffffff;
    --toast-border: #334155;
    --backdrop: rgb(15 23 42 / 0.5);

    /* Theme-specific visibility (logos): use .only-light / .only-dark */
    --show-in-light: block;
    --show-in-dark: none;

    /* Borders (Arcade neutrals, approved 2026-10-12) */
    --border: #e5e5e5;
    --border-strong: #d0d7de;
    --border-width-thin: 1px;
    --border-width: 1.5px;
    --border-width-thick: 2px;

    /* Text (Arcade neutrals) */
    --text: #2b2b2b;
    --text-muted: #6e6e6e;
    --text-subtle: #9e9e9e;
    --text-on-brand: #ffffff;

    /* Brand: primary (green CTA) */
    --primary: #58cc02;
    --primary-hover: #61e002;
    --primary-shadow: #46a302;
    --primary-soft: #eafbe0;          /* Arcade */
    --primary-ink: #3b8700;

    /* Brand: accent (blue action / focus) */
    --accent: #1cb0f6;
    --accent-hover: #2ec0ff;
    --accent-shadow: #1899d6;
    --accent-soft: #e7f6fd;           /* Arcade */
    --accent-ink: #0369a1;            /* accent text on --accent-soft (nav active, user chip) */

    /* Brand: danger (red CTA) */
    --danger: #ff4b4b;
    --danger-hover: #ff5f5f;
    --danger-shadow: #d92424;
    --danger-soft: #ffeaea;           /* Arcade */
    --danger-ink: #ea2b2b;

    /* Brand: gold (sign-in CTA) */
    --text-on-gold: #2b2b2b;
    --gold: #fda701;
    --gold-hover: #fdb622;
    --gold-shadow: #c97f00;
    --bronze: #cd7f32;              /* Live Quiz podium, 3rd place */
    --bronze-shadow: #a0622a;
    --gold-soft: #fef5e6;
    --gold-pastel: #fde68a;
    --gold-pastel-hover: #fcd34d;

    /* Purple (Arcade) */
    --violet: #a855f7;
    --violet-shadow: #9333ea;
    --violet-soft: #f5edfd;

    /* Status (state pills, badges, banners) */
    --success: #16a34a;
    --success-bright: #22c55e;
    --success-ink: #15803d;
    --success-soft: #dcfce7;
    --success-border: #bbf7d0;
    --emerald: #059669;            /* distinct from --success (dE 8.9); keep or snap during the owning feature */
    --emerald-bright: #10b981;
    --emerald-ink: #065f46;
    --emerald-soft: #ecfdf5;
    --emerald-border: #a7f3d0;
    --info: #2563eb;
    --info-ink: #1d4ed8;
    --info-soft: #eff6ff;
    --info-soft-2: #dbeafe;
    --info-border: #bfdbfe;
    --sky: #0284c7;
    --sky-bright: #38bdf8;
    --sky-soft: #e0f2fe;
    --warning: #d97706;
    --warning-bright: #f59e0b;
    --warning-ink: #b45309;
    --warning-soft: #fef3c7;
    --warning-border: #fde68a;
    --error: #ef4444;
    --error-ink: #b91c1c;
    --error-soft: #fee2e2;
    --error-border: #fecaca;
    --purple: #7e22ce;
    --purple-soft: #ede9fe;
    --purple-ink: #6d28d9;
    --purple-border: #ddd6fe;

    /* Focus */
    --ring-width: 3px;

    /* Typography */
    --font-sans: 'Montserrat', system-ui, -apple-system, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    --fs-2xs: 11px;
    --fs-xs: 12px;
    --fs-sm: 13px;
    --fs-md: 14px;
    --fs-base: 15px;
    --fs-lg: 16px;
    --fs-xl: 18px;                 /* body copy */
    --fs-2xl: 20px;
    --fs-3xl: 22px;                /* h3 */
    --fs-4xl: 26px;
    --fs-5xl: 30px;                /* h2 */
    --fs-6xl: 36px;
    --fs-7xl: 44px;                /* h1 */
    --fs-8xl: 64px;                /* big clock (step 54) */
    --fw-regular: 400;
    --fw-medium: 500;
    --fw-semibold: 600;
    --fw-bold: 700;
    --fw-extrabold: 800;
    --fw-black: 900;
    --lh-none: 1;
    --lh-compact: 1.2;
    --lh-tight: 1.15;
    --lh-snug: 1.25;
    --lh-normal: 1.45;
    --lh-body: 1.6;
    --tracking-tight: -0.02em;
    --tracking-caps: 0.05em;
    --tracking-button: 0.04em;
    --tracking-wide: 0.02em;

    /* Spacing (name = multiple of 4px; Bootstrap .p-1/.p-2/.p-3/.p-4/.p-5 = --space-1/2/4/6/12) */
    --space-0-5: 2px;
    --space-1: 4px;
    --space-1-5: 6px;
    --space-2: 8px;
    --space-2-5: 10px;
    --space-3: 12px;
    --space-3-5: 14px;
    --space-4: 16px;
    --space-4-5: 18px;
    --space-5: 20px;
    --space-6: 24px;
    --space-7: 28px;
    --space-8: 32px;
    --space-10: 40px;
    --space-12: 48px;

    /* Radius */
    --radius-xs: 6px;
    --radius-sm: 8px;
    --radius-chip: 10px;
    --radius-md: 12px;
    --radius-control: 14px;        /* inputs, large buttons */
    --radius-lg: 16px;
    --radius-xl: 20px;
    --radius-2xl: 24px;            /* .card */
    --radius-pill: 999px;
    --radius-round: 50%;

    /* Elevation: tactile "press" buttons (Arcade master, approved 2026-10-12) */
    --press-depth-sm: 3px;
    --press-depth: 4px;
    --press-depth-lg: 5px;
    --press-depth-active: 1px;
    --press-depth-active-lg: 2px;
    --press-travel: 2px;
    --press-travel-lg: 3px;
    --shadow-1: 0 1px 3px rgb(15 23 42 / 0.08);
    --shadow-2: 0 2px 8px rgb(15 23 42 / 0.10);
    --shadow-3: 0 6px 20px rgb(15 23 42 / 0.14);

    /* Motion */
    --dur-instant: 80ms;
    --dur-fast: 120ms;
    --dur-base: 150ms;
    --dur-slow: 200ms;
    --dur-slower: 300ms;
    --dur-spin: 900ms;             /* one turn of a loading spinner */
    --ease: ease;
    --ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

    /* States */
    --disabled-opacity: 0.45;

    /* Highlight panel (rosters "Today" card): lime tint */
    --highlight-bg: #a3ea73;
    --highlight-border: #8be354;

    /* Lesson illustration banners: light in both themes (the artwork is drawn for a light ground) */
    --art-blue-a: #cce4ff;   --art-blue-b: #e5f5ff;
    --art-green-a: #bff5be;  --art-green-b: #e0ffe2;
    --art-pink-a: #ffcad5;   --art-pink-b: #ffe7ed;
    --art-violet-a: #dcd6ff; --art-violet-b: #f0edff;
    --art-sky-a: #b9ebff;    --art-sky-b: #e1f7ff;
    --art-gray-a: #dce1e9;   --art-gray-b: #edf0f5;

    /* Framed panel (leaderboards): blue frame around a white inner card */
    --frame-bg: #48c5f6;
    --frame-border: #28abde;
    --frame-ink: #ffffff;

    /* Identity banner (Clubhouse): photo over brand blue, same in both themes */
    --hero-bg: #1e56d4;
    --hero-ink: #ffffff;
    --hero-ink-muted: #dbe7ff;
    --hero-track: rgba(255, 255, 255, 0.28);
    --hero-shade: rgba(9, 30, 90, 0.55);
    --hero-image: url("/assets/imgs/clubhouse/hero-bg.webp");

    /* Icons and controls */
    --icon-sm: 18px;
    --icon-md: 22px;
    --icon-lg: 28px;
    --control-height: 48px;

    /* Brand logo (app header) */
    --logo-height-sm: 40px;
    --logo-height: 52px;

    /* App <main> gutters: 34 / 88 from lg up, 60 bottom below lg */
    --shell-pad-top: 34px;
    --shell-pad-bottom: 88px;
    --shell-pad-bottom-sm: 60px;

    /* Containers */
    --container-xs: 460px;
    --container-md: 900px;
    --container-xl: 1500px;

    /* Layers */
    --z-raised: 10;
    --z-header: 100;
    --z-overlay: 99999;
    --z-modal: 100000;
    --z-toast: 100010;

  }

  /* ------------------------------------------------------------------------
     TOKENS: aliases (tokens defined from other tokens)
     Declared on every themed element, not only :root: a custom property that
     uses var() is resolved where it is declared and then inherited as a fixed
     value. Re-declaring it on [data-theme] makes nested theme panels (style
     guide) resolve it against their own palette.
     ------------------------------------------------------------------------ */
  :root,
  [data-theme="light"],
  [data-theme="dark"] {
    --text-heading: var(--text);
    --focus: var(--accent);
    --ring-color: color-mix(in srgb, var(--accent) 15%, transparent);

    /* Bootstrap bridge: framework utilities read PULL tokens, so dark mode
       flows through them (Bootstrap's own [data-bs-theme] is never set). */
    --bs-body-font-family: var(--font-sans);
    --bs-body-bg: var(--page);
    --bs-body-color: var(--text);
    --bs-emphasis-color: var(--text);
    --bs-secondary-color: var(--text-muted);
    --bs-secondary-bg: var(--surface-2);
    --bs-tertiary-bg: var(--surface-3);
    --bs-border-color: var(--border);
    --bs-border-radius: var(--radius-sm);
    --bs-border-radius-sm: var(--radius-xs);
    --bs-border-radius-lg: var(--radius-md);
    --bs-border-radius-xl: var(--radius-lg);
    --bs-border-radius-xxl: var(--radius-2xl);
    --bs-border-radius-pill: var(--radius-pill);
    --bs-box-shadow-sm: var(--shadow-1);
    --bs-box-shadow: var(--shadow-2);
    --bs-box-shadow-lg: var(--shadow-3);
    --bs-focus-ring-color: var(--ring-color);
    --bs-focus-ring-width: var(--ring-width);
  }

  /* ------------------------------------------------------------------------
     TOKENS: dark (the ONLY place [data-theme="dark"] may appear)
     Values preserve the current dark UI (legacy dark palette + the most-used
     dark component values), not the plan's draft. See TOKENS.md.
     ------------------------------------------------------------------------ */
  [data-theme="dark"] {
    --show-in-light: none;
    --show-in-dark: block;

    --page: #0b1120;
    --surface: #151e32;
    --surface-2: #1e293b;
    --surface-3: #0f172a;
    --field-bg: #0d1526;
    --header-bg: #111827;

    --border: #222f49;
    --border-strong: #334155;

    --text: #f0f4f8;
    --text-muted: #94a3b8;
    --text-subtle: #64748b;

    /* Brand CTA colors stay the same in dark mode (Arcade behavior); only tints change */
    --primary-soft: #162f13;
    --primary-ink: #86efac;
    --accent-soft: #132738;
    --accent-ink: #7dd3fc;
    --frame-bg: #102743;
    --frame-border: #1e3a5f;
    --frame-ink: #e0f2fe;
    --highlight-bg: #17280f;
    --highlight-border: #2c5216;
    --danger-soft: #381616;
    --danger-ink: #fca5a5;
    --violet-soft: #28153b;

    --success-ink: #86efac;
    --success-soft: rgb(34 197 94 / 0.16);
    --success-border: #166534;
    --emerald-soft: rgb(16 185 129 / 0.16);
    --emerald-border: #059669;
    --emerald-ink: #6ee7b7;
    --info-ink: #93c5fd;
    --info-soft: rgb(37 99 235 / 0.16);
    --info-soft-2: rgb(37 99 235 / 0.24);
    --info-border: #1e3a8a;
    --sky-soft: rgb(56 189 248 / 0.16);
    --warning-ink: #fcd34d;
    --warning-soft: rgb(245 158 11 / 0.16);
    --warning-border: #92400e;
    --error-ink: #fca5a5;
    --error-soft: rgb(239 68 68 / 0.16);
    --error-border: #991b1b;
    --purple-soft: rgb(126 34 206 / 0.20);
    --purple-ink: #d8b4fe;
    --purple-border: #7e22ce;
    --gold-soft: #332408;

    --focus: var(--sky-bright);
    --ring-color: color-mix(in srgb, var(--sky-bright) 25%, transparent);
    --shadow-1: 0 1px 3px rgb(0 0 0 / 0.30);
    --shadow-2: 0 2px 8px rgb(0 0 0 / 0.35);
    --shadow-3: 0 6px 20px rgb(0 0 0 / 0.45);
  }

  /* Reduced motion: every duration token drops to zero (replaces pull.css's
     global "transition: none !important"). */
  @media (prefers-reduced-motion: reduce) {
    :root,
    [data-theme="light"],
    [data-theme="dark"] {
      --dur-instant: 0ms;
      --dur-fast: 0ms;
      --dur-base: 0ms;
      --dur-slow: 0ms;
      --dur-slower: 0ms;
    }
  }

  /* ========================================================================
     0. Base elements
     Page-wide defaults that pull.css used to set on bare elements. Wrapped in
     :where() so they have zero specificity: any class rule wins.
     ======================================================================== */

  :where(*, *::before, *::after) { box-sizing: border-box; }

  /* In-page links (#achievements) land below the pinned header, not under it. */
  @media (min-width: 1200px) {
    :where(html) { scroll-padding-top: calc(var(--logo-height) + var(--space-12)); }
  }

  :where(body) {
    margin: 0;
    background-color: var(--page);
    color: var(--text);
    font-family: var(--font-sans);
    font-size: var(--fs-xl);
    font-weight: var(--fw-regular);
    line-height: var(--lh-body);
    -webkit-font-smoothing: antialiased;
  }

  :where(h1, h2, h3, h4) { color: var(--text-heading); }
  :where(h1) { margin: 0 0 var(--space-2-5); font-size: var(--fs-7xl); font-weight: var(--fw-black); line-height: var(--lh-tight); letter-spacing: -0.015em; }
  :where(h2) { margin: 0 0 var(--space-3); font-size: var(--fs-5xl); font-weight: var(--fw-black); line-height: var(--lh-compact); letter-spacing: -0.035em; }
  :where(h3) { margin: 0 0 var(--space-2); font-size: var(--fs-3xl); font-weight: var(--fw-extrabold); line-height: var(--lh-snug); letter-spacing: -0.025em; }
  :where(p) { margin: 0 0 var(--space-4-5); color: var(--text-muted); }
  :where(strong, b) { font-weight: var(--fw-bold); }

  :where(button, input, select, textarea) { font-family: inherit; }
  :where(code) { font-family: var(--font-mono); font-size: var(--fs-md); }

  :where(table) { width: 100%; border-collapse: separate; border-spacing: 0; text-align: left; }

  /* The app <main> (layout.php, lesson.php, 404.php): page gutters */
  .app-main {
    max-width: var(--container-xl);
    margin: 0 auto;
    padding: var(--space-7) var(--space-4-5) var(--shell-pad-bottom-sm);
  }

  @media (min-width: 992px) {
    .app-main { padding: var(--shell-pad-top) var(--space-6) var(--shell-pad-bottom); }
  }

  /* ========================================================================
     1. Layout primitives (container, stack, row, grid)
     ======================================================================== */

  /* Page container inside the app <main>: width only, no spacing.
     Stack its children with .stack (or Bootstrap d-flex utilities). */
  .page {
    --page-max: var(--container-xl);
    width: 100%;
    max-width: var(--page-max);
    margin-inline: auto;
  }

  .page-md { --page-max: var(--container-md); }
  .page-xs { --page-max: var(--container-xs); }

  /* Vertical stack. Default gap 24px; change it with a .gap-* utility. */
  .stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
    min-width: 0;
  }

  /* Header row: title block left, actions right; wraps on narrow screens */
  .page-header {
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
  }

  /* Sidebar on the left, content on the right (plans, rosters).
     One column below lg; sidebar 320-400px at lg; 360-440px at xl. */
  .layout-sidebar {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-7);
    align-items: start;
  }

  /* Sidebar column: stacked panels. */
  .layout-aside {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    min-width: 0;
  }

  @media (min-width: 992px) {
    .layout-sidebar {
      grid-template-columns: minmax(320px, 400px) minmax(0, 1fr);
      gap: var(--space-4-5);
    }
  }

  @media (min-width: 1200px) {
    .layout-sidebar {
      grid-template-columns: minmax(360px, 440px) minmax(0, 1fr);
      gap: var(--space-7);
    }
  }

  .min-w-0 { min-width: 0; }

  /* Gap steps Bootstrap lacks (Bootstrap gap-1..5 = 4/8/16/24/48px).
     Named after the space token: .gap-s5 = var(--space-5) = 20px. Add a step here when a page needs one. */
  .gap-s3-5 { gap: var(--space-3-5); }
  .gap-s5   { gap: var(--space-5); }
  .gap-s7   { gap: var(--space-7); }

  /* Show an element in one theme only (logo pairs) */
  .only-light { display: var(--show-in-light); }
  .only-dark { display: var(--show-in-dark); }

  /* ========================================================================
     2. Typography and text utilities
     ======================================================================== */

  /* Page title: display size by default; -sm for utility/admin tool pages */
  .page-title {
    margin: 0;
    font-family: var(--font-sans);
    font-size: var(--fs-7xl);
    font-weight: var(--fw-black);
    line-height: var(--lh-tight);
    letter-spacing: var(--tracking-tight);
    color: var(--text-heading);
  }

  /* Page titles that a script focuses for screen readers (tabindex="-1", each lesson screen's H1)
     are not interactive, so they get no focus ring. */
  .page-title:focus { outline: none; }

  .page-title-sm {
    margin-bottom: var(--space-1-5);
    font-size: var(--fs-4xl);
    font-weight: var(--fw-extrabold);
  }

  .page-subtitle {
    margin: var(--space-1) 0 0;
    font-size: var(--fs-2xl);
    font-weight: var(--fw-medium);
    line-height: var(--lh-normal);
    color: var(--text-muted);
  }

  .page-subtitle-sm {
    margin: 0;
    font-size: var(--fs-md);
  }

  /* Small muted text for labels and captions */
  .text-caption {
    margin: 0;
    font-size: var(--fs-md);
    font-weight: var(--fw-medium);
    line-height: var(--lh-normal);
    color: var(--text-muted);
  }

  /* Section / card headings */
  .title-lg,
  .title-md,
  .title-sm {
    margin: 0;
    color: var(--text-heading);
    font-family: var(--font-sans);
    font-weight: var(--fw-black);
    line-height: var(--lh-compact);
    letter-spacing: var(--tracking-tight);
  }

  .title-lg { font-size: var(--fs-5xl); }
  .title-md { font-size: var(--fs-3xl); font-weight: var(--fw-extrabold); }
  .title-sm { font-size: var(--fs-lg); font-weight: var(--fw-extrabold); letter-spacing: normal; }

  /* Lead text under a title */
  .text-lead {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-lg);
    font-weight: var(--fw-medium);
    line-height: var(--lh-normal);
  }

  /* Small uppercase label above a title */
  .text-eyebrow {
    display: block;
    margin: 0;
    color: var(--eyebrow-color, var(--accent-ink));
    font-size: var(--fs-xs);
    font-weight: var(--fw-extrabold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
  }

  /* Running text (paragraphs in panels, previews) */
  .text-prose {
    margin: 0;
    color: var(--text);
    font-size: var(--fs-base);
    font-weight: var(--fw-medium);
    line-height: var(--lh-body);
    white-space: pre-line;
  }

  /* Emphasised value inside running text or a cell */
  .text-strong {
    color: var(--text-heading);
    font-weight: var(--fw-extrabold);
  }

  /* Small bold label (list item titles, row labels) */
  .text-label {
    color: var(--text-heading);
    font-size: var(--fs-sm);
    font-weight: var(--fw-extrabold);
  }

  /* ========================================================================
     3. Buttons and form controls
     Master: Arcade tactile buttons (approved 2026-10-12).
     Tone modifiers only set --btn-* variables; size modifiers set metrics.
     ======================================================================== */

  .btn {
    --btn-bg: var(--surface);
    --btn-bg-hover: var(--page);
    --btn-fg: var(--text);
    --btn-shadow: var(--border-strong);
    --btn-border: transparent;
    --btn-depth: var(--press-depth);
    --btn-depth-active: var(--press-depth-active);
    --btn-travel: var(--press-travel);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    margin: 0;
    padding: var(--space-2-5) var(--space-4-5);
    border: var(--border-width) solid var(--btn-border);
    border-radius: var(--radius-md);
    background-color: var(--btn-bg);
    color: var(--btn-fg);
    box-shadow: 0 var(--btn-depth) 0 var(--btn-shadow);
    font-family: var(--font-sans);
    font-size: var(--fs-md);
    font-weight: var(--fw-extrabold);
    line-height: normal;
    letter-spacing: var(--tracking-button);
    text-transform: uppercase;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: transform var(--dur-instant) var(--ease), box-shadow var(--dur-instant) var(--ease), background-color var(--dur-fast) var(--ease);
  }

  .btn:hover { background-color: var(--btn-bg-hover); color: var(--btn-fg); }

  .btn:active {
    transform: translateY(var(--btn-travel));
    box-shadow: 0 var(--btn-depth-active) 0 var(--btn-shadow);
  }

  .btn:focus-visible,
  .cover-input:focus-visible + .btn {
    outline: var(--ring-width) solid var(--focus);
    outline-offset: var(--space-0-5);
  }

  .btn:disabled,
  .btn.is-disabled {
    opacity: var(--disabled-opacity);
    cursor: not-allowed;
    pointer-events: none;
    box-shadow: none;
    transform: none;
  }

  .btn-primary { --btn-bg: var(--primary); --btn-bg-hover: var(--primary-hover); --btn-shadow: var(--primary-shadow); --btn-fg: var(--text-on-brand); }
  .btn-action  { --btn-bg: var(--accent);  --btn-bg-hover: var(--accent-hover);  --btn-shadow: var(--accent-shadow);  --btn-fg: var(--text-on-brand); }
  .btn-gold    { --btn-bg: var(--gold);    --btn-bg-hover: var(--gold-hover);    --btn-shadow: var(--gold-shadow);    --btn-fg: var(--text-on-brand); }
  .btn-danger  { --btn-bg: var(--danger);  --btn-bg-hover: var(--danger-hover);  --btn-shadow: var(--danger-shadow);  --btn-fg: var(--text-on-brand); }

  .btn-outline {
    --btn-bg: var(--surface);
    --btn-bg-hover: var(--page);
    --btn-fg: var(--text);
    --btn-border: var(--border-strong);
    --btn-shadow: var(--border-strong);
    --btn-depth: var(--press-depth-sm);
  }

  .btn-sm {
    --btn-depth: var(--press-depth-sm);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-sm);
    font-size: var(--fs-xs);
  }

  .btn-outline.btn-sm { --btn-depth: var(--press-depth-active-lg); }

  .btn-lg {
    --btn-depth: var(--press-depth-lg);
    --btn-depth-active: var(--press-depth-active-lg);
    --btn-travel: var(--press-travel-lg);
    padding: var(--space-3) var(--space-6);
    border-radius: var(--radius-control);
    font-size: var(--fs-base);
  }

  /* Quiet: no surface until hover (row actions, toolbar icons) */
  .btn-quiet {
    --btn-bg: transparent;
    --btn-bg-hover: var(--surface-3);
    --btn-fg: var(--text-muted);
    --btn-shadow: transparent;
    --btn-depth: 0;
    --btn-depth-active: 0;
    --btn-travel: 0;
  }

  /* Square icon-only button (needs aria-label) */
  .btn-icon { aspect-ratio: 1; padding: var(--space-2); }

  .btn .icon { width: var(--icon-sm); height: var(--icon-sm); }

  /* Form controls. Classes only; bare input/select/label get just the base font. */
  .form-field {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-1-5);
  }

  .form-label {
    display: block;
    margin: 0;
    color: var(--text);
    font-size: var(--fs-md);
    font-weight: var(--fw-extrabold);
    letter-spacing: normal;
    text-transform: none;
  }

  .form-hint {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
  }

  .input {
    width: 100%;
    min-height: var(--control-height);
    margin: 0;
    padding: var(--space-2-5) var(--space-3-5);
    border: var(--border-width-thick) solid var(--border-strong);
    border-radius: var(--radius-control);
    background: var(--field-bg);
    color: var(--text);
    box-shadow: none;
    font-family: inherit;
    font-size: var(--fs-base);
    font-weight: var(--fw-semibold);
    appearance: none;
    transition: border-color var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
  }

  .input:focus {
    outline: none;
    border-color: var(--focus);
    background: var(--field-bg);
    box-shadow: 0 0 0 var(--ring-width) var(--ring-color);
  }

  .input::placeholder { color: var(--text-subtle); }

  .input-lg { font-size: var(--fs-2xl); font-weight: var(--fw-extrabold); }
  /* Text box drawn with dots, so browsers do not treat it as a password to save (step 63: User Accounts page password) */
  .input-secret { -webkit-text-security: disc; }

  .input-sm {
    min-height: var(--space-10);
    padding: var(--space-1-5) var(--space-2-5);
    border-radius: var(--radius-sm);
    font-size: var(--fs-sm);
  }

  .input-short { max-width: calc(var(--space-12) * 2); }
  .input-multiline { resize: vertical; line-height: var(--lh-normal); }

  /* Checkbox / radio with its label: <label class="check"><input class="check-input"> text</label>.
     Native control tinted with --accent. */
  .check {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    color: var(--text);
    font-size: var(--fs-md);
    font-weight: var(--fw-semibold);
    letter-spacing: normal;
    text-transform: none;
    cursor: pointer;
  }

  .check-input {
    flex-shrink: 0;
    width: var(--icon-sm);
    height: var(--icon-sm);
    min-height: 0;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    accent-color: var(--accent);
    cursor: pointer;
  }

  .check-input:focus-visible { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }

  /* Toggle switch: <label class="switch"><input class="switch-input visually-hidden"><span class="switch-track"></span></label>.
     The real checkbox stays hidden but focusable; the track draws the state. */
  .switch {
    position: relative;
    display: inline-flex;
    align-items: center;
    margin: 0;
    cursor: pointer;
  }

  .switch-track {
    position: relative;
    display: inline-block;
    width: var(--space-10);
    height: var(--space-6);
    border-radius: var(--radius-pill);
    background: var(--border-strong);
    transition: background-color var(--dur-fast) var(--ease);
  }

  .switch-track::after {
    content: "";
    position: absolute;
    top: var(--space-0-5);
    left: var(--space-0-5);
    width: var(--space-5);
    height: var(--space-5);
    border-radius: var(--radius-round);
    background: var(--surface);
    box-shadow: var(--shadow-1);
    transition: transform var(--dur-fast) var(--ease);
  }

  .switch-input:checked + .switch-track { background: var(--success-bright); }
  .switch-input:checked + .switch-track::after { transform: translateX(var(--space-4)); }
  .switch-input:focus-visible + .switch-track { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }

  /* Tabs: role="tablist" > .tab[role="tab"][aria-selected]; panels toggle d-none */
  .tab-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1-5);
  }

  .tab {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1-5);
    margin: 0;
    padding: var(--space-1-5) var(--space-3-5);
    border: var(--border-width) solid var(--border-strong);
    border-radius: var(--radius-pill);
    background: var(--surface);
    color: var(--text-muted);
    box-shadow: none;
    font-family: inherit;
    font-size: var(--fs-sm);
    font-weight: var(--fw-bold);
    letter-spacing: normal;
    text-transform: none;
    cursor: pointer;
  }

  .tab:hover { color: var(--text); border-color: var(--accent); }
  .tab[aria-selected="true"],
  .tab[aria-pressed="true"],
  .tab[aria-current="page"] { border-color: var(--accent); background: var(--accent); color: var(--text-on-brand); }
  .tab:focus-visible { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }

  /* Step buttons (lesson preview): current step is aria-current="step" */
  .btn-outline[aria-current="step"] {
    --btn-bg: var(--accent);
    --btn-bg-hover: var(--accent-hover);
    --btn-fg: var(--text-on-brand);
    --btn-border: var(--accent-shadow);
    --btn-shadow: var(--accent-shadow);
  }

  /* Field with icons: .input-group > .input-adorn (+ .input-adorn-end) + .input.input-pad-start/-end */
  .input-group {
    position: relative;
    display: flex;
    align-items: center;
  }

  .input-adorn {
    position: absolute;
    left: var(--space-3-5);
    display: inline-flex;
    color: var(--text-subtle);
    pointer-events: none;
  }

  .input-adorn-end { left: auto; right: var(--space-2); pointer-events: auto; }
  .input-pad-start { padding-left: var(--space-12); }
  .input-pad-end { padding-right: var(--space-12); }

  /* Option list for type-ahead fields (role="listbox"; items role="option") */
  .menu {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: var(--z-raised);
    max-height: calc(var(--space-12) * 6);
    margin-top: var(--space-1);
    padding: var(--space-1-5);
    border: var(--border-width) solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--surface);
    box-shadow: var(--shadow-2);
    overflow-y: auto;
  }

  /* In-flow variant: pushes content down instead of floating (inside scrolling dialogs) */
  .menu-inline { position: static; margin-top: var(--space-1-5); }

  .menu-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-2-5) var(--space-3);
    border-radius: var(--radius-sm);
    color: var(--text);
    cursor: pointer;
  }

  .menu-item:hover,
  .menu-item[aria-selected="true"] { background: var(--accent-soft); }

  .menu-item[aria-disabled="true"] { opacity: var(--disabled-opacity); cursor: not-allowed; background: transparent; }

  .menu-empty {
    padding: var(--space-3-5);
    color: var(--text-muted);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    text-align: center;
  }

  /* ========================================================================
     4. Surfaces (card, panel, dialog, banner / notice)
     Arcade look: flat, 2px border, no shadow.
     ======================================================================== */

  /* Card: the one surface for panels. Margins belong to the layout, not the card. */
  .card {
    padding: var(--space-5);
    border: var(--border-width-thick) solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
    box-shadow: none;
  }

  @media (min-width: 768px) {
    .card { padding: var(--space-6); }
  }

  .card-flush { padding: 0; overflow: hidden; }

  /* Inset panel inside a card (secondary surface) */
  .card-inset {
    padding: var(--space-4-5);
    border-width: var(--border-width-thin);
    border-radius: var(--radius-md);
    background: var(--page);
  }

  /* Placeholder / coming-soon surface */
  .card-placeholder {
    border-style: dashed;
    border-color: var(--border-strong);
    background: var(--surface-2);
  }

  /* Highlight borders (Arcade featured / teacher panels) */
  .card-accent { border-color: var(--accent); }
  .card-gold { border-color: var(--gold); }

  /* Success-tinted panel (unit overview). Eyebrows inside it turn green. */
  .card-success {
    --eyebrow-color: var(--emerald-ink);
    border-color: var(--emerald-border);
    background: var(--emerald-soft);
  }

  /* Danger-tinted panel (Admin: game play stopped) */
  .card-danger {
    border-color: var(--error-border);
    background: var(--error-soft);
  }

  /* Callout: a labelled quote or key idea (essential / focus question) */
  .callout {
    --callout-bg: var(--surface);
    display: flex;
    flex-direction: column;
    gap: var(--space-1-5);
    margin: 0;
    padding: var(--space-3-5) var(--space-4-5);
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-md);
    background: var(--callout-bg);
  }

  .callout-inset { --callout-bg: var(--surface-2); }

  .callout-label {
    display: flex;
    align-items: center;
    gap: var(--space-1-5);
    color: var(--text-muted);
    font-size: var(--fs-2xs);
    font-weight: var(--fw-extrabold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
  }

  .callout-text {
    margin: 0;
    color: var(--text-heading);
    font-size: var(--fs-base);
    font-weight: var(--fw-bold);
    font-style: italic;
    line-height: var(--lh-normal);
  }

  .callout-warning { --callout-bg: var(--warning-soft); border-color: var(--warning-border); }
  .callout-info { --callout-bg: var(--info-soft); border-color: var(--info-border); }
  .callout-warning .callout-label { color: var(--warning-ink); }
  .callout-info .callout-label { color: var(--info-ink); }

  /* Disclosure (accordion item): .card.card-flush > .disclosure-header (+ .disclosure-toggle button) + .disclosure-body */
  .disclosure-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    padding: var(--space-2-5) var(--space-4);
  }

  .disclosure-toggle {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    justify-content: flex-start;
    gap: var(--space-3);
    min-width: 0;
    margin: 0;
    padding: var(--space-1) 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text);
    box-shadow: none;
    font: inherit;
    letter-spacing: normal;
    text-align: left;
    text-transform: none;
    cursor: pointer;
  }

  .disclosure-toggle:focus-visible { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }
  .disclosure-toggle .icon { color: var(--text-subtle); transition: transform var(--dur-fast) var(--ease); }
  .disclosure-toggle[aria-expanded="true"] .icon { transform: rotate(180deg); }

  .disclosure-body {
    padding: var(--space-4);
    border-top: var(--border-width) solid var(--border);
  }

  @media (min-width: 768px) {
    .disclosure-body { padding: var(--space-5) var(--space-6); }
  }

  /* Sticky save bar at the bottom of long editors. data-state="dirty" turns the dot amber. */
  .dock {
    position: sticky;
    bottom: var(--space-3);
    z-index: var(--z-header);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: var(--border-width-thick) solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
    box-shadow: var(--shadow-2);
  }

  .status-dot {
    display: inline-block;
    width: var(--space-2-5);
    height: var(--space-2-5);
    border-radius: var(--radius-round);
    background: var(--success-bright);
  }

  .dock[data-state="dirty"] .status-dot { background: var(--warning-bright); }

  .status-dot-warning { background: var(--warning-bright); }
  .status-dot-danger { background: var(--error); }
  .status-dot-muted { background: var(--text-subtle); }
  .dock[data-state="dirty"] .dock-state { color: var(--warning-ink); }

  .dock-state {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-muted);
    font-size: var(--fs-sm);
    font-weight: var(--fw-bold);
  }

  /* Scrolling list inside a panel (incident feeds). Keyboard-focusable in markup. */
  .scroll-panel {
    max-height: calc(var(--space-12) * 9);
    overflow-y: auto;
    padding-right: var(--space-1);
  }

  .scroll-panel:focus-visible { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }

  /* Illustration banner on lesson cards. Tone modifiers set --art-a / --art-b. */
  .art-banner {
    --art-a: var(--art-blue-a);
    --art-b: var(--art-blue-b);
    position: relative;
    height: calc(var(--space-12) * 3);
    overflow: hidden;
    border-radius: var(--radius-md);
    background: linear-gradient(130deg, var(--art-a), var(--art-b));
  }

  .art-banner > svg { display: block; width: 100%; height: 100%; padding-top: var(--space-2); }
  .art-banner-tag { position: absolute; top: var(--space-2-5); left: var(--space-2-5); z-index: var(--z-raised); }
  /* Uploaded lesson cover (2:1 WebP) fills the banner instead of the drawn artwork */
  .art-banner-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

  /* Game promo picture (Admin Quick Play): 8:5, rounded; falls back to the game's art tone + icon */
  .game-promo {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 8 / 5;
    overflow: hidden;
    border-radius: var(--radius-2xl);
    background: linear-gradient(130deg, var(--art-a, var(--art-blue-a)), var(--art-b, var(--art-blue-b)));
  }

  .game-promo-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

  /* Lesson cover field on the plan editor: the same 2:1 shape the card shows */
  .cover-preview {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: min(100%, 320px);
    aspect-ratio: 2 / 1;
    overflow: hidden;
    border: var(--border-width-thick) dashed var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--surface-2);
  }

  .cover-preview-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
  /* Picture inside content (worksheet Image block, step 45): never wider than its column */
  .media-img { display: block; max-width: 100%; height: auto; border-radius: var(--radius-md); background: var(--surface-2); }

  .cover-preview-empty { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--text-muted); font-size: var(--fs-sm); font-weight: var(--fw-bold); }

  .art-banner-green  { --art-a: var(--art-green-a);  --art-b: var(--art-green-b); }
  .art-banner-pink   { --art-a: var(--art-pink-a);   --art-b: var(--art-pink-b); }
  .art-banner-violet { --art-a: var(--art-violet-a); --art-b: var(--art-violet-b); }
  .art-banner-sky    { --art-a: var(--art-sky-a);    --art-b: var(--art-sky-b); }
  .art-banner-gray   { --art-a: var(--art-gray-a);   --art-b: var(--art-gray-b); }

  /* Highlight panel (lime): summary blocks that should stand out */
  .card-highlight { border-color: var(--highlight-border); background: var(--highlight-bg); }

  .card-roomy { padding: var(--space-7) var(--space-5); }

  @media (min-width: 576px) {
    .card-roomy { padding: var(--space-10) var(--space-8); }
  }

  @media (min-width: 768px) {
    .card-lg { padding: var(--space-7) var(--space-8); }
  }

  /* Notice: inline status message (save results, errors). Tone sets --notice-*. */
  .notice {
    --notice-bg: var(--info-soft);
    --notice-fg: var(--info-ink);
    --notice-border: var(--info-border);
    display: flex;
    align-items: center;
    gap: var(--space-2-5);
    padding: var(--space-3) var(--space-4-5);
    border: var(--border-width) solid var(--notice-border);
    border-radius: var(--radius-control);
    background: var(--notice-bg);
    color: var(--notice-fg);
    font-size: var(--fs-md);
    font-weight: var(--fw-bold);
    line-height: var(--lh-normal);
  }

  .notice svg {
    width: var(--space-4-5);
    height: var(--space-4-5);
    flex-shrink: 0;
    stroke: currentColor;
    fill: none;
  }

  .notice-success { --notice-bg: var(--emerald-soft); --notice-fg: var(--emerald-ink); --notice-border: var(--emerald-border); }
  .notice-danger  { --notice-bg: var(--error-soft); --notice-fg: var(--error-ink); --notice-border: var(--error-border); }
  .notice a { color: inherit; text-decoration: underline; } /* links inside a notice follow its tone */
  .notice-warning { --notice-bg: var(--warning-soft); --notice-fg: var(--warning-ink); --notice-border: var(--warning-border); }
  .notice-info    { --notice-bg: var(--info-soft); --notice-fg: var(--info-ink); --notice-border: var(--info-border); }

  /* Toasts: fixed stack bottom-right; JS adds .is-show to animate in */
  .toast-stack {
    position: fixed;
    bottom: var(--space-6);
    right: var(--space-6);
    z-index: var(--z-overlay);
    display: flex;
    flex-direction: column;
    gap: var(--space-2-5);
    pointer-events: none;
  }

  .toast {
    display: flex;
    align-items: center;
    gap: var(--space-2-5);
    padding: var(--space-3) var(--space-4-5);
    border: var(--border-width) solid var(--toast-border);
    border-radius: var(--radius-md);
    background: var(--toast-bg);
    color: var(--toast-text);
    font-size: var(--fs-sm);
    font-weight: var(--fw-bold);
    opacity: 0;
    transform: translateY(var(--space-5));
    transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
    pointer-events: auto;
  }

  .toast.is-show { opacity: 1; transform: translateY(0); }

  /* Empty state: icon, title, one line of help */
  .empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: var(--text-muted);
  }

  .empty-state-dashed {
    min-height: 320px;
    padding: var(--space-10);
    border: var(--border-width-thin) dashed var(--border-strong);
    border-radius: var(--radius-lg);
  }

  .empty-state-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-12);
    height: var(--space-12);
    margin-bottom: var(--space-3);
    color: var(--text-subtle);
  }

  .empty-state-icon svg {
    width: var(--space-8);
    height: var(--space-8);
    stroke: currentColor;
    stroke-width: 2;
    fill: none;
  }

  .empty-state-icon-accent {
    width: 64px;
    height: 64px;
    margin-bottom: var(--space-3-5);
    border-radius: var(--radius-round);
    background: var(--accent-soft);
    color: var(--accent);
  }

  .empty-state-icon-accent svg {
    width: var(--space-6);
    height: var(--space-6);
  }

  .empty-state-title {
    margin: 0 0 var(--space-1-5);
    color: var(--text-heading);
    font-size: var(--fs-xl);
    font-weight: var(--fw-extrabold);
  }

  .empty-state-text {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-md);
  }

  /* Dialog shell on a native <dialog> (open with showModal(); Esc and backdrop close it).
     Width via --dialog-w; content padding belongs to the dialog body. */
  .dialog {
    --dialog-w: 520px;
    width: min(var(--dialog-w), calc(100vw - var(--space-8)));
    max-height: calc(100vh - var(--space-8) * 2);
    margin: auto;
    padding: 0;
    border: var(--border-width-thick) solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow-3);
    overflow: auto;
  }

  .dialog::backdrop {
    background: var(--backdrop);
    backdrop-filter: blur(4px);
  }

  .dialog-lg { --dialog-w: 880px; }

  .dialog-body {
    position: relative;
    padding: var(--space-7);
  }

  .dialog-close {
    position: absolute;
    top: var(--space-4-5);
    right: var(--space-4-5);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-8);
    height: var(--space-8);
    padding: 0;
    border: 0;
    border-radius: var(--radius-chip);
    background: transparent;
    color: var(--text-subtle);
    box-shadow: none;
    cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  }

  .dialog-close:hover { background: var(--surface-3); color: var(--text); }
  .dialog-close:focus-visible { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }

  .dialog-close svg {
    width: var(--space-5);
    height: var(--space-5);
    stroke: currentColor;
  }

  /* Terminal-style read-only output (diagnostics, logs) */
  .code-block {
    margin: 0;
    padding: var(--space-5);
    border-radius: var(--radius-sm);
    background: var(--code-bg);
    color: var(--code-text);
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    line-height: var(--lh-body);
    white-space: pre-wrap;
    overflow-x: auto;
  }

  /* ========================================================================
     5. Small elements (pill, badge, avatar, icon, progress)
     ======================================================================== */

  /* Pill / status chip. Tone modifiers set --pill-* only. */
  .pill {
    --pill-bg: var(--emerald-soft);
    --pill-fg: var(--emerald-ink);
    --pill-border: var(--emerald-border);
    display: inline-flex;
    align-items: center;
    gap: var(--space-1-5);
    padding: var(--space-1) var(--space-3);
    border: var(--border-width-thin) solid var(--pill-border);
    border-radius: var(--radius-pill);
    background: var(--pill-bg);
    color: var(--pill-fg);
    font-size: var(--fs-2xs);
    font-weight: var(--fw-extrabold);
    letter-spacing: var(--tracking-button);
    line-height: var(--lh-compact);
    white-space: nowrap;
  }

  .pill-success { --pill-bg: var(--emerald-soft); --pill-fg: var(--emerald-ink); --pill-border: var(--emerald-border); }
  .pill-neutral { --pill-bg: var(--surface-3); --pill-fg: var(--text-muted); --pill-border: var(--border-strong); }
  .pill-info    { --pill-bg: var(--info-soft); --pill-fg: var(--info-ink); --pill-border: var(--info-border); }
  .pill-purple  { --pill-bg: var(--purple-soft); --pill-fg: var(--purple-ink); --pill-border: var(--purple-border); }
  .pill-warning { --pill-bg: var(--warning-soft); --pill-fg: var(--warning-ink); --pill-border: var(--warning-border); }
  .pill-danger  { --pill-bg: var(--error-soft); --pill-fg: var(--error-ink); --pill-border: var(--error-border); }

  .pill-lg {
    min-height: var(--space-10);
    padding: var(--space-1-5) var(--space-4-5);
    font-size: var(--fs-md);
    font-weight: var(--fw-extrabold);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
  }

  /* Icons (includes/icons.php ui_icon()): sized here, stroked in currentColor */
  .icon { width: var(--icon-md); height: var(--icon-md); flex-shrink: 0; }
  .icon-sm { width: var(--icon-sm); height: var(--icon-sm); }
  .icon-lg { width: var(--icon-lg); height: var(--icon-lg); }

  /* Icon on a tinted tile. Tone modifiers set --tile-* only. */
  .icon-tile {
    --tile-bg: var(--surface-3);
    --tile-fg: var(--text-muted);
    --tile-size: var(--space-12);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: var(--tile-size);
    height: var(--tile-size);
    border-radius: var(--radius-md);
    background: var(--tile-bg);
    color: var(--tile-fg);
  }

  .icon-tile-xs { --tile-size: var(--space-7); }
  .icon-tile-sm { --tile-size: var(--space-10); }
  .icon-tile-lg { --tile-size: calc(var(--space-8) * 2); }
  .icon-tile-xl { --tile-size: calc(var(--space-12) * 2.5); }
  .icon-tile-round { border-radius: var(--radius-round); }

  /* Number in a tile (unit 01, 02...) */
  .icon-tile-text { font-size: var(--fs-lg); font-weight: var(--fw-black); }
  .icon-tile-solid-accent { --tile-bg: var(--accent); --tile-fg: var(--text-on-brand); }

  .icon-tile-accent  { --tile-bg: var(--accent-soft);  --tile-fg: var(--accent-ink); }
  .icon-tile-violet  { --tile-bg: var(--purple-soft);  --tile-fg: var(--purple-ink); }
  .icon-tile-primary { --tile-bg: var(--primary-soft); --tile-fg: var(--primary-ink); }
  .icon-tile-gold    { --tile-bg: var(--gold-soft);    --tile-fg: var(--warning-ink); }
  .icon-tile-warning { --tile-bg: var(--surface);      --tile-fg: var(--warning-ink); } /* step 59: on an amber chip */
  .icon-tile-danger  { --tile-bg: var(--danger-soft);  --tile-fg: var(--danger-ink); }
  .icon-tile-success { --tile-bg: var(--emerald-soft); --tile-fg: var(--emerald-ink); }
  .icon-tile-solid-success { --tile-bg: var(--success-bright); --tile-fg: var(--text-on-brand); }

  /* Avatar frame (the image inside is .avatar-img, from student_avatar()) */
  .avatar {
    --avatar-size: var(--space-7);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: var(--avatar-size);
    height: var(--avatar-size);
    overflow: hidden;
    border-radius: var(--radius-round);
    background: var(--surface-3);
  }

  .avatar-img {
    display: block;
    flex-shrink: 0;
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: var(--radius-round);
  }

  .avatar-sm { --avatar-size: var(--space-5); }
  .avatar-lg { --avatar-size: var(--space-12); }
  .avatar-xl { --avatar-size: calc(var(--space-12) * 1.75); }

  /* Progress meter: set --meter-value (0-100%) on the element */
  .meter {
    --meter-value: 0%;
    height: var(--space-4);
    overflow: hidden;
    border-radius: var(--radius-pill);
    background: var(--surface-3);
  }

  .meter::before {
    content: "";
    display: block;
    width: var(--meter-value);
    height: 100%;
    border-radius: inherit;
    background: var(--accent);
  }

  /* Stat tile: icon tile + value / label / sub-label */
  .stat {
    display: flex;
    align-items: center;
    gap: var(--space-2-5);
    min-width: 0;
    padding: var(--space-3);
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
  }

  /* A stat tile that links somewhere */
  .stat-link {
    color: var(--text);
    text-decoration: none;
    transition: border-color var(--dur-fast) var(--ease);
  }

  .stat-link:hover { border-color: var(--accent); color: var(--text); }
  .stat-link:focus-visible { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }

  /* Reserved tile in a stat grid (keeps rows balanced until a metric is chosen) */
  .stat-placeholder { border-style: dashed; background: transparent; color: var(--text-subtle); }
  .stat-placeholder .stat-value,
  .stat-placeholder .stat-label { color: var(--text-subtle); }

  .stat-value {
    display: block;
    color: var(--text-heading);
    font-size: var(--fs-3xl);
    font-weight: var(--fw-black);
    line-height: var(--lh-compact);
  }

  /* Big centered number (Dashboard class clock, step 54) */
  .stat-value-display { font-size: var(--fs-8xl); font-variant-numeric: tabular-nums; }

  .stat-label {
    display: block;
    color: var(--text);
    font-size: var(--fs-sm);
    font-weight: var(--fw-extrabold);
    line-height: var(--lh-compact);
  }

  .stat-sub {
    display: block;
    color: var(--text-muted);
    font-size: var(--fs-xs);
    font-weight: var(--fw-medium);
  }

  /* Meter tones */
  .meter-success::before { background: var(--success); }

  /* Identity banner: avatar, name, level and level meter over a photo. The avatar is a
     full-height square fixed to the banner's left end: the banner's rounded corners frame
     it on the left, its right edge is flat (negative margins cancel the padding). */
  .hero-banner {
    --hero-pad-y: var(--space-5);
    --hero-pad-x: var(--space-5);
    display: flex;
    align-items: center;
    gap: var(--space-5);
    min-height: calc(var(--space-12) * 3);
    padding: var(--hero-pad-y) var(--hero-pad-x);
    overflow: hidden;
    border-radius: var(--radius-xl);
    background-color: var(--hero-bg);
    background-image: linear-gradient(90deg, var(--hero-shade), transparent), var(--hero-image);
    background-position: center, right center;
    background-size: cover;
    color: var(--hero-ink);
  }

  .hero-banner .avatar {
    flex-shrink: 0;
    align-self: stretch;
    width: calc(var(--space-12) * 3);
    height: auto;
    margin: calc(-1 * var(--hero-pad-y)) 0 calc(-1 * var(--hero-pad-y)) calc(-1 * var(--hero-pad-x));
    border-radius: 0;
  }

  .hero-banner .avatar-img { border-radius: 0; }

  .hero-banner .meter { background: var(--hero-track); }
  .hero-title { margin: 0; color: var(--hero-ink); font-size: var(--fs-3xl); font-weight: var(--fw-black); line-height: var(--lh-compact); }
  .hero-text { color: var(--hero-ink-muted); font-size: var(--fs-sm); font-weight: var(--fw-bold); }

  @media (min-width: 768px) {
    .hero-banner { --hero-pad-y: var(--space-6); --hero-pad-x: var(--space-7); }
  }

  /* Achievement badge artwork (Clubhouse achievements and Next Up) */
  .achievement-img { flex-shrink: 0; width: calc(var(--space-12) * 1.5); height: auto; aspect-ratio: 1; }
  .achievement-img-lg { flex-shrink: 0; width: calc(var(--space-12) * 2.5); height: auto; aspect-ratio: 1; object-fit: contain; }
  .achievement-img-sm { flex-shrink: 0; width: var(--space-10); height: auto; aspect-ratio: 1; }

  /* Arcade player: full-screen overlay with a slim bar over the game iframe. Rendered with
     data-theme="dark" so it always uses the dark tokens. */
  .game-overlay {
    position: fixed;
    inset: 0;
    z-index: var(--z-overlay);
    display: flex;
    flex-direction: column;
    background: var(--page);
    color: var(--text);
  }

  .game-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
    border-bottom: var(--border-width) solid var(--border);
    background: var(--surface);
  }

  .game-stage { display: flex; flex: 1 1 auto; min-height: 0; padding: var(--space-2); }
  .game-iframe { flex: 1 1 auto; width: 100%; height: 100%; border: 0; border-radius: var(--radius-md); background: var(--page); }

  /* Independent Game Library tabs; score-filter pills retain their shared style. */
  .game-library { min-width: 0; }

  .game-library-tabs {
    flex-wrap: nowrap;
    gap: var(--space-2);
    overflow-x: auto;
    scrollbar-width: none;
  }
  .game-library-tabs::-webkit-scrollbar { display: none; }

  .game-library-tabs > .tab {
    flex: 1 0 auto;
    min-height: var(--space-12);
    padding: var(--space-2) var(--space-3);
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-xl);
    font-weight: var(--fw-extrabold);
    white-space: nowrap;
  }
  .game-library-tabs > .tab:hover {
    background: var(--surface-3);
    color: var(--text);
  }
  .game-library-tabs > .tab:active {
    background: var(--surface-2);
  }
  .game-library-tabs > .tab[aria-selected="true"] {
    background: var(--gold-pastel);
    color: var(--text-on-gold);
    box-shadow: none;
  }
  .game-library-tabs > .tab[aria-selected="true"]:active {
    background: var(--gold-pastel-hover);
  }
  .game-library-tabs > .tab:focus-visible {
    outline-offset: calc(-1 * var(--ring-width));
  }

  .game-library-panel {
    padding-top: var(--space-3);
  }

  /* Game library banner art (image, or .art-banner with a large emoji) */
  .game-banner { display: block; width: 100%; height: auto; aspect-ratio: 16 / 5; border-radius: var(--radius-md); object-fit: cover; }
  .art-banner-icon { font-size: var(--fs-7xl); line-height: var(--lh-compact); }

  /* Small game icon next to a game name */
  .game-favicon { width: var(--icon-lg); height: var(--icon-lg); border-radius: var(--radius-sm); object-fit: contain; }

  /* Choice card: a selectable tile (avatar styles, theme modes). Either a <label> wrapping a
     visually hidden .choice-input radio, or an element with role="radio" + aria-checked.
     .choice-check (a check icon) shows only on the selected card. */
  .choice-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-2-5);
    border: var(--border-width-thick) solid var(--border);
    border-radius: var(--radius-lg);
    margin: 0;
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-base);
    font-weight: var(--fw-medium);
    letter-spacing: normal;
    text-transform: none;
    cursor: pointer;
    transition: border-color var(--dur-fast) var(--ease);
  }

  .choice-card:hover { border-color: var(--accent); }
  .choice-card[aria-checked="true"],
  .choice-card:has(.choice-input:checked) { border-color: var(--accent); background: var(--accent-soft); }
  .choice-card:focus-visible,
  .choice-card:has(.choice-input:focus-visible) { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }
  .choice-card[aria-disabled="true"] { border-color: var(--border); background: var(--surface-2); color: var(--text-muted); cursor: default; }
  .choice-card:has(.choice-input:disabled) { cursor: default; }

  .choice-check { display: none; color: var(--accent-ink); }
  .choice-card[aria-checked="true"] .choice-check,
  .choice-card:has(.choice-input:checked) .choice-check { display: inline-flex; }

  .choice-img { width: 100%; height: auto; aspect-ratio: 1; border-radius: var(--radius-md); background: var(--surface-2); object-fit: contain; }

  /* Theme preview: a tiny page drawn with the tokens of the theme set on it (data-theme="light|dark") */
  .theme-swatch {
    position: relative;
    display: block;
    flex: 1 1 0;
    height: calc(var(--space-12) * 1.25);
    overflow: hidden;
    border: var(--border-width-thin) solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--page);
  }

  .theme-swatch::before { content: ""; position: absolute; inset: 0 0 auto; height: 30%; background: var(--surface); }
  .theme-swatch::after { content: ""; position: absolute; bottom: 18%; left: 14%; width: 44%; height: 26%; border-radius: var(--radius-xs); background: var(--accent); }
  .theme-swatch-pair { display: flex; gap: var(--space-0-5); }

  /* The hidden attribute must win over component display rules (scripts set el.hidden) */
  .btn[hidden],
  .notice[hidden],
  .pill[hidden],
  .chip[hidden] { display: none; }

  /* Status chip: small icon tile + value over a label (lesson header) */
  .chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1-5) var(--space-3) var(--space-1-5) var(--space-1-5);
    border-radius: var(--radius-pill);
    background: var(--surface-2);
    color: var(--text);
  }

  .chip-value {
    display: block;
    color: var(--text-heading);
    font-size: var(--fs-sm);
    font-weight: var(--fw-extrabold);
    line-height: var(--lh-compact);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  /* Amber status chip (step 59: Chromebook collection "Pack Up") */
  .chip-warning { background: var(--warning-soft); }

  .chip-label {
    display: block;
    color: var(--text-muted);
    font-size: var(--fs-xs);
    font-weight: var(--fw-medium);
    line-height: var(--lh-compact);
    white-space: nowrap;
  }

  /* Lesson complete celebration: full-screen backdrop, animation layer, centered card */
  .celebration {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    background: var(--backdrop);
  }

  .celebration-stage { position: absolute; inset: 0; pointer-events: none; }
  .celebration-panel { position: relative; width: 100%; max-width: var(--container-xs); }

  /* Info-tinted panel (lesson "Your Turn" responses) */
  .card-info { border-color: var(--info-border); background: var(--info-soft); }

  /* A question or focus prompt shown as reading text */
  .text-question {
    margin: 0;
    color: var(--text-heading);
    font-size: var(--fs-xl);
    font-weight: var(--fw-medium);
    line-height: var(--lh-normal);
  }

  /* Missing answer, flagged by the lesson player (aria-invalid / data-invalid) */
  .input[aria-invalid="true"] { border-color: var(--error); }
  .card[data-invalid="true"] { border-color: var(--error); box-shadow: 0 0 0 var(--ring-width) var(--error-soft); }

  /* Answer option: <label class="answer"><input class="answer-input visually-hidden"> letter + text */
  .answer {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin: 0;
    padding: var(--space-2-5) var(--space-3);
    border: var(--border-width-thick) solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-base);
    font-weight: var(--fw-medium);
    letter-spacing: normal;
    text-transform: none;
    cursor: pointer;
    transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
  }

  .answer:hover { border-color: var(--accent); }
  .answer:has(.answer-input:checked) { border-color: var(--accent); background: var(--accent-soft); }
  .answer:has(.answer-input:focus-visible) { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }
  .answer:has(.answer-input:disabled) { cursor: default; }
  .answer:has(.answer-input:disabled):hover { border-color: var(--border); }

  .answer-letter {
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    width: var(--space-8);
    height: var(--space-8);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text-heading);
    font-weight: var(--fw-black);
  }

  .answer:has(.answer-input:checked) .answer-letter { background: var(--accent); color: var(--text-on-brand); }

  /* Live Quiz (step 39): big answer tiles on the scholar's screen (<button>) and on the board (<div>).
     aria-pressed="true" = the scholar's pick; data-state="correct" | "wrong" after the reveal.
     Letter tones (red / blue / gold / green) match the board to the scholar's buttons. */
  .answer-lg {
    width: 100%;
    min-height: calc(var(--space-12) * 1.5);
    padding: var(--space-3) var(--space-4);
    font-size: var(--fs-2xl);
    font-weight: var(--fw-bold);
    text-align: start;
  }

  /* Board tiles (.answer-static) and locked buttons do not light up on hover (zero-specificity
     :where, so the pick / correct / wrong states below still win) */
  .answer-static { cursor: default; }
  .answer-lg:disabled { cursor: default; }
  .answer-lg:where(:disabled, .answer-static):hover { border-color: var(--border); }
  .answer-lg .answer-letter { width: var(--space-10); height: var(--space-10); font-size: var(--fs-2xl); }
  .answer[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
  .answer[data-state="correct"] { border-color: var(--success); background: var(--success-soft); }
  .answer[data-state="wrong"] { opacity: var(--disabled-opacity); }
  .answer[data-state="wrong"][aria-pressed="true"] { border-color: var(--error); background: var(--error-soft); opacity: 1; }

  .answer-letter-danger  { background: var(--danger); color: var(--text-on-brand); }
  .answer-letter-accent  { background: var(--accent); color: var(--text-on-brand); }
  .answer-letter-gold    { background: var(--gold); color: var(--text-on-brand); }
  .answer-letter-primary { background: var(--primary); color: var(--text-on-brand); }

  /* Podium: top three, 1st in the middle (order-* utilities in the markup). Each place sets the
     step's height and tone; the step rises in (no motion when reduced motion is on). */
  .podium {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: end;
    gap: var(--space-3);
    width: 100%;
    max-width: var(--container-md);
    margin-inline: auto;
  }

  .podium-place {
    --podium-height: var(--space-12);
    --podium-bg: var(--surface);
    --podium-border: var(--border-strong);
    --podium-shadow: var(--border-strong);
    --podium-ink: var(--text-heading);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
    text-align: center;
  }

  /* Steps are tactile blocks like .btn: solid tone, darker bottom edge. 1st gold, 2nd gray (outline), 3rd bronze. */
  .podium-1 { grid-column: 2; --podium-height: calc(var(--space-12) * 2.5); --podium-bg: var(--gold); --podium-border: var(--gold); --podium-shadow: var(--gold-shadow); --podium-ink: var(--text-on-brand); }
  .podium-2 { grid-column: 1; --podium-height: calc(var(--space-12) * 1.75); }
  .podium-3 { grid-column: 3; --podium-height: calc(var(--space-12) * 1.25); --podium-bg: var(--bronze); --podium-border: var(--bronze); --podium-shadow: var(--bronze-shadow); --podium-ink: var(--text-on-brand); }

  .podium-step {
    display: flex;
    justify-content: center;
    width: 100%;
    height: var(--podium-height);
    margin-bottom: var(--press-depth-lg);
    padding-top: var(--space-3);
    border: var(--border-width) solid var(--podium-border);
    border-radius: var(--radius-lg);
    background: var(--podium-bg);
    color: var(--podium-ink);
    box-shadow: 0 var(--press-depth-lg) 0 var(--podium-shadow);
    font-size: var(--fs-5xl);
    font-weight: var(--fw-black);
    line-height: var(--lh-none);
    transform-origin: bottom;
    animation: podium-rise var(--dur-slower) var(--ease-out) both;
  }

  @keyframes podium-rise { from { transform: scaleY(0); } }

  /* Celebration animation over the page with no backdrop or card (Live Quiz podium) */
  .celebration-layer { position: fixed; inset: 0; z-index: var(--z-overlay); pointer-events: none; }

  /* Star rating: <label class="star"><input class="star-input visually-hidden"><svg class="star-icon"> */
  .star-scale { display: flex; flex-wrap: wrap; gap: var(--space-1); }

  .star {
    display: inline-flex;
    margin: 0;
    padding: var(--space-0-5);
    border-radius: var(--radius-sm);
    color: var(--text-subtle);
    cursor: pointer;
  }

  .star-icon { width: var(--space-8); height: var(--space-8); fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linejoin: round; }
  .star[data-on="true"],
  .star[data-hover="true"] { color: var(--gold); }
  .star[data-on="true"] .star-icon,
  .star[data-hover="true"] .star-icon { fill: currentColor; }
  .star:has(.star-input:focus-visible) { outline: var(--ring-width) solid var(--focus); }

  /* Video: 16:9 box; the player script mounts an iframe or <video> inside */
  .video-frame {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--radius-lg);
    background: var(--surface-3);
  }

  .video-frame > * { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

  /* Loading spinner (stops spinning when motion is reduced) */
  .spinner {
    width: var(--space-8);
    height: var(--space-8);
    border: var(--border-width-thick) solid var(--border);
    border-top-color: var(--accent);
    border-radius: var(--radius-round);
    animation: spin var(--dur-spin) linear infinite;
  }

  @keyframes spin { to { transform: rotate(360deg); } }

  @media (prefers-reduced-motion: reduce) {
    .spinner { animation: none; }
  }

  /* Framed panel: a colored frame with the title on the frame and the content in an
     inner .card. Markup: .card-frame > .card-frame-title + .card. The title class comes
     after .title-* in this file, so it can sit on the same element and set the color. */
  .card-frame {
    display: flex;
    flex-direction: column;
    padding: 0 var(--space-2) var(--space-2);
    border: var(--border-width-thick) solid var(--frame-border);
    border-radius: var(--radius-xl);
    background: var(--frame-bg);
  }

  .card-frame-title { padding: var(--space-4) var(--space-3); color: var(--frame-ink); }
  .card-frame > .card { flex-grow: 1; }

  /* Leaderboard: ranked rows (rank, avatar, name + meter, value) */
  .leaderboard {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    list-style: none; /* .list-unstyled is not in the loaded Bootstrap files; the "…" gap row showed a marker */
  }

  .leaderboard-row {
    display: grid;
    grid-template-columns: var(--space-7) auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-2-5);
  }

  .leaderboard-row[aria-current="true"] {
    margin: calc(-1 * var(--space-1-5));
    padding: var(--space-1-5);
    border-radius: var(--radius-sm);
    background: var(--accent-soft);
  }

  .leaderboard-rank {
    color: var(--text-muted);
    font-size: var(--fs-lg);
    font-weight: var(--fw-black);
    text-align: center;
  }

  .leaderboard-name {
    overflow: hidden;
    color: var(--text-heading);
    font-size: var(--fs-sm);
    font-weight: var(--fw-extrabold);
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  .leaderboard-value {
    color: var(--text-heading);
    font-size: var(--fs-sm);
    font-weight: var(--fw-extrabold);
    white-space: nowrap;
  }

  /* Data table. Classes on <table> only; cells are styled through it. */
  .table-wrap {
    overflow-x: auto;
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-lg);
  }

  .table {
    width: 100%;
    margin: 0;
    border-collapse: collapse;
    border-spacing: 0;
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-md);
    text-align: left;
  }

  .table th {
    padding: var(--space-3) var(--space-4);
    border-bottom: var(--border-width) solid var(--border);
    background: var(--surface-2);
    color: var(--text-muted);
    font-size: var(--fs-xs);
    font-weight: var(--fw-extrabold);
    letter-spacing: var(--tracking-wide);
    text-transform: none;
    white-space: nowrap;
  }

  .table [aria-current="true"] { background: var(--accent-soft); }

  .table td {
    padding: var(--space-3) var(--space-4);
    border-top: var(--border-width-thin) solid var(--border);
    border-bottom: 0;
    color: var(--text);
    font-weight: var(--fw-medium);
    vertical-align: middle;
  }

  /* Many-column tables keep a usable width and scroll inside .table-wrap on phones */
  .table-wide { min-width: calc(var(--space-12) * 15); }

  /* Sortable column header: <th aria-sort><button class="sort-button"> */
  .sort-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1-5);
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--radius-xs);
    background: transparent;
    color: inherit;
    box-shadow: none;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    cursor: pointer;
  }

  .sort-button:hover { color: var(--text); }
  .sort-button:focus-visible { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }

  .sort-icon { color: var(--text-subtle); }
  [aria-sort="ascending"] .sort-icon,
  [aria-sort="descending"] .sort-icon { color: var(--accent); }

  /* Selectable card link (section picker). Current item: aria-current="page". */
  .option-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-3-5);
    padding: var(--space-2-5) var(--space-3-5);
    border: var(--border-width) solid var(--border-strong);
    border-radius: var(--radius-lg);
    background: var(--surface);
    margin: 0;
    color: var(--text);
    font-size: var(--fs-base);
    font-weight: var(--fw-medium);
    letter-spacing: normal;
    text-decoration: none;
    text-transform: none;
    cursor: pointer;
    transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
  }

  /* Tighter rows for short link lists (Admin Quick Actions) */
  .option-card-compact { padding-block: var(--space-2); }

  .option-card:hover { border-color: var(--accent); background: var(--surface-2); color: var(--text); }

  .option-card[aria-current="page"] {
    border-color: var(--accent);
    background: var(--accent-soft);
  }

  .option-card:focus-visible { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-0-5); }

  .option-card-title {
    display: block;
    color: var(--text-heading);
    font-size: var(--fs-base);
    font-weight: var(--fw-extrabold);
  }

  .option-card-text {
    display: block;
    overflow: hidden;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  .option-card-meta {
    color: var(--text-muted);
    font-size: var(--fs-2xs);
    font-weight: var(--fw-semibold);
    line-height: var(--lh-compact);
    text-align: right;
  }

  .option-card[aria-current="page"] .option-card-meta { color: var(--accent-ink); }

  /* Style guide only: a color sample fed by --swatch */
  .swatch {
    display: block;
    height: var(--space-10);
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--swatch);
  }

  .swatch-label {
    display: block;
    margin-top: var(--space-1);
    overflow: hidden;
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--fs-2xs);
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  /* ========================================================================
     6. Navigation (header, sidebar, tabs)
     ======================================================================== */

  /* App header (includes/layout.php). Mobile: brand + identity on one row,
     nav below it as a horizontally scrolling strip. xl+: one row. */
  .app-header {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas: "brand identity" "nav nav";
    align-items: center;
    justify-content: normal;
    gap: var(--space-3) var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-bottom: var(--border-width-thick) solid var(--border);
    background-color: var(--header-bg);
    color: var(--text);
  }

  .app-brand {
    grid-area: brand;
    display: inline-flex;
    border-radius: var(--radius-md);
  }

  .app-logo {
    width: auto;
    height: var(--logo-height-sm);
    max-width: none;
    object-fit: contain;
    transition: transform var(--dur-slow) var(--ease-spring);
  }

  .app-brand:hover .app-logo { transform: scale(1.06); }

  .app-nav {
    grid-area: nav;
    display: flex;
    gap: var(--space-1);
    min-width: 0;
    margin: calc(-1 * var(--space-1));
    padding: var(--space-1);
    overflow-x: auto;
    scrollbar-width: none;
  }

  .app-nav-link {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    padding: var(--space-2) var(--space-3-5);
    border-radius: var(--radius-md);
    color: var(--text-muted);
    font-size: var(--fs-md);
    font-weight: var(--fw-bold);
    white-space: nowrap;
    text-decoration: none;
    transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  }

  .app-nav-link:hover { background-color: var(--surface-2); color: var(--text); }

  .app-nav-link[aria-current="page"] {
    background-color: var(--accent-soft);
    color: var(--accent-ink);
    font-weight: var(--fw-extrabold);
  }

  .app-identity {
    grid-area: identity;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
  }

  /* Profile chip. A student's avatar fills the chip's left end: a circle as tall as the
     chip, flush with its rounded edge (negative margins cancel the padding). The chip's
     size is set by --chip-pad-y/x and --chip-fs, so the avatar can match it exactly. */
  .user-chip {
    --chip-pad-y: var(--space-1-5);
    --chip-pad-x: var(--space-3-5);
    --chip-fs: var(--fs-md);
    display: inline-flex;
    align-items: center;
    gap: var(--space-2-5);
    min-width: 0;
    padding: var(--chip-pad-y) var(--chip-pad-x);
    border-radius: var(--radius-pill);
    background-color: var(--accent-soft);
    color: var(--accent-ink);
    font-size: var(--chip-fs);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    white-space: nowrap;
    text-decoration: none;
    transition: background-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
  }

  .user-chip:hover { background-color: var(--info-soft-2); color: var(--accent-ink); transform: translateY(-1px); }

  .user-chip-avatar {
    --chip-height: calc(var(--chip-fs) * var(--lh-body) + 2 * var(--chip-pad-y));
    display: inline-flex;
    flex-shrink: 0;
    width: var(--chip-height);
    height: var(--chip-height);
    margin-block: calc(-1 * var(--chip-pad-y));
    margin-inline-start: calc(-1 * var(--chip-pad-x));
    overflow: hidden;
    border-radius: var(--radius-round);
  }

  /* Header status chips (step 51): icon + value only, the label line (Today,
     This Week, period name) returns from xxl up, where it fits beside the nav. */
  .app-identity .chip-label { display: none; }

  @media (min-width: 1400px) {
    .app-identity .chip-label { display: block; }
  }

  /* Spot in a short line (step 54: the bathroom line on the Dashboard). One icon over a
     word; data-slot-state = open | taken | you | closed sets the tone. */
  .slot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface);
    color: var(--text-subtle);
  }

  .slot-label {
    font-size: var(--fs-xs);
    font-weight: var(--fw-extrabold);
    line-height: var(--lh-compact);
    text-transform: uppercase;
    letter-spacing: var(--tracking-caps);
  }

  .slot[data-slot-state="open"] { border-color: var(--emerald-border); background: var(--emerald-soft); color: var(--emerald-ink); }
  .slot[data-slot-state="you"] { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink); }
  .slot[data-slot-state="taken"] { color: var(--text-muted); }
  .slot[data-slot-state="closed"] { opacity: var(--disabled-opacity); }
  /* Bare icon spot, no frame (Admin dashboard bathroom line, step 56b) */
  .slot.slot-compact { padding: 0; border: 0; background: transparent; color: var(--text-subtle); opacity: 1; }
  .slot.slot-compact[data-slot-state="taken"] { color: var(--accent); } /* staff: icons only, gray = free, highlight = taken (step 56b) */

  /* A chip that is a button (step 53: the scholar's bathroom line button). Its label
     line (passes left) always shows; it replaced the Arcade passes chip. */
  .chip-button {
    border: 0;
    font: inherit;
    text-align: start;
    cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
  }

  .chip-button .chip-label { display: block; }
  .chip-button:hover:not([aria-disabled="true"]) { background-color: var(--surface-3); transform: translateY(-1px); }
  .chip-button[aria-disabled="true"] { cursor: default; }
  .chip-button[aria-busy="true"] { cursor: progress; }
  .chip-button:focus-visible { outline: var(--ring-width) solid var(--focus); outline-offset: 0; }

  .app-brand:focus-visible,
  .app-nav-link:focus-visible,
  .user-chip:focus-visible {
    outline: var(--ring-width) solid var(--focus);
    outline-offset: 0;
  }

  @media (min-width: 768px) {
    .app-header { padding: var(--space-4) var(--space-6); }
    .app-logo { height: var(--logo-height); }
    .app-identity { gap: var(--space-3); }
    .user-chip { --chip-pad-y: var(--space-2); --chip-pad-x: var(--space-4); --chip-fs: var(--fs-lg); }
  }

  @media (min-width: 1200px) {
    .app-header {
      grid-template-columns: auto minmax(0, 1fr) auto;
      grid-template-areas: "brand nav identity";
      column-gap: var(--space-7);
      padding: var(--space-4-5) var(--space-10);
    }
  }

  /* Pinned header (step 50). From xl up the header is one row, so it stays at
     the top while the page scrolls. Below xl it is two rows and scrolls away.
     (Step 51 moved the one-row layout from lg to xl to make room for the chips.)
     Pages opt out with page_start(..., ['sticky_header' => false]), which adds
     .app-header-static (live quiz). Lessons and the game frame have no header. */
  @media (min-width: 1200px) {
    .app-header {
      position: sticky;
      top: 0;
      z-index: var(--z-header);
    }

    .app-header-static { position: static; }
  }

  /* ========================================================================
     7. Page-level compositions (only what Bootstrap + 1-6 cannot express)
     ======================================================================== */

  /* 404 page: the shipwreck animation links home, with one button under it */
  .error-page {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2-5);
    min-height: 100vh;
    text-align: center;
  }

  .error-art {
    display: block;
    width: min(1000px, 94vw);
    border-radius: var(--radius-2xl);
    transition: transform var(--dur-slow) var(--ease);
  }

  .error-art:hover { transform: scale(1.015); }
  .error-art:focus-visible { outline: var(--ring-width) solid var(--focus); outline-offset: var(--space-2); }

  .error-art-stage {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    aspect-ratio: 1620 / 1080;
  }

  /* Sign-in page */
  .auth-page {
    gap: var(--space-10);
    padding-block: var(--space-12);
  }

  .auth-logo {
    width: 260px;
    max-width: 85vw;
    height: auto;
    aspect-ratio: 3 / 2;
    margin: 0 auto var(--space-4-5);
    object-fit: contain;
    transition: transform var(--dur-slow) var(--ease-spring);
  }

  .auth-logo:hover { transform: scale(1.04) rotate(-1deg); }

  /* Style guide: one themed column ([data-theme] set on the element itself) */
  .theme-panel {
    padding: var(--space-6);
    border: var(--border-width-thick) solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--page);
    color: var(--text);
  }

  /* Career badges: faceted purple edge, shared by library and student views. */
  .achievement-career {
    border: var(--border-width-thick) solid var(--purple-border);
    background: linear-gradient(135deg, var(--purple-soft), var(--surface), var(--purple-soft));
    box-shadow: inset var(--space-1) var(--space-1) 0 var(--purple-border), inset calc(-1 * var(--space-1)) calc(-1 * var(--space-1)) 0 var(--violet-shadow);
  }
}
