/* ---- Self-hosted type system ---------------------------------------- */
@font-face {
  font-family: 'Albert Sans Variable';
  font-style: normal;
  font-display: optional;
  font-weight: 100 900;
  src: url('/fonts/albert-sans-latin-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'DM Serif Display';
  font-style: normal;
  font-display: optional;
  font-weight: 400;
  src: url('/fonts/dm-serif-display-latin-400-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
/* ---- End self-hosted type system ------------------------------------ */
/* =====================================================================
   v9.1-rebrand · Cream & Sage v4 (light) + Forest Floor v2.1 (dark)
   See DESIGN-SYSTEM.md §1 for the canonical palette + four-tier surface
   hierarchy. Pure white / pure black are reserved for inputs, code, and
   small inset wells only — primary cards live on warm tones in both modes.
   ===================================================================== */
:root{
  color-scheme:light;
  /* §1 Surfaces — 4 canonical tiers (WS3 semantic ladder, v9.1)
     PAGE  → --bg              full-screen background (warm paper)
     CARD  → --surface         primary content surface (cards, rows, inputs)
     FLOAT → --surface-elevated elevated above content (modals, sheets, cinema card, floating banners, hover-lift)
     INPUT → --surface-bright  pure-white role — form inputs + code blocks only (RARE)
     Legacy aliases (correct resolution, kept for back-compat — prefer canonical tokens in new code):
       --surface-alt  → var(--surface-elevated)   (FLOAT alias)
       --surface-alt2 → var(--surface)             (CARD  alias)
     Anti-patterns: §11 — do not use --bg for cards; --surface for floats; invent new tiers. */
  --bg-sunken:#E5E0D2;             /* SUNKEN — below page (rare; wells, sunken trays). WS11 v9.7-foundation 2026-05-19. */
  --bg:#EFEBE0;                    /* PAGE  — warm paper */
  --surface:#F5F1E6;               /* CARD  — primary card surface */
  --surface-elevated:#F8F5EE;      /* FLOAT — hover lift, modals, sheets, cinema card, banners */
  --surface-floating:var(--surface-elevated); /* TOP-FLOAT — modal/sheet ceiling. Light: aliases to FLOAT (plenty of contrast headroom). Dark block overrides with a visibly higher rung. WS11 v9.7-foundation. */
  --surface-bright:#FFFFFF;        /* INPUT — pure white (RARE) */
  /* utility pivots — general-purpose text-on-accent + color-mix use in component
     CSS (distinct from --surface-bright's RARE form-input role). WS11. */
  --white:#fff;
  --black:#000;
  --border:#DCD5C4; --border-strong:#BFB6A0;
  --text:#1F1D1A; --text-muted:#57524A; --text-faint:#6B6457; /* WS10-fix: was #857F71 (3.1:1 FAIL on #EFEBE0) → 5.0:1 AA body ✓ */
  /* WS11 v9.7-foundation (2026-05-19) — Stronger-than-muted text for places
     where opacity stacks were used to dim secondary content (cloze siblings,
     captions, tooltips). Pre-mixed to ≥4.5:1 AA body so consumers never need
     `opacity:` to look "calm". Light #3F3A33 = 10.6:1 on cream paper ✓ AAA. */
  --text-muted-strong:#3F3A33;
  /* WS11 v9.7-foundation — Disabled-state foreground. Use on icons/labels that
     are intentionally inactive. ≥3:1 UI (not body). Light #777670 = 3.80:1 on
     cream — meets WCAG 2.2 SC 1.4.11 non-text contrast for state. */
  --text-disabled:#777670;

  /* §1 Multi-accent — sage (primary), honey, coral, periwinkle, sky.
     Each family has deep (text on cream / AAA), mid, and fill (soft chip). */
  --sage-deep:#2D4730; --sage:#4F7050; --sage-fill:#DDE8D9;
  --honey-deep:#6E4509; --honey:#C8861E; --honey-fill:#FBE8C8;
  --coral-deep:#8B3D34; --coral:#C8625A; --coral-fill:#F4D7D2;
  /* Vivid red — pushed-saturation coral used where the surface needs
     to grab attention (collapsed miss-tag pill). Stays warm so it
     doesn't clash with the rest of the warm-paper palette. */
  --coral-vivid:#D8463F;
  /* Lifted coral — used for icon + label fill on the open miss-tag
     tiles. In light mode the standard --coral reads fine on cream so
     they're equivalent; the dark-mode override pushes this toward a
     peachy tone so coral text/icons stay readable on the dark
     coral-tinted tile surface. */
  --coral-lift:#C8625A;
  --peri-deep:#382F86;  --peri:#786BC8;  --peri-fill:#E0DDF5;
  --sky-deep:#2D6B95;   --sky:#4D8CB0;   --sky-fill:#DCEAF3;
  /* patch-007 — violet ramp for Pharmacopia (drug cards). Uses the same
     stop pattern as the other accents: deep (text on light fill), mid, fill.
     A separate --violet-soft (dark-mode equivalent of -fill) is defined in
     the dark-mode block below so the fc-type-label pills match the rest. */
  /* WS10 2026-05-05: Pharma hue shift periwinkle H=244° → magenta H=286°, matches dark mode.
     Mid token improves from 2.9:1 FAIL → 4.9:1 AA ✓ as a side-effect of the hue shift. */
  --violet-deep:#6A1A80; --violet:#9A38BE; --violet-fill:#EFD8FA; --violet-soft:#EFD8FA;
  /* patch-007 — indigo ramp (Routine identity in practice; SAQ card uses --rose below). */
  --indigo-deep:#1E3266; --indigo:#3B5A9C; --indigo-fill:#DCE4F5; --indigo-soft:#DCE4F5;
  /* WS10 — SAQ rose ramp H=330°. Replaces --honey as SAQ card identity; fixes
     SAQ/Hazy collision (both amber H=38°). deep = 6.6:1 AAA on cream ✓. */
  --rose-deep:#9D1E5E; --rose:#C44484; --rose-fill:#F7DDEF; --rose-soft:#F7DDEF;
  /* v10 Saltbush core ramp (Axiom identity — DEC-024) */
  --saltbush-deep:#5E6670;  /* 6.6:1 on cream — body AA ✓ */
  --saltbush:     #808890;  /* mid identity */
  --saltbush-fill:#DDE0E4;  /* soft chip / tinted bg */
  --saltbush-soft:rgba(128,136,144,.14);
  /* v10 Phase 2c (2026-05-19) — lime ramp deletion. Was deprecated alias to saltbush
     during Phase 2a; Phase 2c swept 52 --lime-* consumers in CSS+JS → --saltbush-*.
     6 residual references remain in code comments (historical context, harmless).
     The --hero-axiom-accent var(--lime, fallback) at line ~113 still references --lime;
     that var() resolves to undefined-then-fallback, which we keep for back-compat. */

  /* v10 Dusk Terrain — 9-hue secondary palette (LOCKED 2026-05-19, body-system mapped).
     Curriculum sections A–Q map via SECTION_DUSK helper in pwa/app.js — see DESIGN-SYSTEM.md §1.
     Cross-cutting sections (Pharma B, Body Fluids F, MSK I, Nutrition K, Endocrine L,
     Thermoreg M, Obstetrics P, Antidotes Q) bucket into the closest family as inline
     oklch() tonal variants — no per-tonal tokens, computed at render time. */
  --dusk-mauve:      #8c6080;  /* O Microbiology — purple */
  --dusk-slate-rose: #A03540;  /* D Cardiovascular — red (v10-rev3 shifted from #996070 toward true red) */
  --dusk-ochre:      #8a5448;  /* N Haematology — maroon */
  --dusk-mulga:      #6a7858;  /* J GI — warm green */
  --dusk-heather:    #7a6878;  /* H Neurology — purple-grey */
  --dusk-wattle:     #8B7000;  /* E Renal — deep gold-yellow (v10-rev3 deepened for 3.99:1 UI contrast) */
  --dusk-eucalypt:   #4D8270;  /* A Cellular — silver blue-green */
  --dusk-coolibah:   #5E7A8E;  /* C Respiratory — dusty desert-sky blue */
  --dusk-pindan:     #B25028;  /* G Acid-base — burnt orange-red */
  /* Hero accent tokens — resolve to card-type identity per mode.
     Dark mode redefines these so --sage=sky-blue and --sky=lime-gold. */
  --hero-recall-accent:var(--sky,#4D8CB0);
  --hero-axiom-accent:var(--saltbush,#5E6670); /* v10: was var(--lime, #8A9E1A) — migrated DEC-024 */

  /* Role aliases — components reference these, not the palette by name */
  --accent:var(--sage); --accent-pressed:var(--sage-deep); --accent-soft:var(--sage-fill);
  --accent-text:var(--sage); /* text-safe alias; light mode: sage #4F7050 = 5.53:1 on bg ✓ (same as --accent) */
  /* `--accent-on` — text colour for content sitting on a `var(--accent)` fill.
     Light mode: `var(--bg)` (cream) reads at 4.59:1 on sage `#4F7050` — passes
     body AA. Dark mode (Phase 8c retune 2026-05-05) overrides to `white` so the
     teal `--mint #157570` (WS7) keeps body AA legibility (white on it is
     5.51:1; cream-on-it would be 4.12:1 — passes, but white kept for parity). All `background:var(--accent);
     color:var(--bg)` rules migrated to `color:var(--accent-on)` so the right
     value follows the theme automatically. */
  --accent-on: var(--bg);
  --success:var(--sage-deep); --warn:var(--honey-deep); --err:var(--coral-deep); --info:var(--sky-deep);

  /* Grade colour aliases — single source of truth for app-context grade colour
     references. Cinema scope continues to use `--fc-badge-*` directly (defined
     below in §4). The alias indirection lets the queued palette + light/dark
     audit sprint flip Mastered (or any grade) in one line, decoupling app-
     context use from the cinema-scope WCAG-tuned values when the two diverge.
     `--grade-mastered-glow` is computed from the colour so a recolour
     propagates without a second token edit. */
  --grade-mastered: var(--fc-badge-mastered);
  --grade-mastered-glow: color-mix(in srgb, var(--grade-mastered) 35%, transparent);
  --grade-missed:   var(--fc-badge-missed);
  --grade-missed-glow: color-mix(in srgb, var(--grade-missed) 35%, transparent);
  --grade-honed:    var(--fc-badge-honed);
  --grade-honed-glow:  color-mix(in srgb, var(--grade-honed) 35%, transparent);
  /* AUDIT-2026-05-06 #15 — hazy alias completes the grade-* set so app-context
     code never reaches into cinema-scope --fc-badge-* tokens. Identity is the
     same; the alias indirection lets a future audit retune one mode without
     touching the other. */
  --grade-hazy:      var(--fc-badge-hazy);
  --grade-hazy-text: var(--fc-badge-hazy-text);
  /* AUDIT-2026-05-06 #20 — Per-theme hover tokens. In LIGHT mode tap-feedback
     darkens the chip (mix toward black) — works against cream bg. In DARK
     mode (override below) the same darkening would push the chip toward
     `--bg #111118` and the button "disappears" on hover. The dark-mode block
     flips direction to mix toward white, keeping the chip visible against
     Slate Dusk. White text on either fill remains 5:1+ AA. */
  --grade-honed-hover:    color-mix(in srgb, var(--grade-honed)    85%, #000);
  --grade-missed-hover:   color-mix(in srgb, var(--coral-vivid)    85%, #000);
  --grade-mastered-hover: color-mix(in srgb, var(--grade-mastered) 85%, #000);

  /* AUDIT-2026-05-06 #21 — SAQ history pill palette. Previous code hardcoded
     #48c78e/#6bd6a8/#f14668 as var() fallbacks for tokens that were never
     defined, so the hex always rendered (no theme flip). Now: foreground
     defined here per theme; bg + border derived via color-mix at use sites.
     Light values keep current Bulma look; dark-mode block deepens to fit
     Slate Dusk's muted accent palette. */
  --saq-pass:       #48c78e;
  --saq-borderline: #6bd6a8;
  --saq-fail:       #f14668;

  /* AUDIT-2026-05-06 #23 — Axiom-formula honey label.
     WS11 v9.7-foundation re-audit (2026-05-19): previous comment claimed 7.4:1 AAA
     but actual contrast of #a07800 on cream #EFEBE0 = 3.59:1 (FAIL body 4.5).
     Darkened to #845F00 = 4.85:1 ✓ AA body. Dark mode override below lifts to
     soft gold #D4B250 = 8.45:1 ✓ AAA on Slate Dusk surface. */
  --axiom-honey: #845F00;

  /* AUDIT-2026-05-06 #22 — Pharma chip foreground. Light: pure white on the
     pharma violet brand (4.7:1 AA). Dark: softened to #f0e4ff so the chip
     foreground reads alongside the muted Slate Dusk text instead of
     glare-edge stark white. */
  --text-on-pharma: #fff;

  /* Legacy semantic aliases — kept until Phase 2 migrates renderer references.
     Drift report §3: "--gold → kept as alias to --honey". Same pattern for
     red/amber/green/orange/purple so existing component CSS still resolves. */
  --green:var(--sage); --green-bg:var(--sage-fill); --green-soft:var(--sage-fill);
  --orange:var(--coral); --orange-bg:var(--coral-fill);
  --purple:var(--peri);  --purple-bg:var(--peri-fill);
  --red:var(--coral-deep); --red-bg:var(--coral-fill);
  --amber:var(--honey);    --amber-bg:var(--honey-fill);
  --gold:var(--honey);
  --warn-bg:var(--honey-fill);

  /* Surface aliases — WS3 (v9.1, 2026-05-05): old consumer names cascade to
     the 4-tier canonical tokens. Resolution is semantically correct:
       --surface-alt  → FLOAT (surface-elevated) — used for hover backgrounds, chips, badges
       --surface-alt2 → CARD  (surface)          — used for card bodies, list rows, form skins
     New code should use canonical tokens directly; aliases are not deprecated,
     just not the preferred spelling for new components. */
  --surface-alt:var(--surface-elevated);
  --surface-alt2:var(--surface);

  /* §3 Layout */
  --page-max:1440px; --section-gap:12px;

  /* §2 Typography */
  --font-sans:"Albert Sans Variable",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;
  --font-display:"DM Serif Display",Georgia,"Times New Roman",serif;
  --font-mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;

  --radius:12px; --radius-sm:8px; --radius-md:10px; --radius-lg:16px;
  /* AUDIT-2026-05-06 #17 — Two new tokens name the legitimately-small
     decorative radii (identity bars at 2px, inline code/equation chips at
     4px) so audits stop re-flagging them. --radius-pill aliases the
     existing button-pill token so non-button pills (badges, chips) can
     reach for the same canonical 999px without minting a duplicate. */
  --radius-2xs:2px; --radius-tiny:4px; --radius-pill:var(--btn-radius-pill);
  --shadow-sm:0 1px 3px rgba(0,0,0,0.06);
  --shadow-md:0 4px 12px rgba(0,0,0,0.08);
  --shadow-lg:0 10px 30px rgba(0,0,0,0.12);
  --shadow-glow:0 4px 16px rgba(45,71,48,0.18);
  /* H-P2-01: pharma-specific shadow tokens — pill active + floating bulk-bar. */
  --shadow-pill:0 1px 3px rgba(0,0,0,.15);
  --shadow-floating-bar:0 -2px 16px rgba(0,0,0,.12);

  /* WS1 (Phase 9, 2026-05-05) — Motion + shadow token foundation.
     Codifies the canonical patterns that emerged organically across the
     codebase: `.12s` (389 uses) is the standard duration; cubic-bezier
     `(.4,.05,.2,1)` (10 uses) is the canonical curve; cubic-bezier
     `(.34,1.56,.64,1)` (9 uses) is the spring/overshoot reserved for
     cinema card entry and joyful events. Tokens land here; full literal
     sweep deferred to WS9 (motion polish). Shadow numeric scale aliases
     the existing semantic names so consumers can migrate gradually. */
  --ease-out:    cubic-bezier(.4,.05,.2,1);
  --ease-spring: cubic-bezier(.34,1.56,.64,1);
  --duration-xs: 80ms;
  --duration-sm: 120ms;     /* canonical hover / press / state-flip */
  --duration-md: 200ms;     /* sheets, sidebars, modal entries */
  --duration-lg: 280ms;     /* cinema card entry, joyful celebrations */
  --duration-xl: 380ms;                            /* full-screen overlay (cinema enter/exit) */
  --ease-enter:  cubic-bezier(.05,.7,.1,1);        /* M3 emphasized-decelerate — directional arrivals */
  --ease-exit:   cubic-bezier(.3,0,.8,.15);        /* M3 emphasized-accelerate — leaving */
  --ease-sheet-spring: cubic-bezier(.32,1,.48,1);  /* sheet snap-back (matches sheet.js) */
  /* WS6 (2026-05-05) — Typography scale: canonical 8-stop font-size ramp.
     All component font-size declarations reference these tokens; literal px forbidden in new code.
     Half-px values consolidated semantically: 10.5→xs · 11.5→sm · 12.5→md · 13.5→lg.
     Outliers left raw: 15px (inputs/axiom headers), 18px (emoji/icons), 20px (display numerics), 28px+(display). */
  --font-size-2xs: 10px;   /* micro uppercase labels, counts */
  --font-size-xs:  11px;   /* badges, meta text */
  --font-size-sm:  12px;   /* secondary text, tags */
  --font-size-md:  13px;   /* primary body text, rows */
  --font-size-lg:  14px;   /* h3, buttons, drug names */
  --font-size-xl:  16px;   /* body base, recall prompt */
  --font-size-2xl: 17px;   /* h2, list rows */
  --font-size-3xl: 22px;   /* h1, wordmark */
  /* Phase 1 card-system — intermediate half-step tokens.
     --font-size-2xs-plus replaces hardcoded 10.5px;
     --font-size-sm-plus  replaces hardcoded 12.5px;
     --font-size-lg-plus  replaces hardcoded 15px in axiom-header / axiom-formula. */
  --font-size-2xs-plus: 11px;
  --font-size-sm-plus:  13px;
  --font-size-lg-plus:  15px;
  /* WS5 (2026-05-05) — Sheet surface tokens */
  --backdrop-sheet: rgba(0,0,0,0.5);    /* all sheet backdrops */
  --backdrop-preview: rgba(8,8,16,0.82); /* preview overlay (heavy, intentionally distinct) */
  --z-sheet: 250;      /* all .sheet-backdrop instances (above tab bar 200) */
  --z-settings: 254;   /* settings sidebar (above sheets) */
  --z-palette: 260;    /* ⌘K search palette */
  --z-picker: 265;     /* curriculum picker — above palette so it works from search Explore */
  --z-preview: 270;    /* preview overlay (above palette) */
  --z-refs-sheet: 290; /* refs bottom sheet — stacks above preview overlay */
  --shadow-1: var(--shadow-sm);
  --shadow-2: var(--shadow-md);
  --shadow-3: var(--shadow-lg);

  /* WS2 (Phase 9, 2026-05-05) — Button taxonomy + token foundation.
     3 sizes (xs/sm/md) + lg for composite tiles. 4 variants
     (primary/ghost/destructive/pill). Per-accent ghost via [data-accent].
     Cinema scope override via .focus-overlay .btn--primary cascade. */
  --btn-radius:               6px;
  --btn-radius-pill:          999px;
  --btn-padding-block-xs:     3px;
  --btn-padding-block-sm:     6px;
  --btn-padding-block-md:     9px;
  --btn-padding-block-lg:     14px;
  --btn-padding-inline-xs:    8px;
  --btn-padding-inline-sm:    12px;
  --btn-padding-inline-md:    16px;
  --btn-padding-inline-lg:    24px;
  --btn-font-size-xs:         10px;
  --btn-font-size-sm:         12px;
  --btn-font-size-md:         13px;
  --btn-font-size-lg:         15px;
  --btn-font-weight:          500;     /* §2 cap; override per-button if evidence */
  --btn-shadow-press:         var(--shadow-1);   /* WS1 alias */
  --btn-min-tap:              44px;    /* iOS HIG mandate at pointer:coarse */

  /* Per-variant fills + text + border */
  --btn-bg-primary:           var(--accent);
  --btn-text-primary:         var(--accent-on);
  --btn-bg-ghost:             transparent;
  --btn-text-ghost:           var(--accent);
  --btn-border-ghost:         var(--accent);
  --btn-bg-destructive:       var(--coral-deep);
  --btn-text-destructive:     white;
  --btn-border-destructive:   transparent;
  --btn-bg-pill:              var(--surface);
  --btn-text-pill:            var(--text-muted);
  --btn-border-pill:          var(--border);

  /* §4 Focus-overlay fixed palette — the cinema overlay is a coloured-dark
     midnight regardless of app theme, so these tokens are NOT theme-split.
     Phase 7 (2026-05-02): cinema bg moved from near-black #0f0f10 → deep
     midnight #08083B. Two reasons: (a) impeccable "no pure black" anti-
     pattern — `#0f0f10` had ~0 chroma, lifeless beside the brand; midnight
     adds meaningful blue-purple chroma. (b) the violet swipe-up wash for
     Mastered retains hue separation from this bg (washed out on the
     aubergine alternative). Only use inside `.focus-overlay`. */
  /* Slate Ink (2026-05-26 cinema-mode pass): retuned from indigo #08083B to a
     calmer near-neutral slate per user review. Low chroma at low lightness
     (oklch ~0.18 0.016 248) so the cream card and the grade washes pop without
     the indigo glow. Only use inside `.focus-overlay`. */
  --focus-overlay-bg: #141A25;
  /* Grade badge colours — mapped to FSRS vocabulary (Missed/Hazy/Honed/Mastered).
     Phase 7: fills darkened so a white symbol meets WCAG 2.2 AA body 4.5:1
     AND each fill remains ≥3:1 against `#08083B` (UI dot threshold). Mastered
     migrated gold → violet (Stage 2 D3:a) so the badge echoes the compass
     swipe-up wash and the spectrum is monotonic (no warm→cool→warm loop).
     Hazy stays as amber/black — already passes both thresholds. */
  --fc-badge-missed:   #F05A50;   /* grade 1 Missed   — coral-deeper; white 4.16:1 on fill, on bg 3.34:1 (WS9 2026-05-05: red→coral to unify grade-btn + badge; hue H=5°) */
  --fc-badge-hazy:     #f59e0b;   /* grade 2 Hazy     — amber;      MUST use dark text (#111118 9.78:1); white FAILS (2.2:1) */
  --fc-badge-hazy-text:#111118;  /* WS9-fix: explicit dark-text companion — enforce on any solid Hazy fill */
  --fc-badge-honed:    #15803D;   /* grade 3 Honed    — green-700;  white ✓ 5.02:1, on bg 3.78:1 */
  --fc-badge-mastered: #9F72F8;   /* grade 4 Mastered — amethyst-lighter; white 4.7:1 AA body ✓ (WS9-fix: was #8B5CF6 white 4.23:1 FAIL; lifted ~12L. H=262°, Δhue from Honed=120°, Δhue from Recall=61°.) */
  /* F-P1-04 — Cinema-scoped counter tokens (mobile tap-target pill).
     Keeps all rgba literals out of component rules; defined here next to
     the badge palette where the cinema scope is established. */
  --fc-counter-bg:      rgba(124,106,175,.12);
  --fc-counter-border:  rgba(124,106,175,.3);
  --fc-counter-fg:      rgba(200,180,240,.85);
  --fc-counter-bg-open: rgba(124,106,175,.24);
  --fc-counter-fg-open: rgba(220,200,255,.95);
  /* F-P2-41/42 — Cinema chrome tokens: overlay header/button/text layer.
     --fc-chrome-border  : hairline dividers and icon-button borders
     --fc-chrome-bg      : icon-button and utility surfaces
     --fc-chrome-fg      : primary readable text on cinema
     --fc-chrome-fg-muted: secondary/dim text on cinema */
  --fc-chrome-border:   rgba(255,255,255,.08);
  --fc-chrome-bg:       rgba(255,255,255,.07);
  --fc-chrome-fg:       rgba(255,255,255,.75);
  --fc-chrome-fg-muted: rgba(255,255,255,.45);
  /* Phase 7 — fifth chrome token: progress-bar empty track. Promoted from a
     literal because the F-P2-45 fix from `.12 → .18` still missed the
     ≥3:1 UI threshold on the new cinema bg (was 1.62:1 at α 0.18). At α
     0.36 the track hits 3.19:1 on `#08083B`. */
  --fc-chrome-track:    rgba(255,255,255,.36);

  /* §1 Badge tier medals — Phase 7 (Stage 2 D4:a): light-mode lifts so all
     four tiers meet WCAG 2.2 UI ≥3:1 on `--bg #EFEBE0` warm paper. Previous
     light-mode values (`#CD7F32` / `#C0C0C0` / `#9BD5FF` / `--gold`) failed
     1.32–2.64:1 on cream paper. Platinum aliased to `--sky-deep` so it
     theme-resolves automatically. Gold aliased to `--honey-deep` for the
     same reason. */
  --tier-bronze:   #A65A1F;        /* light: 4.30:1 on #EFEBE0 (was #CD7F32 = 2.64) */
  --tier-silver:   #5A6470;        /* light: 5.05:1 (was #C0C0C0 = 1.53)  */
  --tier-gold:     var(--honey-deep); /* light: 7.00:1 via #6E4509 */
  --tier-platinum: var(--sky-deep);   /* light: 4.83:1 via #2D6B95 */

  /* WS4 (Phase 9, 2026-05-05) — Card primitive tokens. Single shape across
     recall/saq/pharma/axiom. Type identity carried by [data-card-type] +
     stripe colour. Padding aligns 14/14 standard. Tints proven 8% light /
     12% dark (WS3 audit). Stripe width unified at 4px (Q1). */
  --card-padding-block:    14px;
  --card-padding-inline:   14px;
  --card-radius:           var(--radius);    /* 12px */
  --card-stripe-width:     4px;
  --card-tint-light:       0%;  /* Card-redesign 2026-05-05: WS11 14%→0% restrained palette. Stripe carries identity; bg stays neutral so 4 stacked types don't read as a circus. Light-mode tint dropped entirely — paper surface speaks. */
  --card-tint-dark:        6%;  /* Card-redesign 2026-05-05: WS11 18%→6% restrained palette. DM keeps a faint lift so card reads against page-bg dusk; stripe still does most of the identity work. */
  --card-flag-top:         8px;
  --card-flag-right:       8px;
  --card-shadow:           var(--shadow-1);  /* WS1 alias */
  --card-shadow-hover:     var(--shadow-2);

  /* Card redesign 2026-05-05 — .study-card primitive (docs/CARD-REDESIGN-SPEC.md).
     Restrained palette: 0% light tint / 6% dark tint — stripe carries identity.
     Coexists with legacy .recall-card / .saq-card-face / .pharma-card / .axiom
     CSS until phase 2 migrates the JS render functions to .study-card. */
  --study-card-tint-light:    0%;
  --study-card-tint-dark:     6%;
  --study-card-padding-cmf:   14px;
  --study-card-padding-cmp-y: 10px;
  --study-card-padding-cmp-x: 12px;
  --study-card-min-h-cmp:     48px;
  --study-card-marked-tint:   5%;
  --study-card-flag-offset:   32px;
  /* Ribbon primitive — used in focus haul end, session-completion popup,
     Sessions undo tab, Lore daily roll-up. Spec §9. */
  --ribbon-h:                 36px;
  --ribbon-stripe-w:          3px;
  --ribbon-radius:            7px;
  /* Ph6 — card type text colors (readable on light cream surface ≥4.5:1) */
  /* WS11 v9.7-foundation audit (2026-05-19): --type-pharma #5E3E9E on cinema bg #08083B = 4.93:1 ✓ AA body;
     on --surface #F5F1E6 = 8.4:1 ✓ AAA. Dark-mode counterpart #B090F0 on #1A1A24 = 9.2:1 ✓ AAA. No change. */
  /* v10 (2026-05-19): Axiom identity migrated lime #546409 → saltbush #5E6670 per design-language-v10 review (DEC-024). 6.6:1 on cream ✓ AA body. */
  --type-saq:#A82840;--type-axiom:var(--saltbush-deep);--type-recall:#2D6B95;--type-pharma:#5E3E9E;
  /* Phase 1 card-system — nemesis identity palette (Nemesis card stripe + UI accents).
     Crimson → header/stripe, Ember → action/alert, Gold → reward/highlight. */
  --nemesis-crimson: #A02030;
  --nemesis-ember:   #E85D26;
  --nemesis-gold:    #F5C26B;
  /* Card v2 Phase 2 — deep -label tokens (AA-hardened, ≥4.5:1 on tinted surfaces).
     Grade labels: dark text on 12-14% grade-tinted light surface.
     Reveal labels: dark text on 12% type-tinted light surface. */
  --grade-mastered-label:#5B2A86;
  --grade-missed-label:#8B3D34;
  --grade-honed-label:#0f6032;
  --grade-hazy-label:#6E4509;
  --grade-blank-label:#8B3D34;
  --recall-reveal-label:#1E5070;
  --saq-reveal-label:#9D1E5E;
  --pharma-reveal-label:#6A1A80;
  --axiom-reveal-label:#454C54;
}
html.dark{
  color-scheme:dark;
  /* §1 Slate Dusk — surfaces (WS9 v9.6, 2026-05-05: Forest Floor warm-green → cool blue-purple neutral)
     WS11 v9.7-foundation (2026-05-19): widened to 5-rung Material 3-style tint-on-base ladder
     so nested cards perceive elevation. Cool Slate Dusk hue family (~245°, mauve-leaning) preserved;
     each rung baked with subtle primary-hue tint (not pure luminance step). See DESIGN-SYSTEM.md §1.
     PAGE → --bg, CARD → --surface, FLOAT → --surface-elevated, TOP-FLOAT → --surface-floating, INPUT → --surface-bright.
     Shadows alone don't carry elevation in dark mode — pair with `border-top:1px solid
     color-mix(in srgb,white 8%,transparent)` hairline highlight on raised surfaces. */
  --bg-sunken:#0B0B12;             /* SUNKEN — below page (wells/trays). WS11 v9.7-foundation. */
  --bg:#111118;                    /* PAGE  — Slate Dusk deep (unchanged) */
  --surface:#1A1A24;               /* CARD  — Slate Dusk card. WS11: was #18181F (+2L, +3% tint). */
  --surface-elevated:#262632;      /* FLOAT — Slate Dusk elevated. WS11: was #222229 (+3L, +6% tint). */
  --surface-floating:#34344A;      /* TOP-FLOAT — modal/sheet ceiling. WS11: NEW rung above FLOAT (+10% tint), gives sheets clear elevation. */
  --surface-bright:#2C2C38;        /* INPUT — equivalent of pure-white role (UNCHANGED — INPUT role kept; was previously also doing duty as top elevation). */
  --border:#2D2D3A; --border-strong:#3E3E52;
  --text:#EEF0F8; --text-muted:#B8B9C8; --text-faint:#8080A5; /* WS9-fix: was #78789A (4.43:1 FAIL) → #8080A5 (4.6:1 AA ✓) */
  /* WS11 v9.7-foundation — Dark-mode parity for new text tokens.
     --text-muted-strong: #D0D2E0 on bg #111118 = 11.8 AAA; on surface #1A1A24 = 10.4 AAA.
     --text-disabled:     #686878 on bg #111118 = 3.33 — meets WCAG 2.2 SC 1.4.11 UI. */
  --text-muted-strong:#D0D2E0;
  --text-disabled:#686878;

  /* Mid tones — multi-accent. Periwinkle pushed violet (#A89AE8) so SAQ
     pills stay distinct from sky / Key Fact for users with mild blue-yellow
     colour vision variation. AAA preserved on every surface.
     Phase 8b → 8c retune (2026-05-05): `--mint` migrated `#7FE0AD → #1D9E75
     → #157C5C` (deep emerald). Path: original bright mint `#7FE0AD` read as
     neon glare (10.95:1 vs bg). 8b shipped `#1D9E75` (c-teal-400) but the
     full Stripe/Linear-style depth wanted `#157C5C` — currently 3.65:1 vs
     bg, white-on-accent 4.71:1 body AA. Crossing this threshold required
     migrating all `background:var(--accent); color:var(--bg)` rules to
     `color:var(--accent-on)` (token defined at :root + html.dark for
     theme-correct text). Cascade touched 20 sites + the existing dead
     `var(--accent-on)` reference at line 5943 now resolves correctly.
     WS7 (2026-05-05): `--mint` shifted #157C5C → #157570 (teal, H=177°).
     Hue separation from Honed `#15803D` (H=143°): 13° → 34.5°, now ≥30° target.
     white-on-mint: 5.51:1 body AA ✓. `--mint-soft` hue-shifted #1A3F30→#193E3C.
     `--accent-pressed` hue-shifted #2A8B6A→#298985. */
  --mint:#157570;       --mint-soft:#193E3C;
  --honey:#F5C26B;      --honey-soft:#3D2E15;
  --coral:#F09687;      --coral-soft:#3D241F;
  --coral-vivid:#F05A50;   /* WS9: unified with --fc-badge-missed; was #FF7B6F (grade btn now matches badge) */
  --coral-lift:#FFB8AE;
  --peri:#A89AE8;       --peri-soft:#2A234A;
  --sky:#8EA020;        --sky-soft:rgba(142,160,32,.14); /* WS9: repurposed for Axiom card identity (lime-gold H=68°); --info + --tier-platinum now carry explicit #79B9DD */
  /* patch-007 — Pharmacopia violet (dark-mode pair).
     --violet-deep is intentionally a *lift* in dark mode (one ramp stop
     brighter than --violet) so it can serve as a high-contrast meta header
     on the violet-tinted card surface. Light mode keeps --violet-deep dark.
     --violet-fill aliases to --violet-soft so type-label pills behave like
     the other dark-mode accent pills (e.g. .peri-fill resolves to the same
     deep-tone fill in dark mode). */
  --violet-deep:#E898F4; --violet:#B058CC; --violet-soft:#380A42; --violet-fill:#380A42; /* WS9: Pharma identity → magenta-purple H=288°, Δhue from Mastered=26°, Δhue from Recall=87° */
  /* patch-007 — Indigo (SAQ) dark-mode pair. Same lift convention as violet:
     -deep is bright (text on dark fill), -fill aliases to a deep tone so
     type-label pills sit on a saturated surface like the other accents. */
  --indigo-deep:#F5A0CC; --indigo:#DD4490; --indigo-soft:#380A20; --indigo-fill:#380A20; /* WS9b: SAQ → rose H=332°, identity #C02870 (Δhue from Missed H=5° = 37° ✓, was crimson H=345° Δ=20° ✗). --indigo #DD4490 = 4.67:1 AA body ✓; was #E84870 4.73:1 same tier. */
  /* WS10 dark-mode aliases — global card rules use --rose for SAQ identity */
  --rose-deep:#F5A0CC; --rose:#DD4490; --rose-fill:#380A20; --rose-soft:#380A20;

  /* v10 Saltbush core ramp dark pair (Axiom identity — DEC-024) */
  --saltbush-deep:#C4CAD0;  /* 10.8:1 on Slate Dusk #1A1A24 — AAA ✓ */
  --saltbush:     #A0AAAA;
  --saltbush-soft:rgba(160,170,170,.14);
  /* v10 Phase 2c (2026-05-19): --lime-* ramp aliases retired post-sweep — all
     consumers migrated to --saltbush-*. See feat(design) Phase 2c commit. */

  /* v10 Dusk Terrain dark pair (9 hues — locked v10-rev3 values, body-system mapped) */
  --dusk-mauve:      #b08aaa;
  --dusk-slate-rose: #C46068;  /* v10-rev3: was #c08898, brick-red for Cardio */
  --dusk-ochre:      #b07868;
  --dusk-mulga:      #8c9870;
  --dusk-heather:    #a08fa0;
  --dusk-wattle:     #D4BC58;  /* v10-rev3: was #BFC468, golden-yellow for Renal */
  --dusk-eucalypt:   #7DAE96;
  --dusk-coolibah:   #8AA4B8;
  --dusk-pindan:     #D8694A;

  /* v10 Nemesis dark override — crimson lifted #A02030 → #C84050 for AA body on Slate Dusk
     (--nemesis-ember + --nemesis-gold pass dark without override) */
  --nemesis-crimson: #C84050;

  /* Cross-palette aliasing — "deep" tokens resolve to bright equivalents in
     dark, "fill" tokens resolve to *-soft. Components reference --sage-deep
     etc. and get the right value per mode without switching token names. */
  --sage-deep:#79B9DD; --sage:#79B9DD; --sage-fill:rgba(121,185,221,.15); /* WS9: Recall identity = sky #79B9DD; decoupled from accent --mint (#157570) */
  --honey-deep:var(--honey); --honey-fill:var(--honey-soft);
  --coral-deep:var(--coral); --coral-fill:var(--coral-soft);
  --peri-deep:var(--peri);   --peri-fill:var(--peri-soft);
  --sky-deep:var(--sky);     --sky-fill:var(--sky-soft);

  /* AUDIT-2026-05-06 #20 — Dark-mode hover override. Recall grade buttons
     in dark mode must LIGHTEN on hover (mix toward white), not darken
     (mix toward #000) which would push the chip toward --bg #111118 and
     visually disappear. White text on lightened fills:
       --grade-honed   #15803D + 15% white  ≈ #2F9355 — white on it ≥4.5:1 AA ✓
       --grade-missed  #F05A50 + 15% white  ≈ #F37368 — white ≥3:1 large/icon OK
       --grade-mastered #9F72F8 + 15% white ≈ #AC85F9 — white ≥3:1 OK
     Each fill is also visibly distinct from --bg #111118 (was the bug). */
  --grade-honed-hover:    color-mix(in srgb, var(--grade-honed)    85%, #fff);
  --grade-missed-hover:   color-mix(in srgb, var(--coral-vivid)    85%, #fff);
  --grade-mastered-hover: color-mix(in srgb, var(--grade-mastered) 85%, #fff);

  /* AUDIT-2026-05-06 #21 — SAQ history pill dark-mode palette. Bulma-default
     greens/red looked neon against Slate Dusk; deepening to muted variants:
       --saq-pass       #2A9D6D — 5.4:1 on --bg #111118 (was 9.0:1 #48c78e — too bright)
       --saq-borderline #3FA57D — sits between pass and bg
       --saq-fail       #C03450 — 4.9:1 on --bg (was 6.7:1 #f14668 — neon)
     Pill bg + border still derived via color-mix at use sites. */
  --saq-pass:       #2A9D6D;
  --saq-borderline: #3FA57D;
  --saq-fail:       #C03450;

  /* AUDIT-2026-05-06 #23 — Axiom-formula honey on dark. Light #a07800 on
     Slate Dusk reads ~3.05:1 (FAIL body AA). Lift to soft gold #D4B250:
       D4B250 on #111118 = 7.6:1 ✓ AA body, AAA large.
     Hue preserved (~46° honey-gold) to maintain identity. */
  --axiom-honey: #D4B250;

  /* AUDIT-2026-05-06 #22 — Pharma chip foreground on dark. Pure white on
     dark-mode violet `var(--violet) #B058CC` reads ~3.65:1 — passes large
     but feels glare-edge. Soften to #F0E4FF:
       F0E4FF on #B058CC = 3.55:1 (large/UI ≥3:1 ✓)
       Visually muted to fit dark-mode ambient palette. */
  --text-on-pharma: #F0E4FF;

  /* Role aliases */
  --accent:var(--mint); --accent-pressed:#298985; --accent-soft:var(--mint-soft);
  /* Phase 8c: text on `--accent` flips to white in dark mode. White on
     `#157570` is 5.51:1 — passes body AA ✓. `--accent-pressed` #298985
     (H=177°, hue-matched to new mint) — used mainly as box-shadow accent
     edge on buttons; 4.26:1 on dark bg passes large-text AA. */
  --accent-on: white;
  --accent-text: #1E9E98; /* WS9-fix: text-safe accent — 5.3:1 AA body ✓ on --surface. --accent #157570 = 3.1:1 (icon/fill OK, body text FAIL). Use --accent-text for body-size text labels. */
  --success:var(--mint); --warn:#FFB347; --err:#E07A70; --info:#79B9DD; /* WS9: explicit — sky repurposed for Axiom identity */
  --hero-recall-accent:var(--sage,#79B9DD);
  --hero-axiom-accent:var(--saltbush,#C4CAD0); /* v10: was var(--lime, #8EA020) — migrated DEC-024 */
  /* Dark-mode button overrides: destructive bg must stay dark enough for white text.
     In dark mode --coral-deep→var(--coral)=#F09687 (salmon) = 2.2:1 FAIL.
     Use light-mode coral-deep value (#8B3D34) which gives white 7.7:1 AAA. */
  --btn-bg-destructive: #8B3D34;

  /* Legacy semantic aliases */
  --green:var(--mint); --green-bg:var(--mint-soft); --green-soft:var(--mint-soft);
  --orange:var(--coral); --orange-bg:var(--coral-soft);
  --purple:var(--peri);  --purple-bg:var(--peri-soft);
  --red:var(--coral);    --red-bg:var(--coral-soft);
  --amber:var(--honey);  --amber-bg:var(--honey-soft);
  --gold:var(--honey);
  --warn-bg:var(--honey-soft);

  /* Surface aliases — dark-mode parity with :root (WS3 v9.1). Same canonical resolution.
     --surface-alt  → FLOAT (surface-elevated #222229)
     --surface-alt2 → CARD  (surface          #18181F) */
  --surface-alt:var(--surface-elevated);
  --surface-alt2:var(--surface);

  --shadow-sm:0 1px 3px rgba(0,0,0,0.4);
  --shadow-md:0 4px 12px rgba(0,0,0,0.4);
  --shadow-lg:0 10px 30px rgba(0,0,0,0.6);
  --shadow-glow:0 4px 16px rgba(21,117,112,0.22);

  /* §1 Badge tier medals — dark-mode values for Slate Dusk bg (#111118).
     Phase 7 (Stage 2 D4:a): platinum + gold now alias to theme-split tokens
     so they auto-resolve correctly. Bronze + silver keep their explicit
     dark lifts (different design intent than light-mode lifts). */
  --tier-bronze:   #E09040;        /* dark: 7.37:1 on #111118 */
  --tier-silver:   #D4D4D4;        /* dark: 12.67:1 */
  --tier-gold:     var(--honey-deep); /* dark resolves to #F5C26B */
  --tier-platinum: #79B9DD;           /* dark: explicit — was var(--sky-deep) but sky repurposed for Axiom */
  /* Ph6 — card type text colors dark-mode overrides (≥4.5:1 on dark surface) */
  /* v10 (2026-05-19): Axiom dark migrated lime #A8C020 → saltbush #C4CAD0 (10.8:1 AAA on Slate Dusk ✓) */
  --type-saq:#F08098;--type-axiom:var(--saltbush-deep);--type-recall:#79B9DD;--type-pharma:#B090F0;
  /* Card v2 Phase 2 — deep -label tokens dark-mode overrides (light text on dark tinted surfaces ≥4.5:1). */
  --grade-mastered-label:#C4A8FF;
  --grade-missed-label:#FF8F85;
  --grade-honed-label:#22c55e;
  --grade-hazy-label:#F59E0B;
  --grade-blank-label:#FF8F85;
  --recall-reveal-label:#79B9DD;
  --saq-reveal-label:#F070BA;
  --pharma-reveal-label:#CC82E8;
  --axiom-reveal-label:#A0AAAA;
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}

/* Native-feel audit: single nuclear reduced-motion override. Zeroes the
   duration tokens so every token-driven transition/animation collapses.
   0.01ms (not 0) keeps transitionend/animationend firing for JS state. */
@media (prefers-reduced-motion: reduce){
  :root{
    --duration-xs:0.01ms; --duration-sm:0.01ms; --duration-md:0.01ms;
    --duration-lg:0.01ms; --duration-xl:0.01ms;
  }
}

/* ═══════════════════════════════════════════════
   KNOWLEDGE-MAP DESIGN TOKENS  (WS11: moved verbatim from knowledge-map.css)
   The map is an always-dark canvas; these #mapRoot-scoped vars override the
   :root/html.dark palette for elements inside #mapRoot (id specificity wins
   regardless of source order). Hex is permitted here (tokens.css is exempt).
═══════════════════════════════════════════════ */
#mapRoot {
  --bg:            #0E1117;
  --surface:       #161B25;
  --surface2:      #1E2535;
  --surface3:      #252D3F;
  --border:        #2A3347;
  --border2:       #3A4560;
  --text:          #E7ECF3;
  --text-muted:    #8A93A5;
  --text-dim:      #5A6473;

  /* ── MASTERY palette ────────────────────────────────────────────────
     Amethyst / Honey / Coral per spec. Distinct from high-yield overlay.
  ────────────────────────────────────────────────────────────────────── */
  --mastery-strong:       #9F72F8;   /* amethyst — Mastered */
  --mastery-developing:   #E0A23A;   /* honey — Developing */
  --mastery-needs-work:   #F05A50;   /* coral — Needs work */
  --mastery-not-started:  #38BDF8;   /* sky — Not started (has cards, no reviews yet) */
  --mastery-no-cards:     #3A4250;   /* hollow — no cards (corpus gap) */

  /* ── grade distribution bar (detail panel only) ────────────────────
     Same CVD-safe ramp: warm rose → amber → teal → blue-violet → grey
  ────────────────────────────────────────────────────────────────────── */
  --grade-1: #F87171;   /* rose-400 — Blank (missed) */
  --grade-2: #FBBF24;   /* amber-400 — Hazy & Mixed */
  --grade-3: #34D399;   /* emerald-400 — Honed */
  --grade-4: #818CF8;   /* indigo-400 — Mastered */
  --grade-u: #3A4250;   /* slate — Ungraded */

  /* ── COOL hue reserved for structural / cross relationships ─────────
     Distinct from grade-2 amber. Blue used ONLY for cross edges / integration.
  ────────────────────────────────────────────────────────────────────── */
  --cool-cross:    #38BDF8;   /* sky-400 — cross-chapter structural */
  --cool-cross-bg: rgba(56,189,248,0.10);
  --cool-cross-border: rgba(56,189,248,0.35);

  /* ── frontier / ready-to-introduce ─────────────────────────────────── */
  --frontier-ring: #38BDF8;   /* sky-400 — Ready to introduce (per spec) */

  /* co-requisite edge (dashed, neutral) */
  --edge-coreq:    #4A5568;
  /* prerequisite edge (warm grey) */
  --edge-prereq:   #8A93A5;

  /* ── HIGH-YIELD fill-heatmap tints ──────────────────────────────────
     FILL tints applied to node background. Distinct from mastery border ring.
     Strengthened for dark-mode legibility: high/med/low clearly distinct.
     high = rose-red (warm, high luminance+saturation)
     med  = vivid amber-gold (mid luminance, high saturation — NOT muddy brown)
     low  = teal (cool, lower luminance — clearly different axis from med)
     CVD-safe: luminance AND hue differ across all three levels.
  ────────────────────────────────────────────────────────────────────── */
  --hy-high-fill:  rgba(239,68,68,0.38);   /* rose-500 fill tint — vivid red */
  --hy-high-bg:    rgba(239,68,68,0.28);
  --hy-high-border:rgba(239,68,68,0.75);
  --hy-high-color: #FC8585;               /* brighter rose for text on dark */
  --hy-med-fill:   rgba(251,191,36,0.32);  /* amber-400 fill tint — vivid gold */
  --hy-med-bg:     rgba(251,191,36,0.22);
  --hy-med-border: rgba(251,191,36,0.65);
  --hy-med-color:  #FCD34D;               /* amber-300 — bright on dark bg */
  --hy-low-fill:   rgba(20,184,166,0.22);  /* teal-500 fill tint — distinct from amber */
  --hy-low-bg:     rgba(20,184,166,0.15);
  --hy-low-border: rgba(20,184,166,0.45);
  --hy-low-color:  #2DD4BF;               /* teal-400 — clearly distinct from red+amber */

  /* section accents */
  --accent-c:      #38BDF8;
  --accent-d:      #818CF8;

  /* WS11: tokens for the two out-of-block hex refs relocated from knowledge-map.css */
  --scope-toggle-active-text: #bfe7fb;  /* active state on rgba(sky,0.14) bg */
  --km-hy-active:             #F87171;  /* = --grade-1; hy-toggle chip active */

  --radius-sm:     6px;
  --radius-md:     10px;
  --radius-lg:     16px;
  --radius-full:   9999px;

  --detail-w:      490px;
  --spine-max:     680px;
}

/* ====================================================================
   toast.css — styling for the unified toast singleton (pwa/toast.js).
   Sprint E2 / Track A. Consolidates the inline styles previously scattered
   across app.js (.cicm-toast), planner-overview.js (#po-toast),
   coverage-spine-badges.js (.cov-toast) and focus-mode.css (nemesis-tamed).
   Register after tokens.css in pwa/css/_manifest.js.
   ==================================================================== */

/* Host is a logical wrapper only — the positioned stacks do the layout. */
.cicm-toast-host { display: contents; }

/* Two ARIA live regions per stack collapse into one visual column. */
.cicm-toast-region { display: contents; }

/* One fixed visual stack per position. */
.cicm-toast-stack {
  position: fixed;
  z-index: 9999;                 /* above tab bar (200) + sheets/modals (≤999) */
  display: flex;
  flex-direction: column;
  gap: 6px;
  pointer-events: none;          /* toasts re-enable pointer-events themselves */
}
.cicm-toast-stack--bottom-center {
  left: 0; right: 0;
  bottom: calc(80px + env(safe-area-inset-bottom, 0px));
  align-items: center;
}
.cicm-toast-stack--top-right {
  top: calc(16px + env(safe-area-inset-top, 0px));
  right: 14px;
  align-items: flex-end;
}

/* --- The toast itself ------------------------------------------------ */
.cicm-toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: min(86vw, 440px);
  padding: 10px 16px;
  border: 1px solid var(--border, rgba(255, 255, 255, .12));
  border-radius: var(--radius-md, 10px);
  background: var(--surface, #222);
  color: var(--text, #fff);
  font-family: var(--font-sans, 'Albert Sans', system-ui, sans-serif);
  font-size: 13px;
  line-height: 1.4;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .18);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .14s ease, transform .14s ease;
}
.cicm-toast--in  { opacity: 1; transform: translateY(0); }
.cicm-toast--out { opacity: 0; transform: translateY(8px); }
.cicm-toast--clickable { cursor: pointer; }

.cicm-toast__body { flex: 1 1 auto; min-width: 0; }

/* --- Tone variants (token-driven) ----------------------------------- */
.cicm-toast--error {
  font-weight: 500;
  border-color: var(--coral-deep, #8B3D34);
  background: var(--coral-fill, #F4D7D2);
  color: var(--coral-deep, #8B3D34);
}
.cicm-toast--success {
  border-color: var(--grade-honed);
}
.cicm-toast--warn {
  border-color: var(--honey, #E0A33A);
}
.cicm-toast--info {
  border-color: var(--border, rgba(255, 255, 255, .12));
}
.cicm-toast--loading {
  border-color: var(--border, rgba(255, 255, 255, .12));
  opacity: .96;
}

/* --- Action + dismiss controls -------------------------------------- */
.cicm-toast__action {
  flex: 0 0 auto;
  background: transparent;
  border: 0;
  padding: 4px 6px;
  font: inherit;
  font-weight: 600;
  color: inherit;
  text-decoration: underline;
  cursor: pointer;
  border-radius: var(--btn-radius);
}
.cicm-toast__close {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44px hit target while staying visually compact via negative margin. */
  width: 44px; height: 44px;
  margin: -12px -10px -12px 0;
  background: transparent;
  border: 0;
  color: inherit;
  font-size: 18px;
  line-height: 1;
  opacity: .6;
  cursor: pointer;
}
.cicm-toast__close:hover,
.cicm-toast__close:focus-visible { opacity: 1; }

.cicm-toast__action:focus-visible,
.cicm-toast__close:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 1px;
}

/* --- Reduced motion: fade only, no slide --------------------------- */
@media (prefers-reduced-motion: reduce) {
  .cicm-toast {
    transition: opacity var(--duration-sm) linear;
    transform: none;
  }
  .cicm-toast--in,
  .cicm-toast--out { transform: none; }
}

/* §3 Page container — body IS the centred container in this codebase. The
   v9.1 spec lists both <body> direct and a dedicated .app-root wrapper as
   canonical; this PWA uses body. Drift report §6 makes this explicit so
   nobody adds an .app-root nest later. */
/* v172 — Status-zone backdrop. iOS Safari + standalone PWA both render the
   status bar text over page content when scrolled; the body's padding-top
   only protects the FIRST element, not subsequent headings (e.g. SAQ Block,
   block subheadings). A fixed-position backdrop covering the safe-area-top
   zone hides scrolled content behind it without changing layout. */
@media(max-width:600px){
  body::before{
    content:'';
    position:fixed;top:0;left:0;right:0;
    height:env(safe-area-inset-top,0);
    background:var(--bg);
    z-index:100;pointer-events:none;
  }
  /* Bottom safe-area filler — prevents dark strip below tab bar */
  body::after{
    content:'';
    position:fixed;bottom:0;left:0;right:0;
    height:env(safe-area-inset-bottom,0);
    background:color-mix(in srgb,var(--bg) 90%,transparent);
    z-index:199;pointer-events:none;
  }
}
body{
  margin:0 auto;max-width:var(--page-max);
  padding:env(safe-area-inset-top,12px) 24px calc(72px + env(safe-area-inset-bottom,0px));
  font-family:var(--font-sans);
  /* v9.1 §2 spec is 15px base; this codebase ships at 16px from earlier
     UX feedback re. small text on large displays. Leaving at 16px in P1
     and flagging the divergence as a follow-up note for v9.2 review. */
  font-size:16px;line-height:1.55;color:var(--text);background:var(--bg);
  -webkit-font-smoothing:antialiased;
}
/* R-015: dark-mode body transition guarded by reduced-motion preference */
@media(prefers-reduced-motion:no-preference){
  body{transition:background var(--duration-md),color .2s}
}
/* On wide screens the page bg shows behind the centred body — keep the
   surround flush with --bg so the four-tier surface hierarchy stays clean
   (warm paper page → warm cream cards). */
html{background:var(--bg)}
html.dark{background:var(--bg)}
@supports(padding:max(0px)){body{padding-left:max(24px,env(safe-area-inset-left));padding-right:max(24px,env(safe-area-inset-right))}}

h1{font-size:var(--font-size-3xl);font-weight:500;margin:0;letter-spacing:-0.01em}
/* §13 Wordmark — DM Serif Display 400, the only display-font usage outside
   §4G streak number / §5 done screen. Letter-spacing -0.005em per spec. */
.wordmark{font-family:var(--font-display);font-weight:400;font-size:var(--font-size-3xl);letter-spacing:-0.005em;line-height:1}
@media(max-width:600px){.wordmark{font-size:20px}}
/* P1·2 + Today-fix #6 — h2 sections feel quiet at §2-spec weight 500.
   Bump to 600 + breathing room. Numbered prefixes ('1 · ', '2 · ',
   etc.) replaced by a small coloured identity bar via ::before, scoped
   per card-type class. Authors drift from §2 ('h2 — 17px / 500');
   flag for v9.2 §2 review. */
h2{font-size:var(--font-size-2xl);font-weight:500;margin:28px 0 12px;padding-top:20px;border-top:1px solid var(--border);display:flex;align-items:center;gap:9px}
/* The author `h2{display:flex}` above overrides the UA `[hidden]{display:none}`
   rule, so the `hidden` attribute alone won't collapse a section header. This
   restores it (used to collapse empty Today sections — recall/SAQ/pharma/
   axiom/more-cards). */
h2[hidden]{display:none!important}
/* Coloured identity bar — small 4×18 rounded rectangle before the
   heading text, color-mapped to the card type:
     section-recall  → sky    (WS10: sky-blue, matches card identity)
     section-saq     → rose   (WS10: rose H=330°, matches card identity · was honey)
     section-axiom   → lime   (WS10: lime-gold H=68°, matches card identity · was sky)
     section-routine → indigo (calm scheduling · was honey, swapped with SAQ for H1) */
h2.section-recall::before,
h2.section-saq::before,
h2.section-axiom::before,
h2.section-routine::before,
h2.section-pharma::before,
h2.section-more-cards::before{
  content:"";display:inline-block;width:4px;height:18px;
  border-radius:var(--radius-2xs);flex-shrink:0;
  /* Lift the bar onto the text baseline so it reads as a leading mark. */
  align-self:center;
}
/* Center the Today-tab section headings so they line up over their centered
   cards (product request). The colored identity bar + title + sub all center
   as a row. */
h2.section-recall,
h2.section-saq,
h2.section-axiom,
h2.section-pharma,
h2.section-more-cards,
h2.section-routine{justify-content:center}
/* WS10 — section heading identity bars aligned with card hue families */
h2.section-recall::before  {background:var(--sky)}
h2.section-saq::before     {background:var(--rose)}
h2.section-axiom::before   {background:var(--saltbush)}
h2.section-routine::before {background:var(--indigo)}
/* patch-007 — Pharmacopia identity bar in violet (Iatrogenic drug accent). */
h2.section-pharma::before  {background:var(--violet, #7F77DD)}
h2.section-more-cards::before{background:color-mix(in srgb,var(--text-muted, #888) 50%,transparent)}
/* Wave 6c-4 — More Cards ribbon section. Rows render at reduced opacity
   so they read as a "preview" of cards the user is filtering out via
   intensity; clicking promotes them into the live session. */
.more-cards-grid{display:flex;flex-direction:column;gap:4px;margin-bottom:14px;}
.more-cards-row{
  opacity:0.62;
  filter:saturate(0.7);
  cursor:pointer;
  transition:opacity var(--duration-sm),filter var(--duration-sm),transform var(--duration-sm);
}
.more-cards-row:hover{opacity:1;filter:saturate(1);transform:translateX(2px);}
.more-cards-row:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
.more-cards-row::before{
  content:"+ add to session";
  position:absolute;right:8px;top:50%;transform:translateY(-50%);
  font:600 9px/1 'Albert Sans',system-ui,sans-serif;
  color:var(--accent);text-transform:uppercase;letter-spacing:0.6px;
  padding:3px 6px;border-radius:var(--radius-tiny);
  background:color-mix(in srgb,var(--accent) 12%,transparent);
  opacity:0;transition:opacity var(--duration-sm);pointer-events:none;
}
.more-cards-row:hover::before{opacity:1;}
h2:first-of-type{border-top:none;padding-top:0;margin-top:14px}
h2 .sub{font-weight:400;font-size:var(--font-size-md);color:var(--text-muted)}
h3{font-size:var(--font-size-lg);font-weight:500;margin:12px 0 5px}

/* --- Lucide-style inline SVG icon support --- */
.icn{width:1em;height:1em;display:inline-block;vertical-align:-0.15em;stroke:currentColor;fill:none;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}

/* --- Header ---
   Post-audit: 3-column grid so the wordmark + meta line sits centred
   horizontally, the avatar + XP rank dot anchor left, and the search /
   settings buttons anchor right. Equal 1fr columns for the side slots
   keep the centre column geometrically centred regardless of how wide
   the side groups grow. */
.app-header{
  display:grid;
  grid-template-columns:auto 1fr auto;
  align-items:center;
  gap:10px;
  padding:18px 0 20px;
}
@media(max-width:600px){.wordmark{display:none}}
.app-header-left{display:flex;align-items:center;gap:8px;justify-self:start;min-width:0}
.app-title{display:flex;flex-direction:column;gap:2px;min-width:0;justify-self:center;text-align:center;align-items:center;overflow:hidden}
.app-title h1{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.app-actions{display:flex;gap:6px;align-items:center;justify-self:end}
@media(max-width:600px){.app-actions{gap:8px}}/* iOS-005 — raises center-to-center to 44px */
.account-btn{
  width:38px;height:38px;border-radius:50%;
  border:1px solid var(--border);background:var(--accent-soft);color:var(--accent-pressed);
  cursor:pointer;display:inline-flex;align-items:center;justify-content:center;
  font-size:var(--font-size-lg);font-weight:700;flex-shrink:0;transition:background .15s,color .15s,border-color .15s,box-shadow .15s,transform .15s,opacity .15s;
  font-family:inherit;
}
.account-btn:hover{background:var(--accent);color:white;transform:scale(1.04)}
.account-btn:active{transform:scale(0.96)}
html.dark .account-btn{background:var(--accent-soft);color:var(--accent)}
html.dark .account-btn:hover{background:var(--accent);color:var(--accent-on)}
/* XP rank dot — small coloured indicator in the header. Colour encodes the
   user's current rank (Intern → Director). Tooltip on hover shows the rank
   name + XP. Clicking jumps to the History tab. */
.xp-rank-dot{
  display:inline-flex;align-items:center;flex-shrink:0;cursor:pointer;
  padding:4px;border-radius:50%;background:transparent;border:none;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);font-family:inherit;line-height:1;
  margin-left:4px;
}
.xp-rank-dot:hover{background:var(--surface-alt);transform:scale(1.15)}
.xp-rank-dot:active{transform:scale(0.96)}
.xp-rank-dot .dot{
  width:10px;height:10px;border-radius:50%;display:block;
  background:currentColor;
  box-shadow:0 0 0 2px var(--bg),0 0 0 3px currentColor;
}
/* Daily XP goal bar — sits directly under the streak bar.
   Pulls today's XP from localStorage 'cicm-focus-day' (set by Focus Mode
   on session end) and the goal from state.settings.dailyXpGoal. */
/* T-P1-01 — XP goal merged into streak-bar bottom edge.
   .streak-xp-bar is a 3px absolute indicator at bottom of the streak card;
   .streak-xp is an inline counter that appears inside the flex row.
   Both are hidden until the user earns today's first XP (updateXpGoalBar). */
.streak-xp-bar{position:absolute;bottom:0;left:0;height:3px;background:var(--accent);border-radius:0 0 var(--radius) var(--radius);width:0%;transition:width .4s ease,background .25s ease,box-shadow .25s ease;pointer-events:none}
.streak-bar.hit .streak-xp-bar{background:var(--gold);box-shadow:0 0 8px rgba(255,217,61,0.6)}
.streak-xp{display:none;align-items:center;gap:3px;font-size:var(--font-size-xs);color:var(--text-muted);font-variant-numeric:tabular-nums;font-weight:500;white-space:nowrap;margin-left:auto}
.streak-xp.shown{display:inline-flex}
.streak-xp .xp-flash{color:var(--accent-text);font-weight:600}
.streak-bar.hit .streak-xp .xp-flash{color:var(--honey-deep);font-weight:700}
html.dark .streak-bar.hit .streak-xp .xp-flash{color:var(--honey)}
/* Badge haul — sits between stats row and Save&exit on the Focus done screen.
   Only renders if newBadges.length > 0. Each badge slides in from right
   staggered var(--duration-xs) apart for a parade-style reveal. */
.fc-haul{margin:18px 0 4px;padding:14px 12px 18px;background:var(--surface-alt);border-radius:var(--radius-lg);border:1px solid var(--border)}
.fc-haul-title{font-size:var(--font-size-xs);font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.06em;margin-bottom:11px}
.fc-haul-row{display:flex;justify-content:center;gap:14px;overflow-x:auto;padding:6px 4px 4px;scrollbar-width:none}
.fc-haul-row::-webkit-scrollbar{display:none}
@keyframes haulSlideIn{from{opacity:0;transform:translateX(40px) scale(0.7)}to{opacity:1;transform:none}}
.fc-badge-haul{
  display:flex;flex-direction:column;align-items:center;gap:5px;flex-shrink:0;
  animation:haulSlideIn .42s var(--ease-spring) backwards;
}
.fc-badge-haul:nth-child(1){animation-delay:0ms}
.fc-badge-haul:nth-child(2){animation-delay:80ms}
.fc-badge-haul:nth-child(3){animation-delay:160ms}
.fc-badge-haul:nth-child(4){animation-delay:240ms}
.fc-badge-haul:nth-child(5){animation-delay:320ms}
.fc-badge-haul:nth-child(6){animation-delay:400ms}
/* B9-fix: suppress haul slide-in animation under reduced motion. */
@media(prefers-reduced-motion:reduce){.fc-badge-haul{animation:none}}
.fc-badge-haul-icon{
  width:48px;height:48px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-size:24px;line-height:1;
  background:var(--bg);
  border:2px solid var(--gold);
  box-shadow:0 0 0 4px rgba(255,217,61,0.2),0 2px 8px rgba(0,0,0,0.08);
  transition:transform .15s;
}
.fc-badge-haul.tier-silver .fc-badge-haul-icon{border-color:var(--tier-silver);box-shadow:0 0 0 4px rgba(192,192,192,0.25),0 2px 8px rgba(0,0,0,0.08)}
.fc-badge-haul.tier-bronze .fc-badge-haul-icon{border-color:var(--tier-bronze);box-shadow:0 0 0 4px rgba(205,127,50,0.22),0 2px 8px rgba(0,0,0,0.08)}
.fc-badge-haul.tier-platinum .fc-badge-haul-icon{border-color:var(--tier-platinum);box-shadow:0 0 0 4px rgba(155,213,255,0.3),0 2px 8px rgba(0,0,0,0.1)}
.fc-badge-haul:hover .fc-badge-haul-icon{transform:scale(1.1)}
.fc-badge-haul-name{font-size:var(--font-size-2xs);font-weight:700;color:var(--text);max-width:72px;line-height:1.2;text-align:center}
.fc-badge-haul-tier{font-size:9px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.06em}
/* Nemesis card — top-missed recall card, sits below the streak bar.
   Contrast bumped per Julian feedback: title uses coral 800 (light) /
   coral 100 (dark) for ~9:1 contrast vs the surface-alt2 background. */
/* P1·4 — coral left-stripe rendered as an inset overlay rather than a
   3px border. The card carries a uniform 1px border on all four sides
   (so the corners radius cleanly), and a position:absolute ::before
   draws the coral 3px bar inside the rounded-corner inset. Net effect:
   the coral reads as the primary visual anchor without the asymmetric-
   border-width corner artefacts the previous border-left:3px caused. */
.nem{
  position:relative;margin:var(--section-gap,12px) 0 0;padding:11px 13px 11px 16px;
  background:var(--surface-alt2);border:1px solid var(--border);
  border-radius:var(--radius);cursor:pointer;
  transition:transform var(--duration-sm),box-shadow .15s;overflow:hidden;
}
.nem::before{
  content:"";position:absolute;left:0;top:0;bottom:0;
  width:3px;background:var(--coral);
}
.nem.tamed::before{background:var(--accent)}
.nem:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm)}
/* (border-left-color rule retired — tamed colour now lives on ::before above) */
.nem-head{display:flex;align-items:center;gap:8px;font-size:var(--font-size-sm)}
.nem-emoji{font-size:18px;line-height:1;flex-shrink:0}
.nem-title{font-weight:700;font-size:var(--font-size-sm);color:var(--coral-deep);text-transform:uppercase;letter-spacing:0.05em}
html.dark .nem-title{color:var(--coral)}
.nem.tamed .nem-title{color:var(--accent-pressed)}
html.dark .nem.tamed .nem-title{color:var(--accent-text)}
/* Today-fix v2 #3 — Nemesis attempt pips. Three slots showing last 3
   attempts (or pending placeholders when no history yet). Got = sage,
   missed = coral, pending = neutral grey. The whole strip carries a
   screen-reader aria-label summarising the history. */
.nem-misses{
  margin-left:auto;
  display:inline-flex;align-items:center;gap:5px;
}
.nem-pip{
  width:9px;height:9px;border-radius:50%;
  border:1px solid var(--border);
  background:var(--surface-alt);
  flex-shrink:0;
}
/* patch-009 — four-tier grade pips (Mastered / Honed / Hazy / Blank). */
.nem-pip--g4     {background:var(--accent);    border-color:var(--accent)}
.nem-pip--g3     {background:var(--sage);      border-color:var(--sage)}
.nem-pip--g2     {background:var(--amber);     border-color:var(--amber)}
.nem-pip--g1     {background:var(--coral);     border-color:var(--coral)}
.nem-pip--pending{background:transparent;      border-color:var(--border-strong);opacity:0.7}
.nem-prompt{font-size:var(--font-size-lg);font-weight:500;color:var(--text);margin:7px 0 8px;line-height:1.4}
.nem-history{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.nem-dots{display:flex;gap:5px}
.nem-dot{width:9px;height:9px;border-radius:50%;background:var(--surface-alt);border:1px solid var(--border)}
.nem-dot--g4{background:var(--accent);border-color:var(--accent)}
.nem-dot--g3{background:var(--sage);  border-color:var(--sage)}
.nem-dot--g2{background:var(--amber); border-color:var(--amber)}
.nem-dot--g1{background:var(--coral); border-color:var(--coral)}
.nem-tag{font-size:var(--font-size-xs);color:var(--text-muted);font-style:italic}
.nem-tame{margin-top:7px;font-size:var(--font-size-xs);color:var(--accent-pressed);font-weight:600}
html.dark .nem-tame{color:var(--accent-text)}
.nem-tame .progress{font-variant-numeric:tabular-nums;background:var(--accent-soft);padding:1px 5px;border-radius:var(--btn-radius);margin-left:4px;color:var(--accent-pressed)}
html.dark .nem-tame .progress{color:var(--accent-text)}
.icon-btn{
  width:38px;height:38px;border-radius:var(--radius-md);
  border:1px solid var(--border);background:var(--surface);
  cursor:pointer;display:inline-flex;align-items:center;justify-content:center;
  font-size:var(--font-size-2xl);color:var(--text);transition:background .15s,color .15s,border-color .15s,box-shadow .15s,transform .15s,opacity .15s;
}
.icon-btn:hover{background:var(--surface-alt);border-color:var(--accent);color:var(--accent)}
.icon-btn:active{transform:scale(0.96)}
.icon-btn .icn{width:18px;height:18px}
/* R-027 — :focus-visible rings for all icon-level interactive elements.
   Restores keyboard-visible focus that outline:none strips.
   Phase 4: transition:outline-offset .1s so ring pops in rather than snapping. */
.icon-btn:focus-visible,
.gear-tap:focus-visible,
.ns-modal-close:focus-visible,
.card-flag-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:3px;transition:outline-offset .1s}
@media(prefers-reduced-motion:reduce){
  .icon-btn:focus-visible,.gear-tap:focus-visible,
  .ns-modal-close:focus-visible,.card-flag-btn:focus-visible,
  .tab:focus-visible{transition:none}
}
/* WS11 v9.7-foundation (2026-05-19) — Universal :focus-visible baseline.
   WCAG 2.2 SC 2.4.13 (Focus Appearance): ≥2px ring, ≥3:1 contrast vs adjacent.
   Specificity 0,0,1 (the * + :focus-visible pseudo) so any per-component ring
   (R-027, .saq-callout-btn, .toggle, etc.) still wins. Sites that previously
   stripped outline:none without replacement now inherit this ring automatically.
   Per-element `outline:none` should be paired with a custom ring (box-shadow)
   or removed — never left bare. */
*:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:3px}

/* v10 (2026-05-19) — .phase-dot primitive.
   Section/phase taxonomy chip used in Today queue, Library, Curriculum tree,
   and any list/row where a card needs "which body system?" wayfinding.
   Set --phase-color on the element (typically via inline style from a render fn
   that calls sectionColor(letter)). Default size 6px dot; the inline label is
   optional. See DESIGN-SYSTEM.md §1 v10 + DEC-026 (body-system mapping). */
.phase-dot{
  display:inline-flex;align-items:center;gap:6px;
  padding:2px 8px 2px 6px;
  background:color-mix(in srgb,var(--phase-color) 14%,transparent);
  border:1px solid color-mix(in srgb,var(--phase-color) 40%,transparent);
  border-radius:var(--radius-pill);
  font-size:var(--font-size-2xs,10px);font-weight:600;
  color:color-mix(in srgb,var(--phase-color) 30%,var(--text));
  white-space:nowrap;
}
.phase-dot::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--phase-color);display:inline-block;flex-shrink:0}
.phase-dot--bare{padding:0;background:transparent;border:none;color:var(--text-faint)} /* dot-only variant */

/* v10 — .pp-grade-bar segmented progress primitive (grade tokens, NOT Dusk).
   4 segments: mastered, honed, hazy, missed. Pending = empty bar bg.
   Width set inline per segment from per-phase grade counts.
   See DESIGN-SYSTEM.md §1 v10 — phase-progress uses grade tokens; phase
   identity stays in a small header dot, never on the bar (Tier-D discipline #4). */
.pp-grade-bar{
  height:6px;background:var(--surface-elevated);border-radius:var(--radius-pill);
  overflow:hidden;border:1px solid var(--border);display:flex;
}
.pp-grade-bar>.seg{height:100%;transition:width .15s}
.pp-grade-bar>.seg--mastered{background:var(--grade-mastered)}
.pp-grade-bar>.seg--honed{background:var(--grade-honed)}
.pp-grade-bar>.seg--hazy{background:var(--grade-hazy)}
.pp-grade-bar>.seg--missed{background:var(--grade-missed)}

.subtitle{color:var(--text-muted);font-size:var(--font-size-md)}
.badges{display:flex;gap:5px;flex-wrap:wrap}
.badge{display:inline-block;padding:3px 8px;border-radius:var(--btn-radius);font-size:var(--font-size-xs);font-weight:600;line-height:1.3}
.badge-day1{background:var(--sky-fill);color:var(--sky-deep)}
html.dark .badge-day1{background:var(--sky-soft);color:var(--sky)}
.badge-warn{background:var(--warn-bg);color:var(--warn)}
.badge-verify{background:var(--amber-bg);color:var(--honey-deep)}
html.dark .badge-verify{color:var(--amber)}
.badge-live{background:var(--green-bg);color:var(--green)}

/* §4E confidence pill mapping — multi-accent per v9.1 §1.
   Critical → coral, Low → honey, Intermediate → sage-fill (light) /
   sage-deep (dark via aliasing), High → sage filled. Token-driven so
   light/dark resolve automatically. */
.badge-confidence{padding:2px 7px;font-size:var(--font-size-xs);font-weight:600;letter-spacing:0.02em}
/* patch-008 — universal Missed / Honed / Mastered. The library card
   confidence badge is rendered via badge-{Missed|Honed|Mastered}. */
.badge-Missed      {background:var(--coral-fill);color:var(--coral-deep)}
.badge-Honed       {background:var(--honey-fill);color:var(--honey-deep)}
.badge-Mastered    {background:var(--accent);    color:var(--accent-on)}
.badge-unrated{background:var(--surface-alt);color:var(--text-faint)}

/* --- Tabs (adaptive: icon-only mobile, icon+text desktop) ---
   Centred horizontally per post-v9.1 audit feedback. Below 640px the
   tab text hides anyway; the icon row stays scrollable for narrow
   viewports without losing the centre alignment on wide screens. */
.tabs{
  display:flex;justify-content:center;gap:4px;
  border-bottom:1px solid var(--border);
  margin:0 0 14px;position:sticky;top:0;background:var(--bg);
  z-index:8;padding:6px 0 0;overflow-x:auto;scrollbar-width:none;
}
.tabs::-webkit-scrollbar{display:none}
.tab{
  padding:10px 12px;min-height:44px;background:transparent;border:none;border-bottom:2px solid transparent;
  cursor:pointer;font-size:var(--font-size-md);font-weight:600;color:var(--text-muted);
  font-family:inherit;display:flex;align-items:center;gap:7px;white-space:nowrap;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.tab:hover{color:var(--text)}
.tab.active{color:var(--accent-text);border-bottom-color:var(--accent)}
/* §4H Active state — underline only, no rounded outline. The browser focus
   ring is gated behind :focus-visible so keyboard navigation still gets a
   visible ring without polluting mouse / touch interaction. AP9 fix. */
.tab:focus{outline:none}
.tab:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:0;transition:outline-offset .1s}
.tab .icn{width:18px;height:18px}
.tab .tab-text{display:none}
@media(min-width:640px){
  .tab{padding:9px 16px}
  .tab .tab-text{display:inline}
}
/* Admin flag badge — only flex when not hidden (avoids ghost dot from inline display:flex + hidden attr clash) */
#adminFlagCount:not([hidden]){display:flex}
/* §4H Tab count chip — numeric badge, never an unlabelled colour-only
   dot. Renderer hides the chip entirely when count is 0. AP4 fix.
   Today-fix #11 — count chip ONLY renders when its parent tab is the
   active tab. When the user is on a different tab, the count hides
   so the menu bar stays uncluttered. */
.tab .count{
  display:inline-block;background:var(--accent-soft);color:var(--accent-text);
  font-size:var(--font-size-2xs);padding:1px 6px;border-radius:var(--radius-pill);font-weight:500;
  min-width:14px;text-align:center;line-height:1.4;margin-left:4px;
}
.tab .count[hidden]{display:none}
.tab .count{display:none!important}/* v125 — never show card counts on tabs */
.tab-content{display:none;background:var(--bg)}
.tab-content.active{display:block;animation:fadeIn .15s}
/* Opacity-only animation — the prior transform:translateY triggered GPU layer
   creation on iOS which invalidated the tab bar backdrop-filter, causing a
   white flash. Pure opacity avoids the stacking-context churn. */
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion: reduce){.tab-content.active{animation:none}}

/* --- Setup strip — Phase 1 dynamic dashboard --- */
/* Post-audit: subtitle-row is now justified to the centre under the
   wordmark. The subtitle-text drops its flex:1 stretch so the content
   can shrink-to-fit and stay properly centred, with ellipsis still
   active on overflow. */
.subtitle-row{display:flex;flex-direction:column;align-items:center;gap:4px;margin-top:2px;max-width:100%;min-width:0}
/* hdr-block truncates long block names (e.g. "B3 Respiratory") with ellipsis;
   abbreviated form set by JS — full block name always present in title tooltip. */
.hdr-block{font-size:var(--font-size-sm);font-weight:500;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:180px;cursor:pointer;display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:var(--btn-radius);border:1px solid transparent;transition:background var(--duration-sm),border-color .12s}
.hdr-block:hover{background:var(--surface-alt2);border-color:var(--border)}
.hdr-block::after{content:'⌄';font-size:var(--font-size-2xs);opacity:.55;line-height:1}
.hdr-block.has-mismatch{background:color-mix(in srgb,var(--coral) 12%,transparent);border-color:color-mix(in srgb,var(--coral) 35%,var(--border));color:var(--coral-deep, var(--text))}
html.dark .hdr-block.has-mismatch{color:var(--coral)}
.hdr-meta{font-size:var(--font-size-xs);color:var(--text-muted);white-space:nowrap;display:flex;align-items:center;gap:5px}
.hdr-date{display:none;font-size:var(--font-size-sm);color:var(--text-muted)}
.hdr-due-badge{display:inline-flex;align-items:center;padding:0px 6px;border-radius:var(--radius-pill);background:color-mix(in srgb,var(--red) 12%,var(--surface));border:0.5px solid var(--red);font-size:var(--font-size-xs);font-weight:600;color:var(--red);line-height:18px}
.hdr-due-badge.done{background:color-mix(in srgb,var(--green) 10%,var(--surface));border-color:var(--green);color:var(--green)}
/* hdr-stats: replaces pill chips in header; plain coloured spans, no border/padding overhead */
.hdr-stats{display:flex;align-items:center;gap:4px;white-space:nowrap;overflow:hidden;color:var(--text-muted);font-size:11px}
.hdr-stat--due       {color:var(--red);font-weight:600}
.hdr-stat--axiom     {color:var(--saltbush);font-weight:600}
.hdr-stat--pearl     {color:var(--honey);font-weight:600;display:inline-flex;align-items:center;gap:2px}
.hdr-stat--pearl .icn{width:11px;height:11px}
/* FSRS global-state row (D) + session-split row (B) */
.hdr-stat--fsrs-new  {color:var(--sky-deep);font-weight:600}
.hdr-stat--fsrs-learn{color:var(--amber);font-weight:600}
.hdr-stat--fsrs-mat  {color:var(--sage);font-weight:600}
.hdr-stat--fsrs-over {color:var(--red);font-weight:700}
.hdr-stat--fsrs-rev  {color:var(--text-faint);font-weight:600}
/* dark: --sky-deep resolves to lime-gold (axiom); override to sky-blue (recall). --sage→sky-blue clashes with new, so mature gets --sky (lime-gold) */
html.dark .hdr-stat--fsrs-new  {color:var(--sage)}
html.dark .hdr-stat--fsrs-mat  {color:var(--sky)}
/* Tooltip — pointer:fine only (no hover on iOS) */
@media(pointer:fine){
  /* Both .app-title and .hdr-stats carry overflow:hidden by default to
     constrain text. That also clips the absolutely-positioned ::after
     tooltip. Override both here so the tooltip can escape its container.
     The h1 handles its own overflow independently (text-overflow:ellipsis). */
  .app-title{overflow:visible}
  .hdr-stats{overflow:visible}
  .hdr-tip{position:relative}
  .hdr-tip::after{
    content:attr(data-tip);
    position:absolute;bottom:calc(100% + 7px);left:50%;transform:translateX(-50%);
    background:var(--text);color:var(--bg);
    font-size:10px;font-weight:500;line-height:1.3;
    padding:4px 8px;border-radius:var(--btn-radius);white-space:nowrap;
    pointer-events:none;z-index:200;
    opacity:0;transition:opacity var(--duration-sm) .25s;
  }
  .hdr-tip:hover::after{opacity:1}
}
/* Wide header (>480px): single horizontal row — [dots | node | stats], centred as a group */
@media(min-width:481px){
  .app-title{
    display:flex;
    flex-direction:row;
    justify-content:center;
    align-items:center;
    gap:16px;
    width:100%;
    text-align:left;
  }
  .subtitle-row{display:contents}
  .hdr-block{order:2;max-width:280px;font-size:13px;font-weight:600}
  .hdr-stats{order:3;font-size:12px;gap:6px;flex-shrink:0}
  .hdr-stat--pearl .icn{width:12px;height:12px}
  #hdrDeckState{order:2}
  #hdrMeta{order:3}
}
/* Compact header (≤480px): 3-row layout — node / stats / dots, within same height budget */
@media(max-width:480px){
  .app-header{padding:4px 0 2px}
  .app-title{gap:1px}
  .hdr-block{font-size:10.5px;padding:0 4px}
  .hdr-block::after{display:none}
  .hdr-stats{font-size:9.5px;gap:3px}
  .hdr-stat--pearl .icn{width:9px;height:9px}
}
.gear-tap{
  display:inline-flex;align-items:center;justify-content:center;
  width:24px;height:24px;border-radius:50%;border:none;background:transparent;
  color:var(--text-muted);cursor:pointer;font-family:inherit;padding:0;flex-shrink:0;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.gear-tap:hover,.gear-tap.active{background:var(--surface-alt);color:var(--accent)}
.gear-tap .icn{width:15px;height:15px}
/* Gear in subtitle-row: only visible on wide pointer screens */
.gear-tap--subtitle{align-self:center}
body[data-input="touch"] .gear-tap--subtitle{display:none!important}
@media(max-width:599px){.gear-tap--subtitle{display:none!important}}
/* WS2 (Phase 9, 2026-05-05) — .gen-cta + .gen-cta-head removed (#genCtaPanel
   retired session 68; HTML deleted + CSS unused).
   .gen-cta-pills KEPT — still consumed by live setupExpandedPanel layout. */
.gen-cta-pills{display:flex;gap:7px;flex-wrap:wrap}
.setup-pill{
  display:inline-flex;align-items:center;gap:6px;position:relative;
  padding:8px 12px;font-size:var(--font-size-md);font-weight:600;
  background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);
  color:var(--text);cursor:pointer;font-family:inherit;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);flex:1;justify-content:center;min-width:130px;
}
.setup-pill:hover{border-color:var(--accent);color:var(--accent)}
.setup-pill .icn{width:14px;height:14px}
.setup-pill .chev{width:11px;height:11px;color:var(--text-faint);margin-left:auto}
.btn-primary-fw{
  width:100%;padding:13px;background:var(--accent);color:white;
  border:none;border-radius:var(--radius-md);font-size:var(--font-size-lg);font-weight:700;cursor:pointer;
  font-family:inherit;box-shadow:0 3px 0 var(--accent-pressed);transition:background .1s,color .1s,border-color .1s,box-shadow .1s,transform .1s,opacity .1s;
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
}
.btn-primary-fw:hover{transform:translateY(-1px);box-shadow:0 4px 0 var(--accent-pressed)}
.btn-primary-fw:active{transform:translateY(2px);box-shadow:0 1px 0 var(--accent-pressed)}
.btn-primary-fw:disabled{opacity:0.6;cursor:wait;box-shadow:0 2px 0 var(--accent-pressed)}
.btn-primary-fw .icn{width:15px;height:15px}
.setup-expanded{
  margin:11px 0 0;padding:12px 13px;
  background:var(--accent-soft);border:1px solid var(--accent);border-radius:var(--radius);
  display:flex;flex-direction:column;gap:10px;animation:slideDown var(--duration-md) ease-out;
}
@keyframes slideDown{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
.setup-expanded-head{display:flex;align-items:center;font-size:var(--font-size-xs);color:var(--text-muted);text-transform:uppercase;letter-spacing:0.05em;font-weight:600}
.setup-expanded-head .close{margin-left:auto;background:none;border:none;color:var(--text-faint);cursor:pointer;padding:2px;display:inline-flex;align-items:center}
.setup-expanded-head .close:hover{color:var(--text)}
.setup-expanded-head .close .icn{width:14px;height:14px}
.setup-expanded-meta{font-size:var(--font-size-xs);color:var(--text-muted);font-style:italic;margin-top:1px}
.setup-dropdown{
  position:absolute;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  box-shadow:var(--shadow-md);padding:5px 0;font-size:var(--font-size-md);width:230px;z-index:60;
  top:100%;left:0;margin-top:4px;display:none;
}
.setup-dropdown.open{display:block}
.setup-dropdown .opt{padding:8px 12px;cursor:pointer;display:flex;align-items:center;gap:8px;color:var(--text)}
.setup-dropdown .opt:hover{background:var(--surface-alt)}
.setup-dropdown .opt.sel{background:var(--accent-soft);color:var(--accent-pressed);font-weight:600}
html.dark .setup-dropdown .opt.sel{color:var(--accent)}
.setup-dropdown .opt-sub{font-size:var(--font-size-xs);color:var(--text-muted);font-weight:400;margin-left:auto}
.setup-dropdown .opt .icn{width:14px;height:14px}

/* --- Streak bar (v2 polish — primary streak block + secondary stats) --- */
.streak-bar{
  display:flex;align-items:center;gap:12px;padding:11px 14px;
  background:linear-gradient(135deg,var(--accent-soft) 0%,var(--bg) 60%);
  border:1px solid var(--border);border-radius:var(--radius);
  /* §3 T5 — use --section-gap (12px) so the rhythm between Streak → Hero
     → Nemesis → Rapid Recall heading is consistent. */
  margin:var(--section-gap,12px) 0 0;font-size:var(--font-size-sm);flex-wrap:wrap;cursor:pointer;
  transition:transform var(--duration-sm), box-shadow .15s;
  /* T-P1-01 — needed for .streak-xp-bar absolute bottom-edge indicator */
  position:relative;overflow:hidden;
}
.streak-bar:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm)}
/* Primary streak block — flame + bold number + label, visually dominant */
.streak-primary{
  display:flex;align-items:center;gap:8px;padding-right:12px;
  border-right:1px solid var(--border);
}
.streak-primary .streak-flame{font-size:var(--font-size-3xl);line-height:1}
.streak-primary .streak-number{font-size:20px;font-weight:700;color:var(--accent-pressed);line-height:1;font-variant-numeric:tabular-nums}
html.dark .streak-primary .streak-number{color:var(--accent)}
/* Today-fix #1 — number + label sit inline (was display:block which
   stacked the label below the number). Now baseline-aligned in the
   parent flex row so they read as a single 'X DAY STREAK' phrase. */
.streak-primary .streak-label{font-size:var(--font-size-xs);color:var(--text-muted);text-transform:uppercase;letter-spacing:0.05em;font-weight:600;align-self:baseline}
/* Freeze count badge — only renders when freezes are banked. Sky family
   for "reference / informational" per v9.1 §1. */
.streak-freeze{
  display:none;align-items:center;gap:4px;
  font-size:var(--font-size-xs);font-weight:600;color:var(--sky-deep);
  background:var(--sky-fill);border-radius:var(--radius-sm);padding:2px 7px;
}
html.dark .streak-freeze{color:var(--sky);background:var(--sky-soft)}
.streak-freeze.shown{display:inline-flex}
.streak-item{display:flex;align-items:center;gap:5px;color:var(--text);font-weight:500}
/* P1·1 — uppercase every meta label in the streak band so the band reads
   as a tight stat strip alongside the 'DAY STREAK' primary label. The
   numeric values stay in their natural casing (mostly digits anyway). */
.streak-item .label{color:var(--text-muted);font-size:var(--font-size-xs);font-weight:500;text-transform:uppercase;letter-spacing:0.05em}
.streak-item .icn{width:14px;height:14px;color:var(--accent)}
/* Today-fix #2 — week pips render Monday→Sunday with day labels. Today's
   column is the visual anchor: pip bumps to 14px, fills solid with
   var(--accent), gets a glow ring; weekday label is bolder + brighter.
   Filled (mint) days are completed; partial (honey) means a partial
   session; future days render outlined; before-today days that you
   missed render in --text-faint outline. */
.streak-progress{display:flex;gap:10px;margin-left:auto;align-items:flex-end}
/* Audit fix — column min-width so today's 14px pip doesn't shift the
   layout vs the 12px non-today pips. All columns reserve the same
   horizontal real-estate; only the contents differ. */
.streak-day{display:flex;flex-direction:column;align-items:center;gap:4px;min-width:18px}
.streak-day-label{font-size:9.5px;color:var(--text-faint);text-transform:uppercase;letter-spacing:0.04em;line-height:1;font-weight:500}
.streak-day--today .streak-day-label{color:var(--text);font-weight:700;font-size:var(--font-size-xs)}
.streak-day--future .streak-day-label{color:var(--text-faint);opacity:0.55}
.streak-dot{width:12px;height:12px;border-radius:50%;background:var(--surface-alt);border:1px solid var(--border);transition:background .2s}
.streak-dot.filled{background:var(--green);border-color:var(--green);box-shadow:0 0 6px color-mix(in srgb,var(--accent) 35%,transparent)}
.streak-dot.partial{background:var(--amber);border-color:var(--amber)}
/* Today-fix v2 — today's pip stays the SAME size as the others (12px) so
   the pip row reads as an even rhythm. Honey fill marks today (warm
   colour family, distinct from mint completed days), with a subtle
   honey-soft ring for emphasis. The bold weekday letter (set via
   .streak-day--today .streak-day-label) carries the secondary cue. */
.streak-dot.today{
  background:var(--honey);border-color:var(--honey);
  box-shadow:0 0 0 2px color-mix(in srgb,var(--honey) 30%,transparent);
}
.streak-day--future .streak-dot{opacity:0.5}

/* --- Banners --- */
.banner{
  padding:12px 14px;border-radius:var(--radius-sm);margin:11px 0 8px;
  font-size:var(--font-size-md);display:flex;align-items:flex-start;gap:9px;line-height:1.45;
}
.banner-info{background:var(--accent-soft);color:var(--accent-pressed);border-left:3px solid var(--accent)}
html.dark .banner-info{color:var(--accent)}
.banner-warn{background:var(--warn-bg);color:var(--honey-deep);border-left:3px solid var(--warn)}
html.dark .banner-warn{color:var(--warn)}
.banner-err{background:var(--red-bg);color:var(--coral-deep);border-left:3px solid var(--red)}
html.dark .banner-err{color:var(--red)}
.banner-ok{background:var(--green-bg);color:var(--sage-deep);border-left:3px solid var(--green)}
html.dark .banner-ok{color:var(--green)}
.all-done-banner{display:flex;align-items:center;justify-content:space-between;gap:8px}
.all-done-banner-dismiss{background:none;border:none;cursor:pointer;color:inherit;opacity:.5;padding:2px 6px;font-size:14px;line-height:1;border-radius:var(--radius-tiny);flex-shrink:0}
.all-done-banner-dismiss:hover{opacity:1;background:rgba(0,0,0,.08)}

/* --- Cards (general) — stats / chart tiles ---
   WS4 (2026-05-05): original .card renamed to .tile so .card can become
   the unified study-card primitive. Stat-cards + chart-cards compose
   .stat-card / .chart-card directly; .tile is used by any generic wrapper
   that needs the same neutral surface treatment. */
.tile{background:var(--surface-alt2);border:1px solid var(--border);border-radius:var(--radius);padding:13px;transition:transform var(--duration-sm),box-shadow .15s}
.tile:hover{box-shadow:var(--shadow-sm)}

/* --- Details/Toggles --- */
details{margin:8px 0;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface)}
details>summary{padding:10px 13px;cursor:pointer;list-style:none;font-weight:500;display:flex;align-items:center;gap:8px;font-size:var(--font-size-lg)}
details>summary::-webkit-details-marker{display:none}
/* §9 Disclosure carets — SVG chevron data URI, never Unicode ▸ ▾.
   Inline data URI keeps the all-CSS / no-build constraint while killing
   AP19. Stroke uses currentColor so the caret follows summary text colour. */
details>summary::before{
  content:"";display:inline-block;width:14px;height:14px;flex-shrink:0;
  background-color:var(--text-muted);
  -webkit-mask-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
          mask-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;
  transition:transform .15s;
}
details[open]>summary::before{transform:rotate(90deg)}
details .toggle-body{padding:10px 13px 13px 30px;border-top:1px solid var(--border);font-size:var(--font-size-lg);line-height:1.55}
details .toggle-body p{margin:6px 0}
details .toggle-body ul{margin:6px 0;padding-left:20px}
details .toggle-body strong.hl{font-weight:600;background:var(--honey-fill);padding:0 2px;border-radius:var(--radius-2xs)}
html.dark details .toggle-body strong.hl{background:var(--honey-soft);color:var(--honey)}
.eq{font-family:var(--font-mono);background:var(--surface-alt);padding:6px 10px;border-radius:var(--radius-tiny);display:inline-block;margin:3px 0;font-size:var(--font-size-md)}

/* Today-fix v2 #4 — math formula wrap. KaTeX renders display equations
   inside .katex-display (a centred block) with white-space:nowrap so
   the formula never breaks; long formulae overflow the recall card.
   Override:
   - .katex-display: allow inline-line wrap via white-space:normal +
     word-break, plus overflow-x:auto as a fallback for genuinely
     unbreakable content (e.g., single fraction taller than the card).
   - .katex (inline math): also allow wrap so inline mid-paragraph
     formulae don't push the column.
   Tweaking the inner .katex-html is risky (KaTeX repositions glyphs
   absolutely); leaving its layout alone and just relaxing the parent
   white-space + max-width is the safe surgical fix. */
.katex-display{
  white-space:normal !important;
  overflow-x:auto;
  max-width:100%;
  margin:8px 0;
}
.katex-display>.katex{
  white-space:normal;
  display:block;
  text-align:center;
}
.katex{max-width:100%;display:inline-block;white-space:normal}
/* Long fractions / radicals can still exceed the column when content
   is unbreakable (e.g., single denominator longer than the card width).
   The horizontal scroll bar on .katex-display catches that fall-through
   so the formula stays readable rather than clipped. */
.recall-answer .katex-display,
.recall-card .katex-display,
.fc-answer .katex-display{max-width:100%;overflow-x:auto}

/* =====================================================
   WS4 (Phase 9, 2026-05-05) — Unified Card primitive
   Single shape for recall / saq / pharma / axiom.
   Type identity via [data-card-type] + left-stripe colour.
   Mode contracts (browse/today/preview) preserved exactly.
   ===================================================== */

/* Card base — all 4 study card types compose this */
.card{
  position:relative;
  background:var(--surface-alt2);
  border:1px solid var(--border);
  border-left:var(--card-stripe-width) solid var(--card-stripe,var(--accent));
  border-radius:var(--card-radius);
  padding:var(--card-padding-block) var(--card-padding-inline);
  display:flex;flex-direction:column;gap:9px;
  box-shadow:var(--card-shadow);
  transition:
    background var(--duration-sm) var(--ease-out),
    border-color var(--duration-sm) var(--ease-out),
    box-shadow var(--duration-sm) var(--ease-out),
    transform var(--duration-sm) var(--ease-out);
}
.card:hover{box-shadow:var(--card-shadow-hover)}

/* Slots */
.card__header{display:flex;align-items:flex-start;gap:8px;margin-bottom:0;padding-right:calc(var(--card-flag-right) + 14px)}
.card__body{display:flex;flex-direction:column;gap:8px}
.card__footer{display:flex;gap:6px;margin-top:auto}
/* Sticky footer — opt-in via [data-sticky]; used by SAQ rate row */
.card__footer[data-sticky]{
  position:sticky;bottom:0;
  background:var(--surface);
  margin-inline:-14px;margin-bottom:-14px;
  padding:8px 14px 14px;
  border-top:1px solid var(--border);
  z-index:2;
}

/* Type variants — WS11: aligned to WS10 identity tokens.
   Recall=sky(LM)/sage(DM), SAQ=rose, Axiom=lime, Pharma=violet */
.card[data-card-type="recall"]{
  --card-stripe:var(--sky);
  background:color-mix(in srgb,var(--sky) var(--card-tint-light),var(--surface));
}
.card[data-card-type="saq"]{
  --card-stripe:var(--rose);
  background:color-mix(in srgb,var(--rose) var(--card-tint-light),var(--surface));
}
.card[data-card-type="pharma"]{
  --card-stripe:var(--violet);
  background:color-mix(in srgb,var(--violet) var(--card-tint-light),var(--surface));
}
.card[data-card-type="axiom"]{
  --card-stripe:var(--saltbush);
  background:color-mix(in srgb,var(--saltbush) var(--card-tint-light),var(--surface));
}

/* WS11 — DM overrides. --sky DM = lime-gold (Axiom); recall must use --sage (sky-blue) */
html.dark .card[data-card-type="recall"]{--card-stripe:var(--sage);background:color-mix(in srgb,var(--sage) var(--card-tint-dark),var(--surface))}
html.dark .card[data-card-type="saq"]   {background:color-mix(in srgb,var(--rose)   var(--card-tint-dark),var(--surface))}
html.dark .card[data-card-type="pharma"]{background:color-mix(in srgb,var(--violet) var(--card-tint-dark),var(--surface))}
html.dark .card[data-card-type="axiom"] {background:color-mix(in srgb,var(--saltbush)   var(--card-tint-dark),var(--surface))}

/* Mode contracts */
.card[data-mode="browse"]{cursor:pointer}
.card[data-mode="browse"] *[data-no-card-click]{cursor:auto}
/* Preview mode — footer hidden (preview is read-only; rate row not shown) */
.card[data-mode="preview"] .card__footer{display:none}

/* Active-card state — unified Effect 6. Single rule for all types. */
.card.keyboard-focused{
  transition:transform var(--duration-sm) var(--ease-out), box-shadow var(--duration-sm) var(--ease-out), padding var(--duration-sm) var(--ease-out), background var(--duration-sm) var(--ease-out), border-left-width var(--duration-sm) var(--ease-out);
  transform:translateY(-1px);
  border-left-width:calc(var(--card-stripe-width) + 2px);
  padding-left:calc(var(--card-padding-inline) - 2px);
  background:color-mix(in srgb,var(--card-stripe,var(--accent)) 10%,var(--surface-alt2));
  box-shadow:0 4px 14px -4px color-mix(in srgb,var(--card-stripe,var(--accent)) 40%,transparent);
}
@media(prefers-reduced-motion:reduce){
  .card.keyboard-focused{transform:none;transition:background var(--duration-sm) var(--ease-out)}
}

/* =====================================================
   CARD REDESIGN 2026-05-05 — .study-card primitive
   Replaces the dead WS4-phase-9 .card[data-card-type] system above.
   Coexists with legacy .recall-card / .saq-card-face / .pharma-card /
   .axiom rules below until phase 2 migrates the JS render functions.
   Spec: docs/CARD-REDESIGN-SPEC.md
   ===================================================== */

.study-card{
  position:relative;
  background:var(--surface);
  border:1px solid var(--border);
  border-left:var(--card-stripe-width) solid var(--card-accent,var(--sky));
  border-radius:var(--card-radius);
  padding:var(--study-card-padding-cmf);
  display:flex;flex-direction:column;gap:9px;
  transition:
    background var(--duration-sm) var(--ease-out),
    border-color var(--duration-sm) var(--ease-out),
    border-left-color var(--duration-sm) var(--ease-out),
    box-shadow var(--duration-sm) var(--ease-out),
    transform var(--duration-sm) var(--ease-out);
}
.study-card:hover{box-shadow:var(--shadow-1)}

/* Restrained palette — bg lifts only in dark mode (6%); light mode keeps
   surface neutral so stripe alone carries identity. Spec §2 + §21. */
html.dark .study-card{
  background:color-mix(in srgb,var(--card-accent,var(--sky)) var(--study-card-tint-dark),var(--surface));
}

/* Cinema-scope override (2026-05-05 IMPROVE) — cinema cards (.fc-card) define
   their own padding via children's margins; the .study-card 14 px padding
   double-pads cinema and mis-aligns the Show Answer button + clips tall SAQ
   content. Reset padding/gap for cinema to restore legacy layout. */
.fc-card.study-card{padding:0;gap:0}

/* Type variants — only set --card-accent. Card-redesign 2026-05-05 IMPROVE:
   use *-deep tokens for stronger stripe contrast on warm paper. Mid-tone
   accent (--sky/--rose/etc) blended into cream looked too quiet. */
.study-card--recall{--card-accent:var(--sky-deep)}
.study-card--saq   {--card-accent:var(--rose-deep)}
.study-card--pharma{--card-accent:var(--violet-deep)}
.study-card--axiom {--card-accent:var(--saltbush-deep)}
html.dark .study-card--recall{--card-accent:var(--sage-deep)} /* DM Recall via --sage-deep alias */
html.dark .study-card--saq    { --card-accent: var(--type-saq); }
html.dark .study-card--pharma { --card-accent: var(--type-pharma); }
html.dark .study-card--axiom  { --card-accent: var(--type-axiom); }

/* Density modifier — comfortable (default) and compact. Compact body is
   collapsed by default; revealed via [data-revealed]. Refs slot inlines
   chips in compact and uses the icon-tray pattern in comfortable. */
.study-card[data-density="compact"]{
  padding:var(--study-card-padding-cmp-y) var(--study-card-padding-cmp-x);
  gap:6px;min-height:var(--study-card-min-h-cmp);
}

/* Slots */
.study-card__header{
  display:flex;align-items:center;gap:8px;
  padding-right:var(--study-card-flag-offset);
}
.study-card__glyph{
  font-size:14px;line-height:1;color:var(--card-accent);font-weight:500;
  display:inline-flex;align-items:center;justify-content:center;
  width:14px;flex:0 0 auto;
}
.study-card__stem{font-size:14px;line-height:1.4;font-weight:500}
.study-card[data-density="compact"] .study-card__stem{font-size:13px}
.study-card__body{display:flex;flex-direction:column;gap:6px;font-size:12.5px;line-height:1.6}
.study-card[data-density="compact"] .study-card__body{display:none}
.study-card[data-density="compact"][data-revealed] .study-card__body{display:flex}

/* References slot — solidity rule §21: solid 1px separator, not dashed.
   Comfortable: icon button + tray (variant B). Compact: inline chips, no icon. */
.study-card__refs{
  display:flex;align-items:center;gap:8px;
  padding-top:6px;border-top:1px solid var(--border);
  font-size:11px;flex-wrap:wrap;
}
.study-card__refs > .refs-icon{
  width:24px;height:24px;border-radius:var(--btn-radius);
  border:0.5px solid var(--border);background:transparent;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:11px;color:var(--text-muted);cursor:pointer;flex:0 0 auto;
}
.study-card__refs > .refs-icon:hover{background:var(--surface-elevated);color:var(--text)}
.study-card__refs > .refs-tray{
  display:flex;align-items:center;gap:5px;flex-wrap:wrap;
  font-size:10.5px;flex:1 1 auto;
}
.study-card[data-density="comfortable"] .study-card__refs > .refs-tray[hidden]{display:none}
.study-card[data-density="compact"]    .study-card__refs > .refs-icon{display:none}
.study-card[data-density="compact"]    .study-card__refs > .refs-tray[hidden]{display:flex}

.ref-chip{
  display:inline-flex;align-items:center;gap:4px;
  padding:3px 7px;border-radius:var(--btn-radius);
  border:0.5px solid var(--border);background:transparent;
  font-size:10.5px;color:var(--text-muted);
  text-decoration:none;cursor:pointer;
  font-family:inherit;
}
.ref-chip:hover{background:var(--surface-elevated);color:var(--text)}

/* Footer + sticky-on-overflow contract. Sticky engages only when content
   exceeds card height (opt-in via [data-overflow] data-attr set by JS). */
.study-card__footer{margin-top:auto;padding-top:8px}
.study-card__footer[data-overflow]{
  position:sticky;bottom:0;
  background:color-mix(in srgb,var(--surface) 92%,transparent);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  margin-inline:calc(-1 * var(--study-card-padding-cmf));
  margin-bottom:calc(-1 * var(--study-card-padding-cmf));
  padding:8px var(--study-card-padding-cmf) var(--study-card-padding-cmf);
  border-top:1px solid var(--border);
}

/* Marked-state hybrid — stripe shifts to grade colour, body bg gains 5%
   grade tint, footer collapses inverted-T → chip. Body / refs / stem
   never truncate per spec §8.3 solidity preservation rule. */
.study-card[data-graded]{
  border-left-color:var(--grade-color);
  background:color-mix(in srgb,var(--grade-color) var(--study-card-marked-tint),var(--surface));
}
html.dark .study-card[data-graded]{
  background:color-mix(in srgb,var(--grade-color) calc(var(--study-card-marked-tint) + 2%),var(--surface));
}
.study-card[data-graded="missed"]  {--grade-color:var(--grade-missed)}
.study-card[data-graded="honed"]   {--grade-color:var(--grade-honed)}
.study-card[data-graded="mastered"]{--grade-color:var(--grade-mastered)}

/* Solidity preservation — opacity stays 1.0 on body content even when graded.
   §8.3 + §21 — body / refs / stem / header never fade. */
.study-card .study-card__body,
.study-card .study-card__stem,
.study-card .study-card__refs,
.study-card .study-card__header{opacity:1}

/* Marked-state collapse pill — replaces inverted-T post-grade. Tap to undo. */
.study-card__chip{
  display:none;align-items:center;gap:6px;
  padding:7px 10px;border-radius:var(--btn-radius);
  border:0.5px solid var(--grade-color);
  color:var(--grade-color);
  background:color-mix(in srgb,var(--grade-color) 12%,transparent);
  cursor:pointer;font-size:12px;font-weight:500;
  width:auto;align-self:stretch;
  font-family:inherit;
}
.study-card__chip-tag{font-weight:500;text-transform:lowercase}
.study-card__chip-undo{margin-left:auto;font-size:10.5px;opacity:.65;font-weight:400}
.study-card[data-graded] .study-card__chip{display:flex}
/* Phase 5 full — collapse footer when graded (chip replaces inverted-T).
   Grade 1 deferred to tagMiss() so miss-tag overlay stays visible first. */
.study-card[data-graded] .recall-actions .post-reveal,.study-card[data-graded] .recall-actions .miss-tag-overlay{display:none}
.study-card[data-graded] .saq-card-cf-footer{display:none}

/* Sprint B PR1 (B1) — carry-over graded cards from the previous session
   stay visible but frozen on the Today list until session N+1 begins.
   pointer-events:none is load-bearing — prevents stale grade taps. */
.study-card[data-session-context="last"]{opacity:0.55;pointer-events:none}
.study-card[data-session-context="last"] .study-card__chip-tag,
.study-card[data-session-context="last"] [data-grade-chip]{pointer-events:auto;opacity:1}

/* Sprint B PR1 (B3) — top-3 MRU preset chips inside the Custom action card.
   Compact pills sit on the colored card background, adjacent to SET UP.
   Card shape stays unchanged — chips inherit the column flex flow. */
.sh-act-presets{display:flex;flex-wrap:wrap;gap:4px;justify-content:center;margin-top:4px;max-width:100%}
.sh-act-preset-chip{
  display:inline-flex;align-items:center;gap:4px;
  padding:3px 8px 3px 4px;border-radius:99px;
  background:rgba(255,255,255,.18);color:#fff;border:none;
  cursor:pointer;font-family:inherit;font-size:11px;line-height:1;font-weight:500;
  max-width:100%;
  transition:background var(--duration-sm);
}
.sh-act-preset-chip:hover{background:rgba(255,255,255,.28)}
.sh-act-preset-chip:active{background:rgba(255,255,255,.34)}
.sh-act-preset-chip:focus-visible{outline:2px solid rgba(255,255,255,.85);outline-offset:1px}
.sh-act-preset-chip__key{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:16px;height:16px;padding:0 3px;border-radius:var(--radius-tiny);
  background:rgba(255,255,255,.22);color:#fff;
  font-size:10px;font-weight:700;font-variant-numeric:tabular-nums;
}
.sh-act-preset-chip__name{
  font-weight:500;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:120px;
}

/* Sprint D D1 — quiet chip (no fill, no outline). Single biggest visual quietener.
   Was Ph6 .curriculum-chip with tinted fill/border; now text-only across today/library/focus. */
.curriculum-chip{
  display:inline-flex;align-items:center;gap:5px;
  padding:2px 4px;border-radius:0;
  border:0;background:transparent;
  font-size:10.5px;font-weight:500;color:var(--card-accent);
  cursor:pointer;text-decoration:none;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:240px;
}
.curriculum-chip:hover{color:color-mix(in srgb,var(--card-accent) 80%,var(--text))}
.curriculum-chip__icon{font-size:11px;opacity:.55}

/* Sprint D D1/D2/D3 — unified library card header row.
   [chips left] · [history dots centre] · [due + ⋯ right]. Used across Recall/SAQ/Axiom/Drug
   library cards. Replaces type-specific status rows in library mode only. */
.lib-header{display:flex;align-items:center;gap:8px;width:100%;min-height:22px}
.lib-header__chips{display:flex;align-items:center;gap:6px;min-width:0;flex:1 1 auto;overflow:hidden}
/* Sprint D card-polish — header text matches the "Overdue Nd" font (var(--font-size-2xs))
   so chip / dots-new / due all sit on the same visual weight. Topic title truncates
   to a single line with ellipsis when wider than the chip slot allows. */
.lib-header__chip{display:inline-flex;align-items:center;font-size:var(--font-size-2xs,10px);font-weight:500;color:var(--card-accent);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;max-width:100%;line-height:1.3}
.lib-header__chip + .lib-header__chip{padding-left:6px;border-left:0;position:relative;flex-shrink:0}
.lib-header__chip + .lib-header__chip::before{content:"·";color:var(--text-faint);margin-right:6px}
.lib-header__chip--btn{cursor:pointer;background:none;border:0;padding:0;font:inherit;color:inherit}
.lib-header__chip--btn:hover{color:color-mix(in srgb,var(--card-accent) 80%,var(--text))}
.lib-header__dots{display:flex;align-items:center;gap:4px;flex:0 0 auto;margin:0 4px}
.lib-header__dots--new{font-size:var(--font-size-2xs,10px);color:var(--text-faint);font-style:italic;letter-spacing:.02em}
.lib-header__dot{width:6px;height:6px;border-radius:50%;display:inline-block;flex-shrink:0;background:var(--text-faint);opacity:.55}
.lib-header__dot--mastered{background:var(--grade-mastered,#9F72F8);opacity:1}
.lib-header__dot--honed{background:var(--grade-honed,#15803D);opacity:1}
.lib-header__dot--missed{background:var(--grade-missed,#F05A50);opacity:1}
.lib-header__right{display:flex;align-items:center;gap:6px;flex:0 0 auto;margin-left:auto}
.lib-header__due{font-size:var(--font-size-2xs,10px);color:var(--text-muted);white-space:nowrap}
.lib-header__due--overdue{color:var(--grade-missed,#F05A50);font-weight:600}
.lib-header__due--today{color:var(--card-accent);font-weight:600}
.lib-header__due--new{color:var(--text-faint);font-style:italic}
.lib-header__menu{background:none;border:0;padding:2px 6px;color:var(--text-muted);cursor:pointer;font-size:14px;line-height:1;border-radius:var(--radius-tiny);transition:background .12s}
.lib-header__menu:hover{background:var(--surface-alt);color:var(--text)}

/* Sprint D card-polish — focus-mode breadcrumb inlined into the type-row (recall)
   and fc-saq-header-row (saq). Reserves space on the right for the absolute ⋯ menu
   so breadcrumb chip + menu never overlap. font-size matches "Overdue" weight. */
.fc-type-row__crumb,
.fc-saq-header-row__crumb,
.fc-pharma-meta__crumb{
  margin-left:8px;
  font-size:var(--font-size-2xs,10px);
  pointer-events:auto;
  /* leave clearance for the absolute card-options-btn (≈30px from right edge) */
  max-width:calc(100% - 140px);
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}
.fc-type-row__crumb .chip,
.fc-saq-header-row__crumb .chip,
.fc-pharma-meta__crumb .chip{
  font-size:inherit;
  padding:1px 6px;
}
/* Pharma focus meta needs flex to keep the inline crumb on the same line. */
.fc-pharma-meta{display:flex;align-items:center;gap:6px;flex-wrap:wrap}

/* Sprint D card-polish — library cards must not paint the data-graded grade-tint
   backdrop. The unified header's dot row already shows last-5 grades; the whole-card
   tint duplicates that signal AND bleeds into adjacent UI. data-graded persists from
   focus-mode rateToday() runs that share state.ratings keys with library row keys. */
.saq-card--lib[data-graded],
.recall-card--lib[data-graded],
.axiom--lib[data-graded]{
  background:var(--surface-alt2,var(--surface)) !important;
  border-left-color:var(--card-stripe,var(--border)) !important;
}
html.dark .saq-card--lib[data-graded],
html.dark .recall-card--lib[data-graded],
html.dark .axiom--lib[data-graded]{
  background:var(--surface-alt2,var(--surface)) !important;
}

/* Sprint D — Recall library tab in 'axiom' mode reuses buildRecallCard()
   but the card is conceptually an axiom — repaint to lime identity. */
.recall-card.recall-card--axiom-mode{
  background:color-mix(in srgb,var(--saltbush) var(--card-tint-light),var(--surface-alt2));
  border-left-color:var(--saltbush-deep);
  --card-accent:var(--saltbush-deep);
}
html.dark .recall-card.recall-card--axiom-mode{
  background:color-mix(in srgb,var(--saltbush) var(--card-tint-dark),var(--surface-alt2));
}

/* Sprint D D4 — library cards skip footer DOM entirely (recall-actions / saq-card-cf-footer
   / study-card__chip). The CSS hides for older mounts that haven't re-rendered yet. */
.recall-card--lib .recall-actions,
.recall-card--lib .study-card__chip,
.recall-card--lib .recall-status-row,
.saq-card--lib .saq-card-cf-footer,
.saq-card--lib .study-card__chip,
.saq-card--lib .saq-answer-btn,
.saq-card--lib .ref-chip--related,
.axiom--lib .study-card__chip,
.axiom--lib .axiom-actions{display:none !important}

/* Ph6 — References bottom sheet */
.refs-sheet-overlay{
  position:fixed;inset:0;background:var(--backdrop-sheet);
  z-index:var(--z-refs-sheet);display:flex;flex-direction:column;
  justify-content:flex-end;align-items:center;
  backdrop-filter:blur(2px);animation:backdropIn .15s ease;
}
.refs-sheet{
  width:100%;max-width:560px;background:var(--surface-elevated);
  border-radius:var(--radius-lg) var(--radius-lg) 0 0;
  box-shadow:var(--shadow-lg);max-height:94dvh;min-height:70dvh;overflow-y:auto;
  overscroll-behavior:contain;
  padding-bottom:max(24px,env(safe-area-inset-bottom,24px));
  animation:sheetUp var(--duration-md) cubic-bezier(.32,.72,0,1);
}
@media(min-width:700px){.refs-sheet{padding-bottom:24px}}
.refs-sheet__handle{width:36px;height:4px;background:var(--border-strong);border-radius:var(--radius-2xs);margin:10px auto 0;opacity:.6;touch-action:none}
.refs-sheet__ctx{display:flex;align-items:center;gap:8px;padding:10px 14px 9px;border-bottom:1px solid var(--border)}
.refs-sheet__ctx-glyph{font-size:12px;color:var(--text-faint);flex:0 0 auto}
.refs-sheet__ctx-title{font-size:12.5px;color:var(--text-muted);font-weight:500;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.refs-sheet__close{background:none;border:none;cursor:pointer;color:var(--text-muted);font-size:18px;width:28px;height:28px;border-radius:5px;display:flex;align-items:center;justify-content:center;flex:0 0 auto;font-family:inherit;line-height:1}
.refs-sheet__close:hover{background:var(--surface);color:var(--text)}
.ref-row{display:flex;align-items:center;gap:8px;padding:8px 14px;min-height:38px;border-bottom:0.5px solid var(--border);cursor:pointer;color:var(--text);transition:background .1s;background:transparent;border:none;font-family:inherit;font-size:inherit;width:100%;text-align:left}
.ref-row:hover{background:color-mix(in srgb,var(--accent) 4%,var(--surface-elevated))}
.ref-row:last-child{border-bottom:none}
.ref-row__glyph{font-size:11px;flex:0 0 13px;text-align:center;line-height:1}
.ref-row__glyph--saq{color:var(--type-saq)}.ref-row__glyph--axiom{color:var(--type-axiom)}.ref-row__glyph--recall{color:var(--type-recall)}.ref-row__glyph--pharma{color:var(--type-pharma)}
.ref-row__meta{display:inline-flex;align-items:center;justify-content:center;width:100px;flex:0 0 100px;padding:2px 5px;border-radius:var(--radius-tiny);background:var(--surface);border:0.5px solid var(--border);font-size:9.5px;color:var(--text-muted);font-variant-numeric:tabular-nums;white-space:nowrap;line-height:1.3}
.ref-row__title-wrap{flex:1;display:flex;align-items:center;gap:5px;min-width:0}
.ref-row__title{font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}
.ref-row__title--saq{color:var(--type-saq)}.ref-row__title--axiom{color:var(--type-axiom)}.ref-row__title--recall{color:var(--type-recall)}.ref-row__title--pharma{color:var(--type-pharma);font-weight:400}
.ref-row__pearl{font-size:10px;color:var(--pearl,#9A7200);flex:0 0 auto}
.ref-row__arrow{font-size:11px;color:var(--border-strong);flex:0 0 auto}
.ref-drug-list{display:flex;flex-direction:column;padding:0 14px 4px 35px}
.ref-drug-list[hidden]{display:none}
.ref-drug-item{display:flex;align-items:center;gap:8px;padding:6px 0;border-bottom:0.5px solid var(--border);cursor:pointer;font-size:12px;color:var(--type-pharma);transition:color .1s;background:none;border:none;font-family:inherit;width:100%;text-align:left}
.ref-drug-item:last-child{border-bottom:none}
.ref-drug-item:hover{color:color-mix(in srgb,var(--type-pharma) 70%,var(--text))}
.ref-drug-item__glyph{font-size:11px;color:var(--type-pharma);opacity:.5}
.ref-show-more{display:flex;align-items:center;padding:7px 14px 7px 35px;font-size:11.5px;color:var(--accent);background:none;border:none;border-bottom:0.5px solid var(--border);font-family:inherit;cursor:pointer;width:100%;text-align:left}
.ref-show-more:hover{text-decoration:underline}
.ref-source-div{height:1px;background:var(--border)}
.ref-source{display:flex;align-items:center;gap:10px;padding:9px 14px;border:none;border-bottom:0.5px solid var(--border);text-decoration:none;color:var(--text);cursor:pointer;transition:background .1s;background:transparent;font-family:inherit;font-size:inherit;text-align:left;appearance:none;-webkit-appearance:none}
.ref-source:last-child{border-bottom:none}
.ref-source:hover{background:color-mix(in srgb,var(--accent) 4%,var(--surface-elevated))}
.ref-source--static{cursor:default}.ref-source--static:hover{background:transparent}
.ref-source__icon{width:15px;height:15px;flex:0 0 15px;color:var(--text-faint)}
.ref-source__icon svg{width:15px;height:15px;display:block;stroke:currentColor;stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round}
.ref-source__label{font-size:13px;flex:1}
.ref-source__sub{font-size:11px;color:var(--text-faint)}
.ref-source__arrow{font-size:11px;color:var(--border-strong)}
.ref-source-entry{display:block}
.ref-source-entry .ref-source{border-bottom:none}
.ref-source__quote{font-size:11px;color:var(--text-faint);font-style:italic;padding:2px 14px 9px 39px;border-bottom:.5px solid var(--border);margin:0}
.ref-source-entry:last-child .ref-source__quote{border-bottom:none}
.ref-browse-chapters{display:flex;align-items:center;padding:6px 14px 9px 39px;font-size:11.5px;color:var(--accent);background:none;border:none;font-family:inherit;cursor:pointer;width:100%;text-align:left}
.ref-browse-chapters:hover{text-decoration:underline}
.book-chapters-list{overflow-y:auto;-webkit-overflow-scrolling:touch}
.refs-skel-row{display:flex;align-items:center;gap:8px;padding:9px 14px;border-bottom:0.5px solid var(--border)}
.refs-skel__icon{width:13px;height:13px;border-radius:3px;flex:0 0 13px}
.refs-skel__chip{height:18px;width:100px;border-radius:var(--radius-tiny);flex:0 0 100px}
.refs-skel__bar{height:10px;border-radius:var(--radius-tiny)}
.refs-skel__icon,.refs-skel__chip,.refs-skel__bar{background:var(--border);animation:skelPulse 1.3s ease-in-out infinite}
@keyframes skelPulse{0%,100%{opacity:.4}50%{opacity:.85}}
/* F1 — Refs sheet breadcrumb (Section › Chapter › Topic) */
.refs-sheet__breadcrumb{display:flex;align-items:center;gap:2px;flex-wrap:nowrap;overflow:hidden;padding:5px 14px 6px;border-bottom:1px solid var(--border)}
.refs-breadcrumb__sep{font-size:10px;color:var(--text-faint);padding:0 2px;user-select:none;flex:0 0 auto}
.refs-breadcrumb__chip{font-size:10.5px;color:var(--text-muted);background:none;border:none;padding:2px 4px;border-radius:var(--radius-tiny);cursor:pointer;font-family:inherit;line-height:1.5;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.refs-breadcrumb__chip:hover{background:var(--surface);color:var(--accent)}
/* F2/F3 — Refs sheet section label (Progression / See also / Related) */
.refs-section-hdr{font-size:9.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--text-faint);padding:8px 14px 3px;border-top:0.5px solid var(--border)}
.refs-section-hdr:first-child{border-top:none}
.refs-related-loading{padding:12px 14px;font-size:11px;color:var(--text-faint)}
/* Track 2 — Provenance badges (right-aligned, per source row) */
.prov-badge{display:inline-flex;align-items:center;gap:3px;font-size:9px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;padding:2px 7px;border-radius:var(--radius-pill);white-space:nowrap;flex:0 0 auto;margin-left:auto}
.prov-badge--written{background:var(--accent-soft);color:var(--accent);border:1px solid color-mix(in srgb,var(--accent) 34%,transparent)}
.prov-badge--awaits{background:var(--honey-fill);color:var(--honey-deep);border:1px solid color-mix(in srgb,var(--honey-deep) 34%,transparent)}
.prov-badge--ref{background:var(--surface-elevated);color:var(--text-muted);border:1px solid var(--border-strong)}
.prov-badge--topical{background:var(--surface-elevated);color:var(--text-muted);border:1px solid var(--border-strong)}
/* Awaits-validation stacked badge + caption (badge on top, "suggested source" caption below) */
.prov-stack{display:flex;flex-direction:column;align-items:flex-end;gap:2px;margin-left:auto;flex:0 0 auto}
.prov-stack .prov-badge{margin-left:0}
.prov-cap{font-size:10px;color:var(--text-faint);white-space:nowrap}
/* Partial-verdict caveat line (honey-tinted, under written-from rows) */
.ref-prov-caveat{display:flex;gap:5px;align-items:flex-start;font-size:10.5px;color:var(--honey-deep);padding:0 14px 8px 39px;margin:0;border-bottom:0.5px solid var(--border)}
.ref-prov-caveat svg{width:12px;height:12px;flex:0 0 12px;margin-top:1px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}
.ref-source-entry:last-child .ref-prov-caveat{border-bottom:none}
/* Hairline group-gap between card-owned sources and node-inherited topical sources */
.ref-group-gap{height:7px;border-top:0.5px solid var(--border);background:var(--surface-elevated)}
/* Track 2 — Why-linked chip on related-card rows (right-aligned, before arrow) */
.ref-why{display:inline-flex;align-items:center;gap:3px;font-size:9px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;padding:2px 7px;border-radius:var(--radius-pill);white-space:nowrap;flex:0 0 auto;margin-left:auto}
.ref-why--builds{background:var(--accent-soft);color:var(--accent);border:1px solid color-mix(in srgb,var(--accent) 34%,transparent)}
.ref-why--author{background:var(--violet-fill);color:var(--violet-deep);border:1px solid color-mix(in srgb,var(--violet-deep) 34%,transparent)}
.ref-why--topic{background:var(--surface-elevated);color:var(--text-muted);border:1px solid var(--border-strong);font-variant-numeric:tabular-nums}
.ref-why--similar{background:var(--surface-elevated);color:var(--text-muted);border:1px solid var(--border-strong)}
.ref-conf-dots{display:inline-flex;gap:2px;margin-left:2px}
.ref-conf-dot{width:4px;height:4px;border-radius:50%;background:currentColor;opacity:.3}
.ref-conf-dot.on{opacity:1}
/* F7 — Drug card section dividers */
.drug-section{padding:10px 0 6px}
.drug-section+.drug-section{border-top:0.5px solid var(--border)}
.drug-section__label{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--text-faint);margin:0 0 5px}

/* Active-card / keyboard-focused state — single rule for all types.
   Stripe widens by 2px and bg gains 8% type tint; box-shadow lifts. */
.study-card.is-keyboard-focused{
  transform:translateY(-1px);
  border-left-width:calc(var(--card-stripe-width) + 2px);
  padding-left:calc(var(--study-card-padding-cmf) - 2px);
  background:color-mix(in srgb,var(--card-accent) 8%,var(--surface));
  box-shadow:0 4px 14px -4px color-mix(in srgb,var(--card-accent) 40%,transparent);
}
@media(prefers-reduced-motion:reduce){
  .study-card.is-keyboard-focused{transform:none}
}

/* =====================================================
   TRUST PAIR — verified pip + flag (spec §7)
   .card-flag-btn is the new canonical name; legacy .recall-flag-btn
   styling preserved until JS render swap in phase 2.
   ===================================================== */

.card-verified-pip{
  position:absolute;top:8px;right:38px;        /* sits 30px left of flag */
  width:22px;height:22px;border-radius:50%;
  background:var(--grade-honed);color:#fff;
  border:0;cursor:default;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:11px;font-weight:500;line-height:1;
  z-index:2;
}
.card-verified-pip[hidden]{display:none}
html.dark .card-verified-pip{background:var(--grade-honed)}

/* Flag-count badge — appears when reports >= 2. data-count="0" or "1" stays unbadged. */
.card-flag-btn[data-count]:not([data-count="0"]):not([data-count="1"])::after{
  content:attr(data-count);
  position:absolute;top:-4px;right:-4px;
  min-width:14px;height:14px;
  background:var(--grade-missed);color:#fff;
  border:1.5px solid var(--surface);border-radius:var(--radius-pill);
  font-size:9px;font-weight:500;line-height:1;
  display:flex;align-items:center;justify-content:center;
  padding:0 3px;
}


/* Summary header — sister component for ribbon mount points */
.study-ribbon-summary{
  display:flex;justify-content:space-between;align-items:center;
  padding:9px 12px;border-radius:var(--radius-sm);font-size:11px;
  background:color-mix(in srgb,var(--text) 4%,var(--surface));
  border:0.5px solid var(--border);
  margin-bottom:8px;
}
.study-ribbon-summary__stats{display:flex;gap:10px;align-items:center;font-variant-numeric:tabular-nums}
.study-ribbon-summary__stat{display:flex;align-items:center;gap:4px}
.study-ribbon-summary__pip{width:8px;height:8px;border-radius:50%;display:inline-block}
.study-ribbon-summary__pip[data-grade="missed"]  {background:var(--grade-missed)}
.study-ribbon-summary__pip[data-grade="honed"]   {background:var(--grade-honed)}
.study-ribbon-summary__pip[data-grade="mastered"]{background:var(--grade-mastered)}
.study-ribbon-summary__coverage{opacity:.55;font-size:10.5px}

/* ribbon-card styles moved to pwa/ribbon/ribbon.css */

/* Haul stats panel */
.haul-stats{
  display:grid;grid-template-columns:1fr 1fr;gap:8px;
  margin-top:12px;
}
.haul-stat-tile{
  background:color-mix(in srgb,var(--text) 3%,var(--surface));
  border:0.5px solid var(--border);border-radius:var(--radius-sm);
  padding:10px 12px;
}
.haul-stat-tile__hdr{
  display:flex;align-items:center;gap:5px;margin-bottom:5px;
}
.haul-stat-tile__hdr svg{width:12px;height:12px;color:var(--text-faint);stroke-width:2;flex-shrink:0}
.haul-stat-tile__label{
  font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;
  color:var(--text-faint);
}
.haul-stat-tile__value{
  font-size:22px;font-weight:700;font-variant-numeric:tabular-nums;
  font-family:var(--font-mono,ui-monospace,monospace);
  color:var(--text);line-height:1;
}
.haul-stat-tile__sub{
  font-size:10px;color:var(--text-muted);margin-top:3px;
}

/* Haul curriculum heatmap */
.haul-heatmap{
  display:grid;grid-template-columns:repeat(17,1fr);gap:3px;
  margin-top:12px;
}
.haul-heatmap__cell{
  aspect-ratio:1;border-radius:3px;
  background:var(--border);
  display:flex;align-items:center;justify-content:center;
  font-size:8px;font-weight:700;color:var(--text-faint);
}
.haul-heatmap__cell--active{
  background:color-mix(in srgb,var(--sage) 30%,var(--surface));
  color:var(--sage-deep);
}
@media (prefers-reduced-motion:no-preference){
  .haul-heatmap__cell--active{
    animation:heatmap-pulse 2s ease-in-out infinite;
  }
  @keyframes heatmap-pulse{
    0%,100%{opacity:1}
    50%{opacity:0.6}
  }
}

/* ── Haul modal (Sprint G) ─────────────────────────────────────────────── */
@keyframes modalIn{from{opacity:0;transform:scale(.96) translateY(6px)}to{opacity:1;transform:none}}
.haul-backdrop{
  position:fixed;inset:0;background:rgba(0,0,0,.45);backdrop-filter:blur(3px);
  z-index:400;display:flex;align-items:center;justify-content:center;padding:16px;
}
.haul-modal{
  background:var(--surface);border-radius:var(--radius-lg);
  width:min(720px,100%);max-height:min(88dvh,860px);
  display:flex;flex-direction:column;overflow:hidden;
  box-shadow:0 8px 40px rgba(0,0,0,.18),0 2px 8px rgba(0,0,0,.1);
  padding-bottom:env(safe-area-inset-bottom);
}
@media(prefers-reduced-motion:no-preference){
  .haul-modal{animation:modalIn .22s cubic-bezier(.32,1,.54,1) both}
}
/* Hero zone: title(left) | XP(centre) | rank+close(right) */
.haul-hero{
  display:grid;grid-template-columns:1fr auto 1fr;
  align-items:center;gap:8px;
  padding:12px 14px 10px;
  border-bottom:1px solid var(--border);flex-shrink:0;
}
.haul-hero-left{display:flex;align-items:center;gap:8px;min-width:0}
.haul-hero-text{min-width:0}
.haul-hdr-icon{
  width:28px;height:28px;border-radius:var(--radius-sm);
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
}
.haul-hdr-icon svg{width:15px;height:15px;stroke-width:2}
.haul-hdr-icon--default{background:rgba(21,128,61,.1);color:var(--mint)}
.haul-hdr-icon--missed{background:rgba(240,90,80,.12);color:var(--coral-vivid)}
.haul-hdr-icon--rankup{background:rgba(201,160,48,.15);color:#c89a30}
.haul-hdr-icon--badge{background:rgba(139,92,246,.12);color:var(--violet)}
.haul-hdr-title{font-size:14px;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.haul-hdr-expl{font-size:11px;color:var(--text-muted);margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.haul-hero-xp{
  display:flex;align-items:flex-end;justify-content:center;gap:3px;
  padding:4px 8px;
}
.haul-xp-number{
  font-size:44px;font-weight:700;font-family:var(--font-mono,monospace);
  color:var(--text);font-variant-numeric:tabular-nums;line-height:1;letter-spacing:-.02em;
}
.haul-xp-unit{
  font-size:14px;font-weight:600;color:var(--text-muted);margin-bottom:5px;
}
.haul-hero-right{display:flex;align-items:center;justify-content:flex-end;gap:8px}
.haul-hero-rank-stack{text-align:right;min-width:0}
.haul-rank-badge{
  display:inline-flex;align-items:center;gap:5px;
  background:var(--surface-alt);border:1px solid var(--border);
  border-radius:20px;padding:3px 10px 3px 7px;font-size:12px;font-weight:600;color:var(--text);
}
.haul-rank-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.haul-rank-to-next{font-size:11px;color:var(--text-muted);margin-top:3px}
.haul-close{
  width:28px;height:28px;border-radius:50%;background:var(--surface-alt);
  border:none;display:flex;align-items:center;justify-content:center;
  cursor:pointer;color:var(--text-muted);flex-shrink:0;
}
.haul-close svg{width:14px;height:14px;stroke-width:2}
.haul-close:hover{background:var(--border)}
/* Scrollable body */
.haul-body{
  flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:0 16px 8px;
}
.haul-body::-webkit-scrollbar{width:0}
/* Rank progress bar */
.haul-rank-bar{height:2px;background:var(--border);border-radius:1px;margin-bottom:14px;overflow:hidden}
.haul-rank-fill{height:100%;border-radius:1px;transition:width 1.1s cubic-bezier(.4,0,.2,1) .2s}
/* Grade pills */
.haul-grade-row{display:flex;gap:10px;align-items:center;justify-content:center;margin-bottom:10px;flex-wrap:wrap}
.haul-grade-pill{
  display:flex;align-items:center;gap:5px;
  font-size:13px;font-weight:600;padding:4px 10px;border-radius:20px;
}
.haul-grade-pill--missed{background:rgba(240,90,80,.13);color:var(--coral-vivid)}
.haul-grade-pill--honed{background:rgba(21,117,112,.13);color:var(--mint)}
.haul-grade-pill--mastered{background:rgba(139,92,246,.13);color:var(--violet)}
/* 4px stacked health bar */
.haul-health-bar{
  height:4px;border-radius:var(--radius-2xs);display:flex;overflow:hidden;margin-bottom:14px;
}
.haul-health-seg--missed{background:var(--coral-vivid)}
.haul-health-seg--honed{background:var(--mint)}
.haul-health-seg--mastered{background:var(--violet)}
/* Rank-up banner */
.haul-rankup{
  display:flex;align-items:center;gap:10px;
  background:rgba(201,160,48,.08);border:1px solid rgba(201,160,48,.25);
  border-radius:var(--radius-sm);padding:10px 13px;margin-bottom:14px;
}
.haul-rankup svg{width:16px;height:16px;color:#c89a30;flex-shrink:0}
.haul-rankup-text{font-size:13px;font-weight:600;color:#c89a30}
.haul-rankup-sub{font-size:12px;color:var(--text-muted)}
/* Stat tile modifiers */
.haul-stat-tile.good .haul-stat-tile__value{color:var(--mint)}
.haul-stat-tile.warn .haul-stat-tile__value{color:var(--fc-badge-hazy,#b45309)}
.haul-stat-tile.muted .haul-stat-tile__value{color:var(--text-muted)}
/* Heatmap wrapper */
.haul-heatmap-wrap{margin-bottom:16px}
/* Notable events */
.haul-events{margin-bottom:14px}
.haul-event-item{
  display:flex;align-items:center;gap:9px;
  padding:7px 0;border-bottom:1px solid var(--border);
}
.haul-event-item:last-child{border-bottom:none}
.haul-event-icon{
  width:28px;height:28px;border-radius:7px;
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
}
.haul-event-icon svg{width:14px;height:14px;stroke-width:1.75}
.haul-event-icon--badge{background:rgba(139,92,246,.12);color:var(--violet)}
.haul-event-icon--streak{background:rgba(245,158,11,.12);color:#d97706}
.haul-event-icon--nemesis{background:rgba(240,90,80,.12);color:var(--coral-vivid)}
.haul-event-icon--pearl{background:rgba(21,117,112,.1);color:var(--mint)}
.haul-event-body{min-width:0}
.haul-event-title{font-size:13px;color:var(--text);font-weight:500}
.haul-event-sub{font-size:11px;color:var(--text-muted)}
/* Miss nudge */
.haul-miss{
  background:rgba(240,90,80,.08);border:1px solid rgba(240,90,80,.15);
  border-radius:var(--radius-sm);padding:10px 12px;margin-bottom:14px;
}
.haul-miss-hdr{
  display:flex;align-items:center;gap:6px;
  font-size:12px;font-weight:600;color:var(--coral-vivid);margin-bottom:3px;
}
.haul-miss-body{font-size:12px;color:var(--text-muted);line-height:1.45}
/* Ribbon collapse */
/* Breakdown — always visible */
.haul-ribbon-wrap{margin:0 -16px;border-top:1px solid var(--border)}
.haul-ribbon-hdr{
  padding:7px 16px 5px;font-size:11px;font-weight:600;
  color:var(--text-muted);letter-spacing:.04em;text-transform:uppercase;
}
.haul-ribbon-list{display:block;padding:0 0 4px}
/* Haul ribbon card rows (modal-scoped, prefix rc-) */
.haul-ribbon-card{
  display:flex;align-items:center;
  border-bottom:1px solid var(--border);background:var(--surface);
  cursor:default;
}
.haul-ribbon-card:last-child{border-bottom:none}
.rc-stripe{width:3px;flex-shrink:0;align-self:stretch}
.rc-stripe--missed{background:var(--coral-vivid)}
.rc-stripe--honed{background:var(--mint)}
.rc-stripe--mastered{background:var(--violet)}
.rc-glyph{
  width:32px;height:32px;border-radius:var(--radius-sm);
  margin:10px 8px 10px 10px;
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
}
.rc-glyph svg{width:16px;height:16px;stroke-width:1.75}
.rc-glyph--recall{background:rgba(45,107,149,.12);color:var(--type-recall,#2D6B95)}
.rc-glyph--saq{background:rgba(168,40,64,.1);color:var(--type-saq,#A82840)}
.rc-glyph--pharma{background:rgba(94,62,158,.1);color:var(--type-pharma,#5E3E9E)}
.rc-glyph--axiom{background:rgba(84,100,9,.1);color:var(--type-axiom,#546409)}
.rc-body{flex:1;min-width:0;padding:10px 0}
.rc-stem{
  font-size:13px;color:var(--text);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:2px;
}
.rc-meta{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text-muted)}
.rc-meta-chip{
  background:var(--surface-alt);border:1px solid var(--border);
  border-radius:var(--radius-tiny);padding:1px 5px;font-size:10px;font-weight:600;color:var(--text-muted);
}
.rc-right{display:flex;align-items:center;gap:6px;padding:0 10px 0 6px;flex-shrink:0}
.rc-grade-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.rc-grade-dot--missed{background:var(--coral-vivid)}
.rc-grade-dot--honed{background:var(--mint)}
.rc-grade-dot--mastered{background:var(--violet)}
/* Per-ribbon next-due label — filled asynchronously after session-end save */
.haul-ribbon-due{font-size:var(--font-size-xs,11px);color:var(--text-faint);margin-top:2px;line-height:1.3}
/* Footer */
.haul-footer{
  flex-shrink:0;
  padding:12px 16px calc(12px + env(safe-area-inset-bottom));
  border-top:1px solid var(--border);background:var(--surface);
  display:flex;flex-direction:column;gap:8px;
}
.haul-footer-row{display:flex;gap:8px}
.haul-cta{
  flex:1;padding:12px 14px;border-radius:var(--radius-sm);border:none;
  font-family:var(--font-sans);font-size:14px;font-weight:700;cursor:pointer;
  display:flex;align-items:center;justify-content:center;gap:8px;
  transition:opacity .1s;color:#fff;
}
.haul-cta:active{opacity:.8}
/* Coral — Drill misses */
.haul-cta--drill{background:var(--grade-missed)}
.haul-cta--drill:hover{background:color-mix(in srgb,var(--grade-missed) 88%,#000)}
/* Sky — Review */
.haul-cta--review{background:var(--sky)}
.haul-cta--review:hover{background:color-mix(in srgb,var(--sky) 88%,#000)}
/* Honed green — Continue */
.haul-cta--continue{background:var(--grade-honed)}
.haul-cta--continue:hover{background:color-mix(in srgb,var(--grade-honed) 88%,#000)}
/* Neutral secondary (exam recover etc) */
.haul-cta--secondary{
  background:var(--surface-alt);border:1px solid var(--border);color:var(--text);
}
.haul-cta-left{display:flex;flex-direction:column;gap:1px}
.haul-cta-sub{font-size:11px;font-weight:400;opacity:.75;margin-top:1px}
/* XP rank row in Lore tab */
.lore-rank-row{
  display:flex;align-items:center;gap:10px;
  padding:10px 12px;margin-bottom:14px;
  background:var(--surface-alt);border:1px solid var(--border);
  border-radius:var(--radius-sm);
}
.lore-rank-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.lore-rank-info{flex:1;min-width:0}
.lore-rank-label{font-size:14px;font-weight:600;color:var(--text)}
.lore-rank-xp{font-size:12px;color:var(--text-muted);margin-top:1px}
.lore-rank-bar{height:3px;background:var(--border);border-radius:var(--radius-2xs);margin-top:6px;overflow:hidden}
.lore-rank-fill{height:100%;border-radius:var(--radius-2xs)}

/* --- Recall cards ---
   Today-fix #8 — card type identity carried by left-border + tinted
   bg. Type pills dropped from the status row; the card's own visual
   treatment is the type marker. Sage for Recall (WS4: 4px unified stripe).
   Today-fix v2 (revert) — back to CSS Grid with align-items:start. */
.recall-grid{margin:11px 0}
.recall-group{margin-bottom:14px}
.recall-group:last-child{margin-bottom:0}
/* patch-032 round 5 — .recall-group-cards + .recall-col layout retired.
   The recall-group cards container now uses col-stack(3) (the .recall-group-cards
   class is preserved on the wrapper as an extraClass for forward-compat). */

/* WS4: .recall-card composes .card + [data-card-type="recall"]. The base
   visual (bg, border, stripe, padding, radius, transition) comes from .card.
   Only recall-specific layout tweaks live here. */
.recall-card{
  position:relative;
  background:color-mix(in srgb,var(--sky) var(--card-tint-light),var(--surface-alt2)); /* WS11: --sage→--sky (Recall LM identity) */
  border:1px solid var(--border);
  /* Card-redesign IMPROVE: deeper stripe for visibility on cream. */
  border-left:var(--card-stripe-width) solid var(--sky-deep);
  border-radius:var(--radius);
  padding:14px;display:flex;flex-direction:column;gap:9px;
  transition:background var(--duration-sm) var(--ease-out),border-color var(--duration-sm) var(--ease-out),box-shadow var(--duration-sm) var(--ease-out),transform var(--duration-sm) var(--ease-out);
}
/* Card-redesign IMPROVE: soften from --card-shadow-hover (--shadow-2) to --shadow-1
   so hover lift feels lighter on the now-restrained card surface. */
.recall-card:hover{box-shadow:var(--shadow-1)}

/* patch-007 — Pharmacopia variant of recall-card. Reuses the same DOM
   pattern (recall-card.pharma-card) so all keyboard, swipe, and grading
   handlers apply unchanged; only the accent shifts to violet.
   WS4: stripe unified to 4px (--card-stripe-width).
   Accessibility — dark-mode contrast ratios on #131F24 surface:
     · meta (#CECBF6) → 11.4 : 1 · WCAG AAA
     · body (--text)  → 13.4 : 1 · WCAG AAA
     · accent border  → 9.7 : 1 · WCAG AAA */
.pharma-card{
  background:color-mix(in srgb,var(--violet) 8%,var(--surface-alt2));
  /* Card-redesign IMPROVE: deeper stripe. */
  border-left:var(--card-stripe-width) solid var(--violet-deep);
}
/* patch-032 round 5 — .pharma-grid layout rules retired. The pharmacopia
   section now uses the col-stack(3) primitive (defined later in this
   file). The .pharma-grid class is preserved on the wrapper as an
   extraClass so card-styling rules below (.pharma-card, etc.) still
   target the right scope. */
.pharma-card .recall-prompt{color:var(--text)}
.pharma-card .recall-tag,
.pharma-card .pharma-meta{color:var(--violet-deep);font-weight:500}
.pharma-card .pharma-lvl{font-size:9.5px;font-weight:500;padding:1px 6px;border-radius:var(--btn-radius);letter-spacing:0.02em}
.pharma-card .pharma-lvl--l1{background:var(--violet);color:var(--violet-soft,#26215C)}
.pharma-card .pharma-lvl--l2{background:transparent;color:var(--violet-deep);border:0.5px solid var(--violet)}
.pharma-card .pharma-lvl--l3{background:transparent;color:var(--violet-deep);border:0.5px dotted var(--violet)}
/* Action buttons inherit recall-actions but tint the borders + hover violet
   so the affordance reads as part of the same family. */
.pharma-card .recall-actions button{border-color:color-mix(in srgb,var(--violet) 40%,var(--border));color:var(--text)}
.pharma-card .recall-actions button:hover{border-color:var(--violet);background:color-mix(in srgb,var(--violet) 8%,transparent)}
.pharma-grid:empty{display:none}

/* ── Pharmacopia Library tab (patch-016) ───────────────────────────────── */
/* Scope + filter toolbar */
.pharma-toolbar{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:12px;align-items:center}
.pharma-scope-chip,.pharma-filter-chip{
  display:inline-flex;align-items:center;gap:5px;
  padding:10px 14px;min-height:44px;border-radius:var(--radius-sm);font-size:var(--font-size-md);font-weight:600;
  border:1.5px solid var(--border);background:var(--surface);color:var(--text-muted);
  cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);white-space:nowrap;
}
.pharma-scope-chip.active,.pharma-filter-chip.active{
  background:color-mix(in srgb,var(--violet) 12%,var(--surface));
  border-color:var(--violet);color:var(--violet-deep);
}
.pharma-scope-chip:hover,.pharma-filter-chip:hover{border-color:var(--violet);color:var(--text)}
.pharma-session-btn{
  /* margin-left:auto removed — now in dedicated top row */
  display:inline-flex;align-items:center;gap:6px;
  padding:10px 16px;border-radius:var(--radius-md);font-size:var(--font-size-md);font-weight:700;
  border:none;background:var(--violet);color:var(--text-on-pharma);
  cursor:pointer;transition:background .1s,color .1s,border-color .1s,box-shadow .1s,transform .1s,opacity .1s;
  box-shadow:0 2px 0 var(--violet-deep);
}
.pharma-session-btn:hover{transform:translateY(-1px);box-shadow:0 3px 0 var(--violet-deep)}
.pharma-session-btn:active{transform:translateY(1px);box-shadow:none}
.pharma-session-btn svg{width:13px;height:13px}
/* R-024 — on very narrow phones (≤480px) dial scope chips back to 40px
   (still ≥ WCAG 2.5.8 AA 24px floor) so Row 1 reads quieter. */
@media(max-width:480px){
  .pharma-scope-chip,.pharma-filter-chip{min-height:40px;padding:8px 12px}
}
/* patch-032 round 5 — .pharma-lib-list flex layout retired. Pharma library
   uses col-stack(3) (defined later in this file). The .pharma-lib-list
   class is preserved on the wrapper as an extraClass for any styling
   that scopes to it (none currently — kept for forward-compat). */

/* ── Drug entity card ───────────────────────────────────────────────────── */
.pharma-drug-card{
  background:var(--surface-alt2);border:1px solid var(--border);border-radius:var(--radius);
  border-left:3px solid var(--violet);overflow:hidden;
  transition:box-shadow var(--duration-sm);
}
.pharma-drug-card:hover{box-shadow:var(--shadow-sm)}

/* Header = name-row (left, grows) + header-right (dots + chev, never wraps) */
.pharma-drug-header{
  display:flex;align-items:flex-start;gap:8px;padding:11px 12px;cursor:pointer;user-select:none;
}
/* Name column: header line (level · name) → taxonomy sub-line */
.pharma-drug-name-row{
  display:flex;flex-direction:column;gap:3px;flex:1;min-width:0;overflow:hidden;
}
/* Header line — level badge + drug name on ONE row (kicker style). */
.pharma-drug-name-line{
  display:flex;align-items:center;gap:6px;min-width:0;overflow:hidden;
}
.pharma-drug-name-sep{color:var(--text-faint);flex-shrink:0;font-size:var(--font-size-md)}
.pharma-drug-name{font-size:var(--font-size-lg);font-weight:500;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.pharma-drug-taxonomy{font-size:var(--font-size-xs);color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Right cluster: dots + chev — flex-shrink:0 so it never collapses or wraps */
.pharma-drug-header-right{display:flex;align-items:center;gap:6px;flex-shrink:0;padding-top:1px}

/* Level badge */
.pharma-drug-level{font-size:9.5px;font-weight:600;padding:2px 7px;border-radius:var(--btn-radius);letter-spacing:0.02em;white-space:nowrap;flex-shrink:0}
.pharma-drug-level.l1{background:var(--violet);color:var(--violet-soft)}
.pharma-drug-level.l2{background:transparent;color:var(--violet-deep);border:1px solid var(--violet)}
.pharma-drug-level.l3{background:transparent;color:var(--violet-deep);border:1px dotted var(--violet)}
.pharma-drug-level.extra{background:transparent;color:var(--text-faint);border:1px solid var(--border)}

/* FSRS field-dot row */
.pharma-field-dots{display:flex;gap:4px;align-items:center}
.pharma-fdot{
  width:8px;height:8px;border-radius:50%;border:1.5px solid var(--border);
  transition:background .15s;flex-shrink:0;
}
.pharma-fdot.state-new{background:transparent}
.pharma-fdot.state-learning{background:var(--amber)}
.pharma-fdot.state-review{background:var(--green)}
.pharma-fdot.state-due{background:var(--red)}
.pharma-fdot.state-overdue{background:var(--red);box-shadow:0 0 0 2px color-mix(in srgb,var(--red) 25%,transparent)}

/* Expand chevron */
.pharma-drug-chev{width:15px;height:15px;color:var(--text-faint);transition:transform var(--duration-md);flex-shrink:0}
.pharma-drug-card.expanded .pharma-drug-chev{transform:rotate(180deg)}

/* ── Expanded detail panel ──────────────────────────────────────────────── */
.pharma-drug-detail{
  display:none;border-top:1px solid var(--border);padding:10px 12px 12px;
  animation:fadeIn .15s;
}
.pharma-drug-card.expanded .pharma-drug-detail{display:block}
.pharma-field-list{display:flex;flex-direction:column;gap:4px;margin-bottom:10px}

/* Field row — clickable; collapses/expands inline text */
.pharma-field-row{
  display:flex;flex-direction:column;border-radius:var(--radius-sm);overflow:hidden;
  background:var(--surface);border:1px solid var(--border);
  cursor:pointer;transition:border-color var(--duration-sm);
}
.pharma-field-row:hover{border-color:var(--violet)}
.pharma-field-row.field-open{border-color:var(--violet)}
.pharma-field-row-top{
  display:flex;align-items:center;gap:10px;padding:7px 10px;
}
.pharma-field-label{font-size:var(--font-size-md);font-weight:500;color:var(--text);flex:1}
.pharma-field-fsrs{display:flex;align-items:center;gap:6px}
.pharma-field-state{font-size:var(--font-size-xs);font-weight:600;text-transform:uppercase;letter-spacing:0.04em;padding:2px 7px;border-radius:var(--radius-tiny)}
.pharma-field-state.new{display:none}
.pharma-field-state.learning{color:var(--honey-deep);background:var(--amber-bg)}
.pharma-field-state.review{color:var(--sage-deep);background:var(--green-bg)}
.pharma-field-state.due{color:var(--coral-deep);background:var(--red-bg)}
.pharma-field-stability{font-size:var(--font-size-2xs);color:var(--text-faint);font-variant-numeric:tabular-nums}
/* Small chevron on the field row to signal tap-to-expand */
.pharma-field-chev{width:13px;height:13px;color:var(--text-faint);transition:transform .15s;flex-shrink:0}
.pharma-field-row.field-open .pharma-field-chev{transform:rotate(180deg)}

/* Inline text panel revealed on tap */
.pharma-field-text{
  padding:8px 10px 10px;border-top:1px solid var(--border);
  font-size:var(--font-size-md);line-height:1.6;color:var(--text);
  animation:fadeIn var(--duration-sm);
}
.pharma-field-text--loading{color:var(--text-faint);font-style:italic;font-size:var(--font-size-md)}

/* ── Card actions footer ────────────────────────────────────────────────── */
.pharma-drug-actions{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding-top:8px;border-top:1px solid var(--border);
}
.pharma-drug-source-link{font-size:var(--font-size-sm);color:var(--violet-deep);text-decoration:none;font-weight:500}
.pharma-drug-source-link:hover{text-decoration:underline}
.pharma-drug-synced{font-size:var(--font-size-2xs);color:var(--text-faint);margin-left:auto}
/* Drill-down session button (per-drug) */
.pharma-drug-drill-btn{
  display:inline-flex;align-items:center;gap:5px;margin-left:auto;
  padding:5px 12px;border-radius:var(--radius-sm);font-size:var(--font-size-sm);font-weight:700;
  border:1.5px solid var(--violet);color:var(--violet-deep);background:transparent;
  cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.pharma-drug-drill-btn:hover{background:color-mix(in srgb,var(--violet) 10%,transparent)}

/* ── Session builder sheet ──────────────────────────────────────────────── */
.pharma-session-sheet{max-width:560px}
.pharma-session-sheet .sheet-head{margin-bottom:14px}
.pharma-session-templates{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:16px}
@media(max-width:480px){.pharma-session-templates{grid-template-columns:repeat(2,1fr)}}
.pharma-tmpl-btn{
  padding:10px 8px;border-radius:var(--radius-md);text-align:center;border:1.5px solid var(--border);
  background:var(--surface);cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.pharma-tmpl-btn.active{border-color:var(--violet);background:color-mix(in srgb,var(--violet) 8%,var(--surface))}
.pharma-tmpl-btn:hover{border-color:var(--violet)}
.pharma-tmpl-icon{font-size:18px;margin-bottom:4px}
.pharma-tmpl-name{font-size:var(--font-size-sm);font-weight:600;color:var(--text)}
.pharma-tmpl-desc{font-size:var(--font-size-xs);color:var(--text-faint);margin-top:2px}
.pharma-session-row{margin-bottom:12px}
.pharma-session-row-label{font-size:var(--font-size-xs);font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:var(--text-faint);margin-bottom:6px}
.pharma-session-chips{display:flex;flex-wrap:wrap;gap:6px}
.pharma-session-chip{
  display:inline-flex;align-items:center;
  padding:10px 13px;min-height:44px;border-radius:var(--radius-pill);font-size:var(--font-size-sm);font-weight:600;
  border:1.5px solid var(--border);background:var(--surface);color:var(--text-muted);cursor:pointer;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.pharma-session-chip.active{border-color:var(--violet);background:color-mix(in srgb,var(--violet) 10%,var(--surface));color:var(--violet-deep)}
/* Card cap slider row */
.pharma-session-cap-row{margin-bottom:12px}
.pharma-session-cap-label-row{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:6px}
.pharma-session-cap-val{font-size:var(--font-size-sm);font-weight:600;color:var(--violet-deep);font-variant-numeric:tabular-nums}
.pharma-session-cap-slider{
  width:100%;accent-color:var(--violet);cursor:pointer;
  height:4px;border-radius:var(--radius-2xs);
}
/* Count preview + launch */
.pharma-session-count{
  text-align:center;font-size:var(--font-size-md);font-weight:600;color:var(--violet-deep);
  padding:8px 0 4px;min-height:22px;transition:color .15s;
}
.pharma-session-count--empty{color:var(--text-faint)}
.pharma-session-launch{
  width:100%;padding:12px;margin-top:4px;border-radius:var(--radius-md);
  font-size:var(--font-size-lg);font-weight:700;border:none;
  background:var(--violet);color:var(--text-on-pharma);cursor:pointer;
  box-shadow:0 2px 0 var(--violet-deep);transition:background .1s,color .1s,border-color .1s,box-shadow .1s,transform .1s,opacity .1s;
}
.pharma-session-launch:hover{transform:translateY(-1px);box-shadow:0 3px 0 var(--violet-deep)}
.pharma-session-launch:active{transform:translateY(1px);box-shadow:none}
.pharma-session-launch:disabled{opacity:.45;cursor:default;transform:none;box-shadow:none}

/* ── Pharma toolbar rows ────────────────────────────────────────────────── */
.pharma-tb-row{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.pharma-tb-row--filters{flex-wrap:wrap}

/* ── View toggle (Drugs / Classes) — equal-width ─────────────────────────── */
.pharma-view-toggle{
  display:flex;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-md);padding:2px;gap:2px;flex-shrink:0;
}
@media(max-width:480px){.pharma-view-toggle{width:100%}}
.pharma-view-btn{
  /* flex:1 makes both Drugs and Classes buttons the same width */
  flex:1;padding:4px 12px;border-radius:var(--radius-sm);font-size:var(--font-size-sm);font-weight:600;
  border:none;background:transparent;color:var(--text-muted);cursor:pointer;white-space:nowrap;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.pharma-view-btn.active{background:var(--violet);color:var(--text-on-pharma);box-shadow:var(--shadow-pill)}

/* ── Filter disclosure toggle (H-P1-04) ────────────────────────────────── */
/* Collapses row 2 (level + status + extras chips) behind a single chip.
   Shows active filter count as a small badge. Row 2 auto-opens when any
   filter is active; JS also respects state.pharmaLib.filterRowOpen. */
.pharma-filter-toggle{
  padding:5px 11px;border-radius:var(--radius-lg);font-size:var(--font-size-sm);font-weight:600;
  border:1.5px solid var(--border);background:var(--surface);color:var(--text-muted);cursor:pointer;
  display:flex;align-items:center;gap:5px;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.pharma-filter-toggle.active{
  border-color:var(--violet);background:color-mix(in srgb,var(--violet) 10%,var(--surface));color:var(--violet-deep);
}
.pharma-filter-count{
  display:inline-flex;align-items:center;justify-content:center;
  width:16px;height:16px;border-radius:50%;
  background:var(--violet);color:var(--text-on-pharma);font-size:9px;font-weight:700;
}

/* ── Select mode toggle ─────────────────────────────────────────────────── */
.pharma-select-toggle{
  padding:5px 11px;border-radius:var(--radius-sm);font-size:var(--font-size-sm);font-weight:600;
  border:1.5px solid var(--border);background:var(--surface);color:var(--text-muted);cursor:pointer;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.pharma-select-toggle.active{
  border-color:var(--violet);background:color-mix(in srgb,var(--violet) 10%,var(--surface));color:var(--violet-deep);
}

/* ── Drug card select ring + checkbox ──────────────────────────────────── */
.pharma-drug-card.pharma-selected{
  border-color:var(--violet);
  box-shadow:0 0 0 2px color-mix(in srgb,var(--violet) 30%,transparent);
}
.pharma-select-check{
  width:20px;height:20px;border-radius:50%;border:2px solid var(--border);
  background:var(--surface);display:flex;align-items:center;justify-content:center;
  flex-shrink:0;margin-right:4px;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.pharma-select-check.checked{background:var(--violet);border-color:var(--violet);color:white}
.pharma-select-check svg{width:11px;height:11px;stroke:white}

/* ── Bulk action bar ────────────────────────────────────────────────────── */
.pharma-bulk-bar{
  position:fixed;bottom:0;left:0;right:0;z-index:250; /* above tab bar (200) */
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding:10px 16px calc(10px + env(safe-area-inset-bottom));
  background:var(--surface-alt2);border-top:1px solid var(--border);
  box-shadow:var(--shadow-floating-bar); /* H-P2-01: token replaces literal */
  animation:sheetUp var(--duration-md) ease-out; /* WS5: canonical sheetUp (full-slide) */
}
/* WS5 (2026-05-05): @keyframes sheetUp = full-slide bottom-sheet enter (translateY(100%)→none).
   @keyframes sheetCentreIn = peek-fade for centred modals + banners (translateY(20px)+opacity).
   @keyframes backdropIn = backdrop opacity fade. All three defined as singletons below. */
.pharma-bulk-count{font-size:var(--font-size-md);font-weight:600;color:var(--text);flex:1}
.pharma-bulk-btn{
  display:inline-flex;align-items:center;justify-content:center;
  padding:10px 16px;min-height:44px;border-radius:var(--radius-md);font-size:var(--font-size-md);font-weight:700;
  border:1.5px solid var(--border);background:var(--surface);color:var(--text-muted);
  cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);white-space:nowrap;
}
.pharma-bulk-btn--primary{
  background:var(--violet);color:var(--text-on-pharma);border-color:var(--violet);
  box-shadow:0 2px 0 var(--violet-deep);
}
.pharma-bulk-btn--primary:hover{transform:translateY(-1px);box-shadow:0 3px 0 var(--violet-deep)}

/* ── Class grid ─────────────────────────────────────────────────────────── */
/* patch-032 round 5 — .pharma-class-grid rules removed. The class is preserved
   on the col-stack wrapper as an extraClass; the grid-template-columns media
   rules were never effective (parent was display:flex, ignored). */

/* ── Class card ─────────────────────────────────────────────────────────── */
.pharma-class-card{
  background:var(--surface-alt2);border:1px solid var(--border);border-radius:var(--radius);
  border-left:3px solid var(--violet);overflow:hidden;transition:box-shadow var(--duration-sm);
  display:flex;flex-direction:column;
}
.pharma-class-card:hover{box-shadow:var(--shadow-sm)}
.pharma-class-card.expanded{border-color:var(--violet)}
.pharma-class-header{
  display:flex;align-items:flex-start;gap:8px;padding:10px 12px 8px;cursor:pointer;user-select:none;
}
.pharma-class-name-wrap{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}
.pharma-class-name{font-size:var(--font-size-lg);font-weight:600;color:var(--text)}
.pharma-class-levels{display:flex;gap:4px;flex-wrap:wrap}
.pharma-class-header-right{display:flex;align-items:center;gap:5px;flex-shrink:0;padding-top:1px}
.pharma-class-drug-count{font-size:var(--font-size-xs);color:var(--text-faint);font-weight:600;font-variant-numeric:tabular-nums}
.pharma-class-card.expanded .pharma-drug-chev{transform:rotate(180deg)}

/* Per-field rows */
.pharma-class-field-list{padding:0 12px 8px;display:flex;flex-direction:column;gap:3px}
.pharma-class-field-row{
  display:flex;align-items:center;gap:8px;padding:3px 0;
  border-bottom:1px solid color-mix(in srgb,var(--border) 40%,transparent);
}
.pharma-class-field-row:last-child{border-bottom:none}
.pharma-class-field-label{font-size:var(--font-size-xs);font-weight:500;color:var(--text-muted);flex:1;white-space:nowrap}
.pharma-class-field-dots{display:flex;gap:3px;align-items:center;flex-wrap:wrap}
.pharma-class-field-more{font-size:9px;color:var(--text-faint);margin-left:2px}
.pharma-class-field-stat{
  font-size:var(--font-size-2xs);font-weight:600;color:var(--text-faint);
  font-variant-numeric:tabular-nums;white-space:nowrap;min-width:32px;text-align:right;
}
.pharma-class-field-stat--new{color:color-mix(in srgb,var(--text-faint) 70%,transparent)}

/* Expanded drug list inside class card */
.pharma-class-drug-list{
  border-top:1px solid var(--border);
  display:flex;flex-direction:column;
}
.pharma-class-drug-row{
  display:flex;align-items:center;gap:8px;padding:7px 12px;
  border-bottom:1px solid color-mix(in srgb,var(--border) 50%,transparent);
  cursor:pointer;transition:background .1s;
}
.pharma-class-drug-row:last-child{border-bottom:none}
.pharma-class-drug-row:hover{background:color-mix(in srgb,var(--violet) 5%,var(--surface-alt2))}
.pharma-class-drug-row.pharma-selected{background:color-mix(in srgb,var(--violet) 10%,var(--surface-alt2))}
.pharma-class-drug-name{font-size:var(--font-size-md);font-weight:500;color:var(--text);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* smaller select check variant */
.pharma-select-check--sm{width:16px;height:16px;border-radius:var(--radius-tiny)}
.pharma-select-check--sm svg{width:9px;height:9px}
.pharma-select-check.partial{
  background:color-mix(in srgb,var(--violet) 30%,var(--surface));
  border-color:var(--violet);color:var(--violet-deep);
  font-size:var(--font-size-xs);font-weight:700;display:flex;align-items:center;justify-content:center;
}

/* Class card footer */
.pharma-class-footer{
  display:flex;align-items:center;gap:8px;padding:8px 12px;
  border-top:1px solid var(--border);margin-top:auto;
}
.pharma-class-add-all{
  padding:4px 10px;border-radius:var(--btn-radius);font-size:var(--font-size-sm);font-weight:600;
  border:1.5px solid var(--border);background:transparent;color:var(--text-muted);
  cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.pharma-class-add-all:hover{border-color:var(--violet);color:var(--violet-deep)}

/* Extras filter chip variant */
.pharma-filter-chip--extras{
  opacity:.55;font-style:italic;
}
.pharma-filter-chip--extras.active{opacity:1;font-style:normal}

/* ── Comparison sheet ───────────────────────────────────────────────────── */
.pharma-compare-sheet{
  max-width:none;width:min(98vw,960px);max-height:88dvh;
  display:flex;flex-direction:column;overflow:hidden;
}
/* Scrollable wrapper — horizontal scroll on narrow screens */
.pharma-cmp-scroll{
  flex:1;overflow-y:auto;overflow-x:auto;
  /* ensure field-label col sticks on horizontal scroll */
}
.pharma-cmp-name-row,.pharma-cmp-row{
  display:grid;gap:1px;background:var(--border);
  /* 90px sticky label col + min 160px per drug col */
  grid-template-columns:90px repeat(var(--cmp-cols,2),minmax(160px,1fr));
  min-width:calc(90px + var(--cmp-cols,2)*160px);
}
.pharma-cmp-name-row{border-bottom:2px solid var(--border);position:sticky;top:0;z-index:2}
.pharma-cmp-drug-header{
  display:flex;flex-direction:column;gap:4px;padding:10px 10px;
  background:var(--surface-alt2);
}
.pharma-cmp-drug-name{font-size:var(--font-size-md);font-weight:600;color:var(--text);line-height:1.3}
.pharma-cmp-field-label{
  display:flex;align-items:center;
  padding:0 8px;font-size:var(--font-size-2xs);font-weight:700;text-transform:uppercase;
  letter-spacing:.05em;color:var(--text-faint);background:var(--surface);
  border-right:1px solid var(--border);position:sticky;left:0;z-index:1;
}
.pharma-cmp-cell{
  padding:8px 10px;background:var(--surface-alt2);
  display:flex;flex-direction:column;gap:5px;
  transition:background var(--duration-sm);
}
.pharma-cmp-cell--has-text{cursor:pointer}
.pharma-cmp-cell--has-text:hover{background:color-mix(in srgb,var(--violet) 5%,var(--surface-alt2))}
/* Compact FSRS state row: dot + short label */
.pharma-cmp-state-row{display:flex;align-items:center;gap:5px}
.pharma-cmp-state-dot{
  width:8px;height:8px;border-radius:50%;border:1.5px solid var(--border);flex-shrink:0;
}
.pharma-cmp-state-label{font-size:9.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
.pharma-cmp-state-label--new{display:none}
.pharma-cmp-state-label--learning{color:var(--honey-deep)}
.pharma-cmp-state-label--review{color:var(--sage-deep)}
.pharma-cmp-state-label--due,.pharma-cmp-state-label--overdue{color:var(--coral-deep)}
.pharma-cmp-cell-text{font-size:var(--font-size-md);line-height:1.6;color:var(--text);animation:fadeIn .15s}
.pharma-cmp-cell-text--collapsed{
  display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden;
  color:var(--text-muted);
}
.pharma-cmp-cell--expanded .pharma-cmp-cell-text--collapsed{
  display:block;-webkit-line-clamp:unset;overflow:visible;color:var(--text);
}
.pharma-cmp-loading{padding:24px;text-align:center;color:var(--text-faint);font-size:var(--font-size-md)}

/* patch-007 — Active-card state, Effect 6 (composed). WS4: consolidated
   into .card.keyboard-focused above; per-type rules kept here for recall
   + pharma (which still emit .recall-card/.pharma-card) as composition
   aliases that delegate to the unified token-driven rule.
   SAQ — Sprint J: outer wrapper merged into single element; rule targets
   .saq-card directly (no longer needs .saq-card-face descendant). */
.recall-card.keyboard-focused{
  transition:transform var(--duration-sm) var(--ease-out), box-shadow var(--duration-sm) var(--ease-out), padding var(--duration-sm) var(--ease-out), background var(--duration-sm) var(--ease-out), border-left-width var(--duration-sm) var(--ease-out);
  transform:translateY(-1px);
  border-left-width:calc(var(--card-stripe-width) + 2px); /* 6px */
  padding-left:calc(var(--card-padding-inline) - 2px);    /* 12px */
  background:color-mix(in srgb,var(--sky) 10%,var(--surface-alt2)); /* WS11: --sage→--sky */
  box-shadow:0 4px 14px -4px color-mix(in srgb,var(--sky) 40%,transparent);
}
.pharma-card.keyboard-focused{
  background:color-mix(in srgb,var(--violet) 10%,var(--surface-alt2));
  box-shadow:0 4px 14px -4px color-mix(in srgb,var(--violet) 40%,transparent);
}
/* SAQ — Sprint J: single element; rule targets .saq-card directly. */
.saq-card.keyboard-focused.active{
  transition:transform var(--duration-sm) var(--ease-out), box-shadow var(--duration-sm) var(--ease-out), padding var(--duration-sm) var(--ease-out), background var(--duration-sm) var(--ease-out), border-left-width var(--duration-sm) var(--ease-out);
  transform:translateY(-1px);
  border-left-width:calc(var(--card-stripe-width) + 2px); /* 6px */
  padding-left:calc(var(--card-padding-inline) + 3px);    /* 17px */
  background:color-mix(in srgb,var(--rose) 10%,var(--surface-alt2)); /* WS11: --honey→--rose */
  box-shadow:0 4px 14px -4px color-mix(in srgb,var(--rose) 40%,transparent);
}
@media (prefers-reduced-motion: reduce){
  .recall-card.keyboard-focused,
  .saq-card.keyboard-focused.active{transform:none;transition:background var(--duration-sm) var(--ease-out)}
}
.recall-prompt{font-weight:500;font-size:var(--font-size-xl);line-height:1.45}
/* v172 — Answer body bg one shade darker than card surface (Issue #21).
   Cream-on-cream lacked depth; color-mix darkens --surface by ~6% for a
   subtle nested-surface feel. Border now solid 0.5px instead of dashed. */
/* Card-redesign 2026-05-05 IMPROVE — solidity rule §21: no inner box-within-card
   chrome. Body text sits flush on the card surface; no bg, no border. Padding
   compensates for the lost inset. */
/* Sprint J — .recall-answer display rules DELETED. recallCard() now emits
   .fc-answer; visibility handled by .study-card.revealed .fc-answer. Only
   typography rules (p, li, table etc) remain below — they cover both classes. */
/* card-unification sprint J: contenteditable styling for fc-answer */
.recall-answer[contenteditable="true"],.fc-answer[contenteditable="true"]{border-color:var(--accent);border-style:solid;background:var(--accent-soft);outline:none}

/* v176 — Rich-text typography for ALL markdown-rendered card bodies.
   Applies to every renderRichTextIn target so paragraphs, lists, code,
   blockquotes, and headings get proper spacing + styling instead of
   collapsing into a wall of text. */
.recall-answer p,.fc-answer p,.fc-callout-body p,.fc-callout-body-inline p,
.saq-callout-body p,
.fc-tab-panel p,.model-body p,.toggle-body p,.card-body p{margin:0 0 .55em}
.recall-answer p:last-child,.fc-answer p:last-child,.fc-callout-body p:last-child,
.fc-callout-body-inline p:last-child,.saq-callout-body p:last-child,.fc-tab-panel p:last-child,
.model-body p:last-child,.toggle-body p:last-child,.card-body p:last-child{margin-bottom:0}
.recall-answer ul,.recall-answer ol,.fc-answer ul,.fc-answer ol,
.fc-callout-body ul,.fc-callout-body ol,.fc-callout-body-inline ul,.fc-callout-body-inline ol,
.saq-callout-body ul,
.fc-tab-panel ul,.saq-callout-body ol,.fc-tab-panel ol,.model-body ul,.model-body ol,
.toggle-body ul,.toggle-body ol,.card-body ul,.card-body ol{margin:.3em 0 .55em;padding-left:1.4em}
.recall-answer li,.fc-answer li,.fc-callout-body li,.fc-callout-body-inline li,
.saq-callout-body li,
.fc-tab-panel li,.model-body li,.toggle-body li,.card-body li{margin:.15em 0}
.recall-answer code,.fc-answer code,.fc-callout-body code,.fc-callout-body-inline code,
.saq-callout-body code,
.fc-tab-panel code,.model-body code,.toggle-body code,.card-body code{
  font-family:var(--font-mono);font-size:.92em;
  background:color-mix(in srgb,var(--text) 8%,transparent);
  padding:1px 5px;border-radius:var(--radius-tiny);
}
.recall-answer blockquote,.fc-answer blockquote,.fc-callout-body blockquote,
.fc-callout-body-inline blockquote,.saq-callout-body blockquote,.fc-tab-panel blockquote,.model-body blockquote,
.toggle-body blockquote,.card-body blockquote{
  margin:.4em 0;padding:6px 12px;
  border-left:3px solid color-mix(in srgb,var(--accent) 50%,var(--border));
  background:color-mix(in srgb,var(--accent) 5%,transparent);
  color:var(--text-muted);font-style:italic;
}
.recall-answer h1,.recall-answer h2,.recall-answer h3,.recall-answer h4,
.fc-answer h1,.fc-answer h2,.fc-answer h3,.fc-answer h4,
.fc-callout-body h1,.fc-callout-body h2,.fc-callout-body h3,
.saq-callout-body h1,
.fc-tab-panel h1,.saq-callout-body h2,.fc-tab-panel h2,.saq-callout-body h3,.fc-tab-panel h3,
.model-body h1,.model-body h2,.model-body h3,
.card-body h1,.card-body h2,.card-body h3{
  font-size:1em;font-weight:600;margin:.5em 0 .25em;color:var(--text);
  border:0;padding:0;display:block;
}
.recall-answer strong,.fc-answer strong,.fc-callout-body strong,
.saq-callout-body strong,
.fc-tab-panel strong,.model-body strong,.card-body strong{font-weight:600;color:var(--text)}
.recall-answer em,.fc-answer em,.fc-callout-body em,
.saq-callout-body em,
.fc-tab-panel em,.model-body em,.card-body em{font-style:italic;color:var(--text)}
/* patch-032 — markdown tables in answer bodies (model-body / saq-callout-body /
   card-body / fc-callout-body / recall-answer). Default browser tables render
   borderless which makes dense PK / compare-and-contrast tables impossible to
   parse. Faint cell borders + tinted header row + zebra rows give the structure
   the eye needs without competing with the prose. Numbers stay tabular for
   alignment. */
.recall-answer table,.fc-answer table,.fc-callout-body table,.fc-callout-body-inline table,
.saq-callout-body table,
.fc-tab-panel table,.model-body table,.card-body table,.toggle-body table{
  /* iOS-render audit 2026-05-23 — dense PK / compare-and-contrast tables exceed
     the card width and used to overflow off the right edge (clipped). GitHub-
     standard CSS-only fix: make the table a block box that scrolls horizontally
     within the card. width:max-content lets columns size to content; max-width
     caps narrow tables at the card width; overscroll-x:contain stops the swipe
     from hijacking page scroll. No renderer change needed. */
  display:block;
  width:max-content;
  max-width:100%;
  overflow-x:auto;
  overscroll-behavior-x:contain;
  border-collapse:collapse;margin:8px 0;
  font-size:.95em;line-height:1.4;
  font-variant-numeric:tabular-nums;
}
.recall-answer th,.recall-answer td,.fc-answer th,.fc-answer td,
.fc-callout-body th,.fc-callout-body td,.fc-callout-body-inline th,.fc-callout-body-inline td,
.saq-callout-body th,
.fc-tab-panel th,.saq-callout-body td,.fc-tab-panel td,.model-body th,.model-body td,
.card-body th,.card-body td,.toggle-body th,.toggle-body td{
  border:1px solid color-mix(in srgb,var(--border) 70%,transparent);
  padding:5px 8px;text-align:left;vertical-align:top;
}
.recall-answer th,.fc-answer th,.fc-callout-body th,.fc-callout-body-inline th,
.saq-callout-body th,
.fc-tab-panel th,.model-body th,.card-body th,.toggle-body th{
  background:color-mix(in srgb,var(--surface-alt) 60%,transparent);
  font-weight:600;color:var(--text);
}
/* Zebra: every even body row tinted; keeps header distinct without a heavier border */
.recall-answer tbody tr:nth-child(even) td,
.fc-answer tbody tr:nth-child(even) td,
.fc-callout-body tbody tr:nth-child(even) td,
.fc-callout-body-inline tbody tr:nth-child(even) td,
.saq-callout-body tbody tr:nth-child(even) td,
.fc-tab-panel tbody tr:nth-child(even) td,
.model-body tbody tr:nth-child(even) td,
.card-body tbody tr:nth-child(even) td,
.toggle-body tbody tr:nth-child(even) td{
  background:color-mix(in srgb,var(--surface-alt) 30%,transparent);
}
/* First column (label column for compare-and-contrast tables) tinted slightly
   so the eye anchors to the parameter names. */
.recall-answer td:first-child,.fc-answer td:first-child,
.fc-callout-body td:first-child,.fc-callout-body-inline td:first-child,
.saq-callout-body td:first-child,
.fc-tab-panel td:first-child,.model-body td:first-child,
.card-body td:first-child,.toggle-body td:first-child{
  color:var(--text-muted);font-weight:500;
}

/* v177 — SAQ model-answer formatting refinements. Three groups of rules:
   (1) kill the deadspace between headings and their first following sibling
       (paragraphs and lists no longer add their own margin-top);
   (2) strengthen GFM table borders so the cells are obviously gridded
       (the prior 70%-transparent border was near-invisible on cream);
   (3) typed examiner-callout blockquotes — classifyCallouts() in app.js
       tags <blockquote>s whose first <strong> matches a known label
       ("Examiner misses to nail:", "One thing to remember:", "Definition:",
       "Keystone:", "Safety margin:") with .callout + .callout-<kind>. The
       source markdown is unchanged for export fidelity; the in-app render
       hides the verbose label and draws an icon + coloured left-bar. */

/* (1) Heading deadspace — zero top-margin on the first element after a heading.
   Existing rule sets h2/h3/h4 to margin:.5em 0 .25em; sibling paragraphs and
   lists were adding their own .55em / .3em top, producing visible deadspace. */
.recall-answer h1+*,.recall-answer h2+*,.recall-answer h3+*,.recall-answer h4+*,
.fc-answer h1+*,.fc-answer h2+*,.fc-answer h3+*,.fc-answer h4+*,
.fc-callout-body h1+*,.fc-callout-body h2+*,.fc-callout-body h3+*,
.fc-callout-body-inline h1+*,.fc-callout-body-inline h2+*,.fc-callout-body-inline h3+*,
.saq-callout-body h1+*,
.fc-tab-panel h1+*,.saq-callout-body h2+*,.fc-tab-panel h2+*,.saq-callout-body h3+*,.fc-tab-panel h3+*,
.model-body h1+*,.model-body h2+*,.model-body h3+*,
.card-body h1+*,.card-body h2+*,.card-body h3+*,
.toggle-body h1+*,.toggle-body h2+*,.toggle-body h3+*{margin-top:0}

/* (2) Table border strengthening — same selectors as the patch-032 rules
   above but with a solid, visible border colour. Header row gets a slightly
   darker tint to lock it as the heading. */
.recall-answer th,.recall-answer td,.fc-answer th,.fc-answer td,
.fc-callout-body th,.fc-callout-body td,.fc-callout-body-inline th,.fc-callout-body-inline td,
.saq-callout-body th,
.fc-tab-panel th,.saq-callout-body td,.fc-tab-panel td,.model-body th,.model-body td,
.card-body th,.card-body td,.toggle-body th,.toggle-body td{
  border-color:color-mix(in srgb,var(--border) 100%,transparent);
}
.recall-answer th,.fc-answer th,.fc-callout-body th,.fc-callout-body-inline th,
.saq-callout-body th,
.fc-tab-panel th,.model-body th,.card-body th,.toggle-body th{
  background:color-mix(in srgb,var(--accent) 12%,var(--surface-alt));
  border-bottom:2px solid color-mix(in srgb,var(--accent) 40%,var(--border));
}

/* (3a) Common chrome for typed callouts. 4px coloured left-bar, gentle tint,
   16px left padding leaves room for the absolutely-positioned icon. */
.recall-answer blockquote.callout,.fc-answer blockquote.callout,
.fc-callout-body blockquote.callout,.fc-callout-body-inline blockquote.callout,
.saq-callout-body blockquote.callout,
.fc-tab-panel blockquote.callout,.model-body blockquote.callout,
.card-body blockquote.callout,.toggle-body blockquote.callout{
  position:relative;
  margin:.6em 0;padding:8px 12px 8px 38px;
  border-left:4px solid var(--accent);
  background:color-mix(in srgb,var(--accent) 5%,transparent);
  color:var(--text);font-style:normal;
  border-radius:0 4px 4px 0;
}
.recall-answer blockquote.callout::before,.fc-answer blockquote.callout::before,
.fc-callout-body blockquote.callout::before,.fc-callout-body-inline blockquote.callout::before,
.saq-callout-body blockquote.callout::before,
.fc-tab-panel blockquote.callout::before,.model-body blockquote.callout::before,
.card-body blockquote.callout::before,.toggle-body blockquote.callout::before{
  content:'';position:absolute;left:12px;top:10px;width:18px;height:18px;
  background-position:center;background-repeat:no-repeat;background-size:contain;
}
/* Tighten body spacing inside callouts so the icon aligns with the first line. */
.recall-answer blockquote.callout > *:first-child,
.fc-answer blockquote.callout > *:first-child,
.fc-callout-body blockquote.callout > *:first-child,
.fc-callout-body-inline blockquote.callout > *:first-child,
.saq-callout-body blockquote.callout > *:first-child,
.fc-tab-panel blockquote.callout > *:first-child,
.model-body blockquote.callout > *:first-child,
.card-body blockquote.callout > *:first-child,
.toggle-body blockquote.callout > *:first-child{margin-top:0}
.recall-answer blockquote.callout > *:last-child,
.fc-answer blockquote.callout > *:last-child,
.fc-callout-body blockquote.callout > *:last-child,
.fc-callout-body-inline blockquote.callout > *:last-child,
.saq-callout-body blockquote.callout > *:last-child,
.fc-tab-panel blockquote.callout > *:last-child,
.model-body blockquote.callout > *:last-child,
.card-body blockquote.callout > *:last-child,
.toggle-body blockquote.callout > *:last-child{margin-bottom:0}

/* (3b) callout-examiner — high-yield / examiner-pitfalls. Iconless: the
   peri (purple) left-bar carries the signal, no glyph. Most common callout
   (63% of SAQs). Reduce left-padding since there's no icon slot to reserve. */
.recall-answer blockquote.callout-examiner,.fc-answer blockquote.callout-examiner,
.fc-callout-body blockquote.callout-examiner,.fc-callout-body-inline blockquote.callout-examiner,
.saq-callout-body blockquote.callout-examiner,
.fc-tab-panel blockquote.callout-examiner,.model-body blockquote.callout-examiner,
.card-body blockquote.callout-examiner,.toggle-body blockquote.callout-examiner{
  border-left-color:var(--peri,#7c5cb8);
  background:color-mix(in srgb,var(--peri,#7c5cb8) 6%,transparent);
  padding-left:14px;
}
.recall-answer blockquote.callout-examiner::before,.fc-answer blockquote.callout-examiner::before,
.fc-callout-body blockquote.callout-examiner::before,.fc-callout-body-inline blockquote.callout-examiner::before,
.saq-callout-body blockquote.callout-examiner::before,
.fc-tab-panel blockquote.callout-examiner::before,.model-body blockquote.callout-examiner::before,
.card-body blockquote.callout-examiner::before,.toggle-body blockquote.callout-examiner::before{
  content:none;
}

/* (3c) callout-key — "One thing to remember". Lightbulb icon, honey accent. */
.recall-answer blockquote.callout-key,.fc-answer blockquote.callout-key,
.fc-callout-body blockquote.callout-key,.fc-callout-body-inline blockquote.callout-key,
.saq-callout-body blockquote.callout-key,
.fc-tab-panel blockquote.callout-key,.model-body blockquote.callout-key,
.card-body blockquote.callout-key,.toggle-body blockquote.callout-key{
  border-left-color:var(--honey,#d4922b);
  background:color-mix(in srgb,var(--honey,#d4922b) 7%,transparent);
}
.recall-answer blockquote.callout-key::before,.fc-answer blockquote.callout-key::before,
.fc-callout-body blockquote.callout-key::before,.fc-callout-body-inline blockquote.callout-key::before,
.saq-callout-body blockquote.callout-key::before,
.fc-tab-panel blockquote.callout-key::before,.model-body blockquote.callout-key::before,
.card-body blockquote.callout-key::before,.toggle-body blockquote.callout-key::before{
  /* Lucide `lightbulb` */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23d4922b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5'/><path d='M9 18h6'/><path d='M10 22h4'/></svg>");
}

/* (3d) callout-definition — vocabulary clarification. Book icon, sage accent. */
.recall-answer blockquote.callout-definition,.fc-answer blockquote.callout-definition,
.fc-callout-body blockquote.callout-definition,.fc-callout-body-inline blockquote.callout-definition,
.saq-callout-body blockquote.callout-definition,
.fc-tab-panel blockquote.callout-definition,.model-body blockquote.callout-definition,
.card-body blockquote.callout-definition,.toggle-body blockquote.callout-definition{
  border-left-color:var(--sage,#5e8b6c);
  background:color-mix(in srgb,var(--sage,#5e8b6c) 6%,transparent);
}
.recall-answer blockquote.callout-definition::before,.fc-answer blockquote.callout-definition::before,
.fc-callout-body blockquote.callout-definition::before,.fc-callout-body-inline blockquote.callout-definition::before,
.saq-callout-body blockquote.callout-definition::before,
.fc-tab-panel blockquote.callout-definition::before,.model-body blockquote.callout-definition::before,
.card-body blockquote.callout-definition::before,.toggle-body blockquote.callout-definition::before{
  /* Lucide `book-open` */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235e8b6c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 7v14'/><path d='M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z'/></svg>");
}

/* (3e) callout-safety — "Keystone" / "Safety margin". Warning-triangle icon. */
.recall-answer blockquote.callout-safety,.fc-answer blockquote.callout-safety,
.fc-callout-body blockquote.callout-safety,.fc-callout-body-inline blockquote.callout-safety,
.saq-callout-body blockquote.callout-safety,
.fc-tab-panel blockquote.callout-safety,.model-body blockquote.callout-safety,
.card-body blockquote.callout-safety,.toggle-body blockquote.callout-safety{
  border-left-color:#c0573a;
  background:color-mix(in srgb,#c0573a 7%,transparent);
}
.recall-answer blockquote.callout-safety::before,.fc-answer blockquote.callout-safety::before,
.fc-callout-body blockquote.callout-safety::before,.fc-callout-body-inline blockquote.callout-safety::before,
.saq-callout-body blockquote.callout-safety::before,
.fc-tab-panel blockquote.callout-safety::before,.model-body blockquote.callout-safety::before,
.card-body blockquote.callout-safety::before,.toggle-body blockquote.callout-safety::before{
  /* Lucide `triangle-alert` */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c0573a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3'/><path d='M12 9v4'/><path d='M12 17h.01'/></svg>");
}

/* v178 — Six new typed callouts: Pitfall, Mnemonic, Clinical pearl, Equation,
   Mechanism, Heuristic. Same chrome pattern as the existing four (4px coloured
   left-bar, 5% tint background, ::before Lucide SVG icon, 38px left-padding
   to reserve the icon slot). Background opacity halved from sky-fill / lime-fill
   per user feedback ("less vibrant — try 50%"). Each variant adds its colour
   token + icon override. */

/* (3g) callout-pitfall — common-mistake / wrong-track signal. Red bar
   (shares with safety) but distinct icon (Lucide `octagon-alert`). */
.recall-answer blockquote.callout-pitfall,.fc-answer blockquote.callout-pitfall,
.fc-callout-body blockquote.callout-pitfall,.fc-callout-body-inline blockquote.callout-pitfall,
.saq-callout-body blockquote.callout-pitfall,
.fc-tab-panel blockquote.callout-pitfall,.model-body blockquote.callout-pitfall,
.card-body blockquote.callout-pitfall,.toggle-body blockquote.callout-pitfall{
  border-left-color:#c0573a;
  background:color-mix(in srgb,#c0573a 7%,transparent);
}
.recall-answer blockquote.callout-pitfall::before,.fc-answer blockquote.callout-pitfall::before,
.fc-callout-body blockquote.callout-pitfall::before,.fc-callout-body-inline blockquote.callout-pitfall::before,
.saq-callout-body blockquote.callout-pitfall::before,
.fc-tab-panel blockquote.callout-pitfall::before,.model-body blockquote.callout-pitfall::before,
.card-body blockquote.callout-pitfall::before,.toggle-body blockquote.callout-pitfall::before{
  /* Lucide `octagon-alert` */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c0573a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M2.586 17.414A2 2 0 0 1 2 16V8a2 2 0 0 1 .586-1.414l4-4A2 2 0 0 1 8 2h8a2 2 0 0 1 1.414.586l4 4A2 2 0 0 1 22 8v8a2 2 0 0 1-.586 1.414l-4 4A2 2 0 0 1 16 22H8a2 2 0 0 1-1.414-.586z'/><path d='M12 8v4'/><path d='M12 16h.01'/></svg>");
}

/* (3h) callout-mnemonic — peri (matches examiner family). Lucide `brain`.
   The body uses the .mnem-letter chip pattern (see below) so `**M**ethanol`
   in source renders as a coloured-chip "M" continuous with "ethanol". */
.recall-answer blockquote.callout-mnemonic,.fc-answer blockquote.callout-mnemonic,
.fc-callout-body blockquote.callout-mnemonic,.fc-callout-body-inline blockquote.callout-mnemonic,
.saq-callout-body blockquote.callout-mnemonic,
.fc-tab-panel blockquote.callout-mnemonic,.model-body blockquote.callout-mnemonic,
.card-body blockquote.callout-mnemonic,.toggle-body blockquote.callout-mnemonic{
  border-left-color:var(--peri,#7c5cb8);
  background:color-mix(in srgb,var(--peri,#7c5cb8) 6%,transparent);
}
.recall-answer blockquote.callout-mnemonic::before,.fc-answer blockquote.callout-mnemonic::before,
.fc-callout-body blockquote.callout-mnemonic::before,.fc-callout-body-inline blockquote.callout-mnemonic::before,
.saq-callout-body blockquote.callout-mnemonic::before,
.fc-tab-panel blockquote.callout-mnemonic::before,.model-body blockquote.callout-mnemonic::before,
.card-body blockquote.callout-mnemonic::before,.toggle-body blockquote.callout-mnemonic::before{
  /* Lucide `brain` */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237c5cb8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z'/><path d='M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z'/><path d='M15 13a4.5 4.5 0 0 1-3-4'/><path d='M17.599 6.5a3 3 0 0 0 .399-1.375'/><path d='M6.003 5.125A3 3 0 0 0 6.401 6.5'/><path d='M3.477 10.896a4 4 0 0 1 .585-.396'/><path d='M19.938 10.5a4 4 0 0 1 .585.396'/><path d='M6 18a4 4 0 0 1-1.967-.516'/><path d='M19.967 17.484A4 4 0 0 1 18 18'/></svg>");
}
/* Mnemonic letter chips — `**M**ethanol` source renders as `<strong>M</strong>ethanol`.
   Inside callout-mnemonic, the surviving <strong>s (after classifier strips
   the "Mnemonic:" label) get a small coloured chip-pill. Continuous with
   the following text (no trailing margin) so `<M>ethanol` reads as one word. */
.recall-answer blockquote.callout-mnemonic strong,.fc-answer blockquote.callout-mnemonic strong,
.fc-callout-body blockquote.callout-mnemonic strong,.fc-callout-body-inline blockquote.callout-mnemonic strong,
.saq-callout-body blockquote.callout-mnemonic strong,
.fc-tab-panel blockquote.callout-mnemonic strong,.model-body blockquote.callout-mnemonic strong,
.card-body blockquote.callout-mnemonic strong,.toggle-body blockquote.callout-mnemonic strong{
  background:color-mix(in srgb,var(--peri,#7c5cb8) 18%,transparent);
  color:var(--peri-deep,var(--peri,#7c5cb8));
  padding:1px 5px;border-radius:3px;
  font-weight:700;font-size:1.05em;
  margin-right:0;
}

/* (3i) callout-pearl — Clinical pearl. Sky family + Lucide `search-check`.
   Background tinted at 7% per "less vibrant" feedback (was 14% sky-fill). */
.recall-answer blockquote.callout-pearl,.fc-answer blockquote.callout-pearl,
.fc-callout-body blockquote.callout-pearl,.fc-callout-body-inline blockquote.callout-pearl,
.saq-callout-body blockquote.callout-pearl,
.fc-tab-panel blockquote.callout-pearl,.model-body blockquote.callout-pearl,
.card-body blockquote.callout-pearl,.toggle-body blockquote.callout-pearl{
  border-left-color:var(--sky,#4D8CB0);
  background:color-mix(in srgb,var(--sky,#4D8CB0) 7%,transparent);
}
.recall-answer blockquote.callout-pearl::before,.fc-answer blockquote.callout-pearl::before,
.fc-callout-body blockquote.callout-pearl::before,.fc-callout-body-inline blockquote.callout-pearl::before,
.saq-callout-body blockquote.callout-pearl::before,
.fc-tab-panel blockquote.callout-pearl::before,.model-body blockquote.callout-pearl::before,
.card-body blockquote.callout-pearl::before,.toggle-body blockquote.callout-pearl::before{
  /* Lucide `search-check` */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234D8CB0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m8 11 2 2 4-4'/><circle cx='11' cy='11' r='8'/><path d='m21 21-4.3-4.3'/></svg>");
}

/* (3j) callout-equation — Lime family + Lucide `sigma`. Source content can be
   either `> **Equation:** [[axiom:slug]]` (transcluded from the axiom catalog)
   OR inline KaTeX `> **Equation:** $V_D / V_T = (P_{aCO_2} - P_{ECO_2}) / P_{aCO_2}$`.
   When transclusion target is missing, falls back silently to the inline text. */
.recall-answer blockquote.callout-equation,.fc-answer blockquote.callout-equation,
.fc-callout-body blockquote.callout-equation,.fc-callout-body-inline blockquote.callout-equation,
.saq-callout-body blockquote.callout-equation,
.fc-tab-panel blockquote.callout-equation,.model-body blockquote.callout-equation,
.card-body blockquote.callout-equation,.toggle-body blockquote.callout-equation{
  border-left-color:var(--saltbush, #5E6670);
  background:color-mix(in srgb,var(--saltbush, #5E6670) 7%,transparent);
}
.recall-answer blockquote.callout-equation::before,.fc-answer blockquote.callout-equation::before,
.fc-callout-body blockquote.callout-equation::before,.fc-callout-body-inline blockquote.callout-equation::before,
.saq-callout-body blockquote.callout-equation::before,
.fc-tab-panel blockquote.callout-equation::before,.model-body blockquote.callout-equation::before,
.card-body blockquote.callout-equation::before,.toggle-body blockquote.callout-equation::before{
  /* Lucide `sigma` */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238A9E1A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M18 7V5a1 1 0 0 0-1-1H6.5a.5.5 0 0 0-.4.8l4.5 6a2 2 0 0 1 0 2.4l-4.5 6a.5.5 0 0 0 .4.8H17a1 1 0 0 0 1-1v-2'/></svg>");
}

/* (3k) callout-mechanism — Sky family (shares with pearl), distinct icon
   (Lucide `atom`). Content typically renders as a chip-pipeline (see .md-flow). */
.recall-answer blockquote.callout-mechanism,.fc-answer blockquote.callout-mechanism,
.fc-callout-body blockquote.callout-mechanism,.fc-callout-body-inline blockquote.callout-mechanism,
.saq-callout-body blockquote.callout-mechanism,
.fc-tab-panel blockquote.callout-mechanism,.model-body blockquote.callout-mechanism,
.card-body blockquote.callout-mechanism,.toggle-body blockquote.callout-mechanism{
  border-left-color:var(--sky,#4D8CB0);
  background:color-mix(in srgb,var(--sky,#4D8CB0) 7%,transparent);
}
.recall-answer blockquote.callout-mechanism::before,.fc-answer blockquote.callout-mechanism::before,
.fc-callout-body blockquote.callout-mechanism::before,.fc-callout-body-inline blockquote.callout-mechanism::before,
.saq-callout-body blockquote.callout-mechanism::before,
.fc-tab-panel blockquote.callout-mechanism::before,.model-body blockquote.callout-mechanism::before,
.card-body blockquote.callout-mechanism::before,.toggle-body blockquote.callout-mechanism::before{
  /* Lucide `atom` */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234D8CB0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='1'/><path d='M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z'/><path d='M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z'/></svg>");
}

/* (3l) callout-heuristic — Honey family + Lucide `scale`. Body preserves
   source newlines as visual line breaks (no bullets, no run-on sentence).
   marked.js with {breaks:true} already converts \n to <br>, so this rule
   just kills any inherited list-style and tightens line-height. */
.recall-answer blockquote.callout-heuristic,.fc-answer blockquote.callout-heuristic,
.fc-callout-body blockquote.callout-heuristic,.fc-callout-body-inline blockquote.callout-heuristic,
.saq-callout-body blockquote.callout-heuristic,
.fc-tab-panel blockquote.callout-heuristic,.model-body blockquote.callout-heuristic,
.card-body blockquote.callout-heuristic,.toggle-body blockquote.callout-heuristic{
  border-left-color:var(--honey,#d4922b);
  background:color-mix(in srgb,var(--honey,#d4922b) 7%,transparent);
}
.recall-answer blockquote.callout-heuristic::before,.fc-answer blockquote.callout-heuristic::before,
.fc-callout-body blockquote.callout-heuristic::before,.fc-callout-body-inline blockquote.callout-heuristic::before,
.saq-callout-body blockquote.callout-heuristic::before,
.fc-tab-panel blockquote.callout-heuristic::before,.model-body blockquote.callout-heuristic::before,
.card-body blockquote.callout-heuristic::before,.toggle-body blockquote.callout-heuristic::before{
  /* Lucide `scale` */
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23d4922b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m16 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z'/><path d='m2 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z'/><path d='M7 21h10'/><path d='M12 3v18'/><path d='M3 7h2c2 0 5-1 7-2 2 1 5 2 7 2h2'/></svg>");
}
.recall-answer blockquote.callout-heuristic p,.fc-answer blockquote.callout-heuristic p,
.fc-callout-body blockquote.callout-heuristic p,.fc-callout-body-inline blockquote.callout-heuristic p,
.saq-callout-body blockquote.callout-heuristic p,
.fc-tab-panel blockquote.callout-heuristic p,.model-body blockquote.callout-heuristic p,
.card-body blockquote.callout-heuristic p,.toggle-body blockquote.callout-heuristic p{
  line-height:1.6;
}

/* v178 — Wikilinks: in-app cross-references emitted by the preprocessor for
   [[topic:CODE]] / [[drug:slug]] / [[recall:slug]] syntax. Style is restrained:
   inherit colour, dotted underline that strengthens on hover. Cursor pointer
   signals interactivity. The .wikilink-{type} variants tint the underline so
   readers can distinguish the cross-reference target at a glance. */
.recall-answer a.wikilink,.fc-answer a.wikilink,.fc-callout-body a.wikilink,
.fc-callout-body-inline a.wikilink,.saq-callout-body a.wikilink,.fc-tab-panel a.wikilink,.model-body a.wikilink,
.card-body a.wikilink,.toggle-body a.wikilink{
  color:inherit;text-decoration:none;cursor:pointer;
  border-bottom:1px dotted color-mix(in srgb,var(--text) 35%,transparent);
  transition:border-bottom-color .15s, color .15s;
}
.recall-answer a.wikilink:hover,.fc-answer a.wikilink:hover,
.fc-callout-body a.wikilink:hover,.fc-callout-body-inline a.wikilink:hover,
.saq-callout-body a.wikilink:hover,
.fc-tab-panel a.wikilink:hover,.model-body a.wikilink:hover,
.card-body a.wikilink:hover,.toggle-body a.wikilink:hover{
  border-bottom-color:var(--accent);color:var(--accent);
}
.recall-answer a.wikilink-topic,.fc-answer a.wikilink-topic,
.fc-callout-body a.wikilink-topic,.fc-callout-body-inline a.wikilink-topic,
.saq-callout-body a.wikilink-topic,
.fc-tab-panel a.wikilink-topic,.model-body a.wikilink-topic,
.card-body a.wikilink-topic,.toggle-body a.wikilink-topic{
  border-bottom-color:color-mix(in srgb,var(--sage,#5e8b6c) 55%,transparent);
}
.recall-answer a.wikilink-drug,.fc-answer a.wikilink-drug,
.fc-callout-body a.wikilink-drug,.fc-callout-body-inline a.wikilink-drug,
.saq-callout-body a.wikilink-drug,
.fc-tab-panel a.wikilink-drug,.model-body a.wikilink-drug,
.card-body a.wikilink-drug,.toggle-body a.wikilink-drug{
  border-bottom-color:color-mix(in srgb,var(--honey,#d4922b) 55%,transparent);
}
.recall-answer a.wikilink-recall,.fc-answer a.wikilink-recall,
.fc-callout-body a.wikilink-recall,.fc-callout-body-inline a.wikilink-recall,
.saq-callout-body a.wikilink-recall,
.fc-tab-panel a.wikilink-recall,.model-body a.wikilink-recall,
.card-body a.wikilink-recall,.toggle-body a.wikilink-recall{
  border-bottom-color:color-mix(in srgb,var(--peri,#7c5cb8) 55%,transparent);
}
/* Mnemonic inline expansion (from [[mnemonic:slug]]). Renders as a stack of
   chipped letter + expansion rows, sharing the callout-mnemonic chip pattern. */
.recall-answer .md-mnemonic,.fc-answer .md-mnemonic,.fc-callout-body .md-mnemonic,
.fc-callout-body-inline .md-mnemonic,.saq-callout-body .md-mnemonic,.fc-tab-panel .md-mnemonic,.model-body .md-mnemonic,
.card-body .md-mnemonic,.toggle-body .md-mnemonic{
  display:inline-flex;flex-direction:column;gap:2px;
  margin:.3em 0;
  padding:6px 10px;
  border-left:3px solid var(--peri,#7c5cb8);
  background:color-mix(in srgb,var(--peri,#7c5cb8) 5%,transparent);
  border-radius:0 4px 4px 0;
  vertical-align:middle;
}
.recall-answer .md-mnemonic-row,.fc-answer .md-mnemonic-row,
.fc-callout-body .md-mnemonic-row,.fc-callout-body-inline .md-mnemonic-row,
.saq-callout-body .md-mnemonic-row,
.fc-tab-panel .md-mnemonic-row,.model-body .md-mnemonic-row,
.card-body .md-mnemonic-row,.toggle-body .md-mnemonic-row{
  display:block;line-height:1.5;
}
.recall-answer .md-mnemonic .md-mnemonic-row strong,
.fc-answer .md-mnemonic .md-mnemonic-row strong,
.fc-callout-body .md-mnemonic .md-mnemonic-row strong,
.fc-callout-body-inline .md-mnemonic .md-mnemonic-row strong,
.saq-callout-body .md-mnemonic .md-mnemonic-row strong,
.fc-tab-panel .md-mnemonic .md-mnemonic-row strong,
.model-body .md-mnemonic .md-mnemonic-row strong,
.card-body .md-mnemonic .md-mnemonic-row strong,
.toggle-body .md-mnemonic .md-mnemonic-row strong{
  background:color-mix(in srgb,var(--peri,#7c5cb8) 18%,transparent);
  color:var(--peri-deep,var(--peri,#7c5cb8));
  padding:1px 5px;border-radius:3px;
  font-weight:700;font-size:1.05em;margin-right:0;
}

/* v178 (patch-055) — Foundation-weak SAQ indicator. Set when worker dashboard
   marks the SAQ payload with `foundation_weak: true` because it transcludes
   one or more axioms the user has lapsed ≥2 times. Soft amber accent +
   small badge — not a blocker, just a hint that underlying material needs
   review. Title attribute exposes the specific axioms. */
.saq-card.saq-card--foundation-weak{
  position:relative;
}
.saq-card.saq-card--foundation-weak::before{
  content:'foundation review';
  position:absolute;top:8px;right:8px;
  font-size:10px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  color:var(--honey-deep,var(--honey,#d4922b));
  background:color-mix(in srgb,var(--honey,#d4922b) 14%,transparent);
  padding:2px 6px;border-radius:3px;
  pointer-events:none;
  z-index:1;
}

/* v178 — Highlight `==text==` markdown extension. Renders as <mark>.
   Peri-tinted at 7% (matches the "less vibrant" reduction applied to sky/lime
   callouts). Inherits text colour so it works in both light and dark themes. */
.recall-answer mark,.fc-answer mark,.fc-callout-body mark,.fc-callout-body-inline mark,
.saq-callout-body mark,
.fc-tab-panel mark,.model-body mark,.card-body mark,.toggle-body mark{
  background:color-mix(in srgb,var(--peri,#7c5cb8) 18%,transparent);
  color:inherit;
  padding:1px 3px;border-radius:3px;
}

/* v178 — Subscript / superscript size + line-height. Browser defaults are
   close but inconsistent across iOS Safari / Chrome; pin them for predictability. */
.recall-answer sub,.fc-answer sub,.fc-callout-body sub,.fc-callout-body-inline sub,
.saq-callout-body sub,
.fc-tab-panel sub,.model-body sub,.card-body sub,.toggle-body sub,
.recall-answer sup,.fc-answer sup,.fc-callout-body sup,.fc-callout-body-inline sup,
.saq-callout-body sup,
.fc-tab-panel sup,.model-body sup,.card-body sup,.toggle-body sup{
  font-size:.72em;line-height:0;
}

/* (3f) Numbered-circle list markers inside any typed callout. The migration
   converts inline "(1) X; (2) Y; (3) Z" prose into ordered-list markdown
   ("1. X\n2. Y\n3. Z"), which marked renders as <ol><li>...</li></ol>. The
   default decimal markers get hidden and replaced with a filled coloured
   circle counter, matching the accent of the parent callout. */
.recall-answer blockquote.callout ol,.fc-answer blockquote.callout ol,
.fc-callout-body blockquote.callout ol,.fc-callout-body-inline blockquote.callout ol,
.saq-callout-body blockquote.callout ol,
.fc-tab-panel blockquote.callout ol,.model-body blockquote.callout ol,
.card-body blockquote.callout ol,.toggle-body blockquote.callout ol{
  list-style:none;padding-left:0;margin:.25em 0;counter-reset:callout-item;
}
.recall-answer blockquote.callout ol > li,.fc-answer blockquote.callout ol > li,
.fc-callout-body blockquote.callout ol > li,.fc-callout-body-inline blockquote.callout ol > li,
.saq-callout-body blockquote.callout ol > li,
.fc-tab-panel blockquote.callout ol > li,.model-body blockquote.callout ol > li,
.card-body blockquote.callout ol > li,.toggle-body blockquote.callout ol > li{
  counter-increment:callout-item;position:relative;
  padding-left:28px;margin:4px 0;
}
.recall-answer blockquote.callout ol > li::before,.fc-answer blockquote.callout ol > li::before,
.fc-callout-body blockquote.callout ol > li::before,.fc-callout-body-inline blockquote.callout ol > li::before,
.saq-callout-body blockquote.callout ol > li::before,
.fc-tab-panel blockquote.callout ol > li::before,.model-body blockquote.callout ol > li::before,
.card-body blockquote.callout ol > li::before,.toggle-body blockquote.callout ol > li::before{
  content:counter(callout-item);
  position:absolute;left:0;top:.15em;
  width:20px;height:20px;line-height:20px;text-align:center;
  border-radius:50%;font-size:.78em;font-weight:600;
  background:var(--callout-accent,var(--peri,#7c5cb8));color:#fff;
}
.recall-answer blockquote.callout-examiner ol > li::before,
.fc-answer blockquote.callout-examiner ol > li::before,
.fc-callout-body blockquote.callout-examiner ol > li::before,
.fc-callout-body-inline blockquote.callout-examiner ol > li::before,
.saq-callout-body blockquote.callout-examiner ol > li::before,
.fc-tab-panel blockquote.callout-examiner ol > li::before,
.model-body blockquote.callout-examiner ol > li::before,
.card-body blockquote.callout-examiner ol > li::before,
.toggle-body blockquote.callout-examiner ol > li::before{background:var(--peri,#7c5cb8)}
.recall-answer blockquote.callout-key ol > li::before,.fc-answer blockquote.callout-key ol > li::before,
.fc-callout-body blockquote.callout-key ol > li::before,.fc-callout-body-inline blockquote.callout-key ol > li::before,
.saq-callout-body blockquote.callout-key ol > li::before,
.fc-tab-panel blockquote.callout-key ol > li::before,.model-body blockquote.callout-key ol > li::before,
.card-body blockquote.callout-key ol > li::before,.toggle-body blockquote.callout-key ol > li::before{
  background:var(--honey,#d4922b)
}
.recall-answer blockquote.callout-definition ol > li::before,
.fc-answer blockquote.callout-definition ol > li::before,
.fc-callout-body blockquote.callout-definition ol > li::before,
.fc-callout-body-inline blockquote.callout-definition ol > li::before,
.saq-callout-body blockquote.callout-definition ol > li::before,
.fc-tab-panel blockquote.callout-definition ol > li::before,
.model-body blockquote.callout-definition ol > li::before,
.card-body blockquote.callout-definition ol > li::before,
.toggle-body blockquote.callout-definition ol > li::before{background:var(--sage,#5e8b6c)}
.recall-answer blockquote.callout-safety ol > li::before,
.fc-answer blockquote.callout-safety ol > li::before,
.fc-callout-body blockquote.callout-safety ol > li::before,
.fc-callout-body-inline blockquote.callout-safety ol > li::before,
.saq-callout-body blockquote.callout-safety ol > li::before,
.fc-tab-panel blockquote.callout-safety ol > li::before,
.model-body blockquote.callout-safety ol > li::before,
.card-body blockquote.callout-safety ol > li::before,
.toggle-body blockquote.callout-safety ol > li::before{background:#c0573a}
/* v178 — circle colours for the six new typed callouts. */
.recall-answer blockquote.callout-pitfall ol > li::before,
.fc-answer blockquote.callout-pitfall ol > li::before,
.fc-callout-body blockquote.callout-pitfall ol > li::before,
.fc-callout-body-inline blockquote.callout-pitfall ol > li::before,
.saq-callout-body blockquote.callout-pitfall ol > li::before,
.fc-tab-panel blockquote.callout-pitfall ol > li::before,
.model-body blockquote.callout-pitfall ol > li::before,
.card-body blockquote.callout-pitfall ol > li::before,
.toggle-body blockquote.callout-pitfall ol > li::before{background:#c0573a}
.recall-answer blockquote.callout-mnemonic ol > li::before,
.fc-answer blockquote.callout-mnemonic ol > li::before,
.fc-callout-body blockquote.callout-mnemonic ol > li::before,
.fc-callout-body-inline blockquote.callout-mnemonic ol > li::before,
.saq-callout-body blockquote.callout-mnemonic ol > li::before,
.fc-tab-panel blockquote.callout-mnemonic ol > li::before,
.model-body blockquote.callout-mnemonic ol > li::before,
.card-body blockquote.callout-mnemonic ol > li::before,
.toggle-body blockquote.callout-mnemonic ol > li::before{background:var(--peri,#7c5cb8)}
.recall-answer blockquote.callout-pearl ol > li::before,
.fc-answer blockquote.callout-pearl ol > li::before,
.fc-callout-body blockquote.callout-pearl ol > li::before,
.fc-callout-body-inline blockquote.callout-pearl ol > li::before,
.saq-callout-body blockquote.callout-pearl ol > li::before,
.fc-tab-panel blockquote.callout-pearl ol > li::before,
.model-body blockquote.callout-pearl ol > li::before,
.card-body blockquote.callout-pearl ol > li::before,
.toggle-body blockquote.callout-pearl ol > li::before{background:var(--sky,#4D8CB0)}
.recall-answer blockquote.callout-equation ol > li::before,
.fc-answer blockquote.callout-equation ol > li::before,
.fc-callout-body blockquote.callout-equation ol > li::before,
.fc-callout-body-inline blockquote.callout-equation ol > li::before,
.saq-callout-body blockquote.callout-equation ol > li::before,
.fc-tab-panel blockquote.callout-equation ol > li::before,
.model-body blockquote.callout-equation ol > li::before,
.card-body blockquote.callout-equation ol > li::before,
.toggle-body blockquote.callout-equation ol > li::before{background:var(--saltbush, #5E6670)}
.recall-answer blockquote.callout-mechanism ol > li::before,
.fc-answer blockquote.callout-mechanism ol > li::before,
.fc-callout-body blockquote.callout-mechanism ol > li::before,
.fc-callout-body-inline blockquote.callout-mechanism ol > li::before,
.saq-callout-body blockquote.callout-mechanism ol > li::before,
.fc-tab-panel blockquote.callout-mechanism ol > li::before,
.model-body blockquote.callout-mechanism ol > li::before,
.card-body blockquote.callout-mechanism ol > li::before,
.toggle-body blockquote.callout-mechanism ol > li::before{background:var(--sky,#4D8CB0)}
.recall-answer blockquote.callout-heuristic ol > li::before,
.fc-answer blockquote.callout-heuristic ol > li::before,
.fc-callout-body blockquote.callout-heuristic ol > li::before,
.fc-callout-body-inline blockquote.callout-heuristic ol > li::before,
.saq-callout-body blockquote.callout-heuristic ol > li::before,
.fc-tab-panel blockquote.callout-heuristic ol > li::before,
.model-body blockquote.callout-heuristic ol > li::before,
.card-body blockquote.callout-heuristic ol > li::before,
.toggle-body blockquote.callout-heuristic ol > li::before{background:var(--honey,#d4922b)}

/* ════════════════════════════════════════════════════════════════════════
   v179 — Drug-card chip-section schema.
   Applied to blockquotes that classifyCallouts/applyV2Section tag with
   `.section` (when ≥2 V2_SECTION_MAP labels appear in a card) OR directly
   by _renderDrugPreview / _appendPharmaFieldSection for single-field leaves.
   Each section carries a custom --section-color CSS var.
   ════════════════════════════════════════════════════════════════════════ */
.recall-answer blockquote.section,.fc-answer blockquote.section,
.fc-callout-body blockquote.section,.fc-callout-body-inline blockquote.section,
.saq-callout-body blockquote.section,
.fc-tab-panel blockquote.section,.model-body blockquote.section,
.card-body blockquote.section,.toggle-body blockquote.section{
  position:relative;margin:.55em 0;padding:8px 12px 10px;
  border-left:3px solid var(--section-color,var(--accent));
  border-radius:0 6px 6px 0;
  background:color-mix(in srgb, var(--section-color,var(--accent)) 6%, var(--surface));
  color:var(--text);font-style:normal;quotes:none;
}
.recall-answer blockquote.section::before,.fc-answer blockquote.section::before,
.fc-callout-body blockquote.section::before,.fc-callout-body-inline blockquote.section::before,
.saq-callout-body blockquote.section::before,
.fc-tab-panel blockquote.section::before,.model-body blockquote.section::before,
.card-body blockquote.section::before,.toggle-body blockquote.section::before{content:none}

/* Chip header — pill sitting above the section body. applyV2Section +
   _appendPharmaFieldSection both place .section-chip as the FIRST direct
   child of blockquote.section, so it stacks above siblings. */
.section-chip{
  display:inline-block;margin:0 0 6px;padding:2px 10px;
  font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--section-color,var(--accent));
  background:color-mix(in srgb, var(--section-color,var(--accent)) 14%, var(--surface));
  border:1px solid color-mix(in srgb, var(--section-color,var(--accent)) 28%, var(--surface));
  border-radius:var(--radius-pill);line-height:1.4;white-space:nowrap;
}
/* Body content directly after the chip — collapse top margin */
blockquote.section > .section-chip + p,
blockquote.section > .section-chip + ul,
blockquote.section > .section-chip + ol,
blockquote.section > .section-chip + blockquote,
blockquote.section > .section-chip + div{margin-top:0}
blockquote.section > p:first-child{margin-top:0}

/* drug-section__body — inner wrapper inside _renderDrugPreview /
   _appendPharmaFieldSection so CardBody-rendered prose has its own container. */
blockquote.section > .drug-section__body{margin-top:2px}
blockquote.section > .drug-section__body > p:first-child{margin-top:0}
blockquote.section > .drug-section__body > blockquote:first-child{margin-top:0}

/* Nested tier-2 chips (CVS / GU / RS inside pd_adverse;
   Class / Indications / Dose inside class_indications_dose).
   Reduce vertical rhythm so nested sections stack tightly. */
blockquote.section blockquote.section{margin:.4em 0;padding:6px 10px 8px}
blockquote.section blockquote.section .section-chip{font-size:10px;padding:1px 8px}

/* PK / Dose two-column definition grid. applyV2Section + enhanceDrugFieldBody
   convert `<li><strong>Field</strong> value</li>` into spans .field-name +
   .field-value. CSS lays them out as a 2-col grid. */
blockquote.section[data-section="pk"] ul,
blockquote.section[data-section="dose"] ul,
ul[data-field-grid="pk"],ul[data-field-grid="dose"]{
  list-style:none;padding:0;margin:.4em 0 .2em;
  display:grid;grid-template-columns:max-content 1fr;gap:2px 12px;
}
blockquote.section[data-section="pk"] ul li,
blockquote.section[data-section="dose"] ul li,
ul[data-field-grid="pk"] li,ul[data-field-grid="dose"] li{display:contents;margin:0}
blockquote.section .field-name,ul[data-field-grid] .field-name{
  font-weight:600;color:var(--section-color,var(--accent));
  white-space:nowrap;align-self:start;
}
blockquote.section .field-value,ul[data-field-grid] .field-value{
  color:var(--text);align-self:start;
}

/* Mechanism arrow flow — chipMechanismFlows turns `A → B → C` chains into
   inline .mech-flow with colored connectors between plain step text. */
.mech-flow{display:inline}
.mech-step{color:inherit}
.mech-arrow{color:var(--section-color,#7c5cb8);font-weight:700;margin:0 .15em}

/* §4D T6 — taxonomy single line, ellipsis on overflow. The link inherits
   the truncation; tooltip surfaces the full path on hover/focus. */
.recall-tag{font-size:var(--font-size-sm);color:var(--text-muted);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;min-width:0}
.recall-tag a{color:var(--text-muted);text-decoration:none;border-bottom:1px dotted var(--text-faint);max-width:100%;display:inline-block;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom}
.recall-tag a:hover{color:var(--accent);border-bottom-color:var(--accent)}

/* Today-fix v2 — recall topic sub-header. Anchors to its .recall-group
   parent section width (NOT the page width). Sub-header sits at the
   top of each group; the masonry .recall-group-cards underneath
   matches the same width.
   Sub-header is clickable: opens Notion topic URL or modal fallback. */
.recall-group-header{
  display:flex;align-items:center;gap:8px;
  font-size:var(--font-size-xs);font-weight:600;color:var(--text-muted);
  text-transform:uppercase;letter-spacing:0.05em;
  padding:8px 0 6px;margin:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  text-decoration:none;
  cursor:pointer;
  transition:color var(--duration-sm);
}
/* v172 — On narrow viewports the topic heading was clipped mid-word
   ("D3I · NORMAL PRESSURE AND FLOW PAT…"). Allow wrap so the full
   chapter name is readable. (Issue #14) */
@media(max-width:600px){
  .recall-group-header{
    white-space:normal;word-break:break-word;
    line-height:1.35;text-overflow:clip;
  }
}
.recall-group-header:hover{color:var(--accent)}
.recall-group-header::before{
  content:"";flex:0 0 12px;height:1px;background:var(--border);transition:background var(--duration-sm);
}
.recall-group-header::after{
  content:"";flex:1;height:1px;background:var(--border);transition:background var(--duration-sm);
}
.recall-group-header:hover::before,
.recall-group-header:hover::after{background:var(--accent)}
.recall-card--grouped .recall-tag{display:none}

/* §4F Visually hidden but screen-reader accessible (utility). */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* Predict row */
/* Self-confidence scale (was 1-5 numeric pips). Five Lucide face icons
   from "guessing" → "certain" with semantic colour ramp + hover labels.
   Stored value is still 1–5 for FSRS compatibility. */
.predict-row{display:flex;align-items:center;gap:9px;font-size:var(--font-size-sm);color:var(--text-muted);flex-wrap:wrap}
.predict-row .predict-label{text-transform:uppercase;letter-spacing:0.04em;font-weight:600;font-size:var(--font-size-xs)}
.predict-dots{display:flex;gap:5px}
.predict-dot{
  width:32px;height:32px;border:1.5px solid var(--border);background:var(--surface);
  border-radius:var(--radius-sm);cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;padding:0;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);color:var(--text-muted);
}
.predict-dot .icn{width:18px;height:18px}
.predict-dot:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm)}
/* Per-level resting tints — subtle so unselected stays calm */
.predict-dot[data-pick="1"]:hover{border-color:var(--red);color:var(--red)}
.predict-dot[data-pick="2"]:hover{border-color:var(--orange);color:var(--orange)}
.predict-dot[data-pick="3"]:hover{border-color:var(--amber);color:var(--honey-deep)}
.predict-dot[data-pick="4"]:hover{border-color:var(--green);color:var(--green)}
.predict-dot[data-pick="5"]:hover{border-color:var(--accent);color:var(--accent)}
/* Selected state — fully colour-filled per level */
.predict-dot.selected{color:white}
.predict-dot.selected[data-pick="1"]{background:var(--red);border-color:var(--red)}
.predict-dot.selected[data-pick="2"]{background:var(--orange);border-color:var(--orange)}
.predict-dot.selected[data-pick="3"]{background:var(--amber);border-color:var(--amber);color:var(--honey-deep)}
.predict-dot.selected[data-pick="4"]{background:var(--green);border-color:var(--green)}
.predict-dot.selected[data-pick="5"]{background:var(--accent);border-color:var(--accent)}
.predict-meta{font-size:var(--font-size-xs);color:var(--text-faint);font-style:italic}

.recall-actions{display:flex;gap:6px;margin-top:auto;flex-wrap:wrap;--grade-bar-h:83px}
.recall-actions button{
  padding:8px 13px;border:1.5px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);
  cursor:pointer;font-size:var(--font-size-md);color:var(--text);font-weight:600;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.recall-actions button:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.recall-actions button:active{transform:scale(0.97)}
/* patch-008 — Show Answer is the quiet ghost; the three grade buttons
   carry the colour ramp:
   • r-grade--missed   (1) red          — Missed; opens the miss-tag overlay
   • r-grade--honed    (3) green  — Honed (var(--fc-badge-honed))
   • r-grade--mastered (4) violet — Mastered (var(--fc-badge-mastered))
   Review is unchanged (advanced affordance). */
.recall-actions button.show{flex:1;color:var(--text);border-color:var(--border);background:var(--surface)}
.recall-actions button.show:hover{color:var(--accent);border-color:var(--accent);background:var(--surface)}
.recall-actions button.r-grade{flex:1}
/* Inverted-T (grid): Mastered spans both columns in row-1; Missed/Honed
   fill row-2 col-by-col. Height locked to --grade-bar-h so swapping to
   the miss-tag overlay causes zero vertical displacement.
   AUDIT-2026-05-06 #26 — gap:0 + inner-radius:0 makes the inverted-T
   read as one unified segmented control instead of three disjoint
   pills. Outer corners stay rounded; the active-collapse state (below)
   restores full radius on the lone visible button. */
.recall-actions .post-reveal{
  display:grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;
  gap:0;width:100%;height:var(--grade-bar-h,83px);box-sizing:border-box;
  transition:height .15s ease;
}
.recall-actions .post-reveal .r-grade{border-radius:0}
.recall-actions .post-reveal .r-grade:hover{transform:none}
.recall-actions .post-reveal .r-grade--mastered{
  grid-column:1/-1;grid-row:1;
  border-top-left-radius:10px;border-top-right-radius:10px;
}
.recall-actions .post-reveal .r-grade--missed  {
  grid-column:1;grid-row:2;
  border-bottom-left-radius:10px;
}
.recall-actions .post-reveal .r-grade--honed   {
  grid-column:2;grid-row:2;
  border-bottom-right-radius:10px;
}
/* Active collapse: flatten to single full-width cell at half height.
   Height halves toward the bottom edge — top row folds away. */
.recall-actions .post-reveal:has(.r-grade.active){
  grid-template-rows:1fr;grid-template-columns:1fr;
  height:calc(var(--grade-bar-h,83px) / 2);
}
.recall-actions .post-reveal:has(.r-grade.active) .r-grade.active{
  grid-column:1/-1;grid-row:1;
  /* Single visible button gets full radius back (overrides the inverted-T
     selective-corner rules above). AUDIT-2026-05-06 #26. */
  border-radius:var(--radius-md);
}
/* Resting tint — each grade carries its identity colour at low saturation */
/* #2 — INVERTED: ungraded=filled (eye-catching), graded=outline (recedes) */
/* Ungraded = solid fill (eye-catching). Uses --fc-badge-* for all three so
   the palette is mode-invariant — --red shifts to salmon in dark mode. */
.recall-actions button.r-grade--missed   {background:var(--coral-vivid);    border-color:var(--coral-vivid);    color:#fff}
.recall-actions button.r-grade--hazy     {background:var(--grade-hazy);   border-color:var(--grade-hazy);  color:var(--grade-hazy-text)} /* amber MUST use dark text */
.recall-actions button.r-grade--honed    {background:var(--grade-honed);  border-color:var(--grade-honed);  color:#fff}
.recall-actions button.r-grade--mastered {background:var(--grade-mastered);border-color:var(--grade-mastered);color:#fff}
/* Hover — theme-aware tint via --grade-*-hover tokens (see :root + html.dark
   §1 grade aliases). Light mode darkens; dark mode lightens — keeps the
   chip visible against the active page bg in either theme. */
.recall-actions button.r-grade--missed:hover   {background:var(--grade-missed-hover);  border-color:var(--coral-vivid)}
.recall-actions button.r-grade--honed:hover    {background:var(--grade-honed-hover);   border-color:var(--grade-honed)}
.recall-actions button.r-grade--mastered:hover {background:var(--grade-mastered-hover);border-color:var(--grade-mastered)}
/* Graded/active = outline (task done, recedes) */
.recall-actions button.r-grade--missed.active   {background:color-mix(in srgb,var(--coral-vivid) 10%,var(--surface));border-color:var(--coral-vivid);color:var(--coral-vivid)}
.recall-actions button.r-grade--honed.active    {background:color-mix(in srgb,var(--grade-honed) 10%,var(--surface));border-color:var(--grade-honed);color:var(--grade-honed)}
.recall-actions button.r-grade--mastered.active {background:color-mix(in srgb,var(--grade-mastered) 10%,var(--surface));border-color:var(--grade-mastered);color:var(--grade-mastered)}
.recall-actions:has(.r-grade.active) .r-grade:not(.active){display:none}
.recall-actions:has(.r-grade.selected) .r-grade:not(.selected){display:none}
/* selected mirrors active: outline */
.r-grade--missed.selected  {background:color-mix(in srgb,var(--coral-vivid) 10%,var(--surface));border-color:var(--coral-vivid);color:var(--coral-vivid)}
.r-grade--honed.selected   {background:color-mix(in srgb,var(--grade-honed) 10%,var(--surface));border-color:var(--grade-honed);color:var(--grade-honed)}
.r-grade--mastered.selected{background:color-mix(in srgb,var(--grade-mastered) 10%,var(--surface));border-color:var(--grade-mastered);color:var(--grade-mastered)}
.fc-grade-btns{display:flex;gap:0;margin-bottom:0}
.fc-grade-btns:has(.fc-grade-btn.active) .fc-grade-btn:not(.active){display:none}
/* WS4 (2026-05-05): .fact > .recall-actions DEAD CODE DELETED. .fact class no longer emitted. */
.recall-actions button.review{flex:0 0 auto;background:transparent;color:var(--text-muted)}
.recall-actions button.review:hover,.recall-actions button.review.active{color:var(--accent);border-color:var(--accent);background:var(--accent-soft)}
.recall-card .post-reveal{display:none}
.recall-card.revealed .show{display:none}
.recall-card.revealed .post-reveal{display:grid}

/* --- Today-fix v3 — Miss-tag overlay (recovery-based: Forgot / Almost
   / Slipped). Replaces the old .miss-tag-row chip cluster.
   Visible only when the recall card is in .tag-open (i.e., the user
   tapped Missed). When open, the post-reveal Got it/Missed pair hides
   and the overlay fills the action area.
   Surface treatment: coral-tinted bg + 2px coral border, matching the
   §4D 'missed' identity. Three large icon buttons in a 3x1 row. */
/* Card-redesign 2026-05-05 IMPROVE — flat in-place transform of the inverted-T
   into the miss-tag selector. Drops the coral outline + bg so the overlay sits
   inside the existing footer chrome rather than reading as a separate box on top
   of it. The header text + button outlines still carry the coral identity. */
.miss-tag-overlay{
  display:none;
  width:100%;
  background:transparent;
  border:0;
  border-radius:0;
  padding:0;
  animation:fadeIn .18s ease both;
}
.recall-card.tag-open .miss-tag-overlay{display:flex;flex-direction:column;height:var(--grade-bar-h,83px);box-sizing:border-box}
.recall-card.tag-open .post-reveal{display:none}
.recall-card.tag-collapsed .miss-tag-overlay{display:block;background:transparent;border:none;padding:0;animation:none;height:auto}
.recall-card.tag-collapsed .miss-tag-header,
.recall-card.tag-collapsed .miss-tag-grid{display:none}
.recall-card.tag-collapsed .post-reveal{display:none}
/* Today SAQ / card — confidenceRow() produces .post-reveal +
   .miss-tag-overlay siblings inside .recall-actions, matching recall cards
   exactly. Tag-open/collapsed rules are identical to the recall pattern.
   WS4 (2026-05-05): .fact selectors removed (dead); .card added alongside
   .saq-card for unified primitive coverage. */
.saq-card .post-reveal,.card .post-reveal,.axiom .post-reveal,.pharma-card .post-reveal,.fc-card .post-reveal{display:grid}
.saq-card.tag-open .miss-tag-overlay,.card.tag-open .miss-tag-overlay,.axiom.tag-open .miss-tag-overlay,.pharma-card.tag-open .miss-tag-overlay,.fc-card.tag-open .miss-tag-overlay{display:flex;flex-direction:column;height:var(--grade-bar-h,83px);box-sizing:border-box}
.saq-card.tag-open .post-reveal,.card.tag-open .post-reveal,.axiom.tag-open .post-reveal,.pharma-card.tag-open .post-reveal,.fc-card.tag-open .post-reveal{display:none}
.saq-card.tag-collapsed .miss-tag-overlay,.card.tag-collapsed .miss-tag-overlay,.axiom.tag-collapsed .miss-tag-overlay,.pharma-card.tag-collapsed .miss-tag-overlay,.fc-card.tag-collapsed .miss-tag-overlay{display:block;background:transparent;border:none;padding:0;animation:none;height:auto}
.saq-card.tag-collapsed .miss-tag-header,.card.tag-collapsed .miss-tag-header,.axiom.tag-collapsed .miss-tag-header,.pharma-card.tag-collapsed .miss-tag-header,.fc-card.tag-collapsed .miss-tag-header,
.saq-card.tag-collapsed .miss-tag-grid,.card.tag-collapsed .miss-tag-grid,.axiom.tag-collapsed .miss-tag-grid,.pharma-card.tag-collapsed .miss-tag-grid,.fc-card.tag-collapsed .miss-tag-grid{display:none}
.saq-card.tag-collapsed .post-reveal,.card.tag-collapsed .post-reveal,.axiom.tag-collapsed .post-reveal,.pharma-card.tag-collapsed .post-reveal,.fc-card.tag-collapsed .post-reveal{display:none}
.saq-card.tag-collapsed .miss-tag-collapsed,.card.tag-collapsed .miss-tag-collapsed,.axiom.tag-collapsed .miss-tag-collapsed,.pharma-card.tag-collapsed .miss-tag-collapsed,.fc-card.tag-collapsed .miss-tag-collapsed{display:flex}

/* Phase 1.3 — Force-tag refusal shake. Applied when user hits Escape on a
   tag-open card while force-tag is on and no tag has been picked yet. */
@keyframes tagShakeKf {
  0%,100% { transform: translateX(0); }
  20%,60% { transform: translateX(-3px); }
  40%,80% { transform: translateX(3px); }
}
.tag-shake{animation:tagShakeKf .42s cubic-bezier(.36,.07,.19,.97)}
@media (prefers-reduced-motion: reduce){
  .tag-shake{animation:none;outline:2px solid var(--coral);outline-offset:-2px}
}

.miss-tag-header{
  display:flex;align-items:center;justify-content:center;gap:5px;
  font-size:var(--font-size-sm);font-weight:600;color:var(--coral);
  margin-bottom:7px;
}
.miss-tag-header-icon{width:13px;height:13px;flex-shrink:0}
.miss-tag-grid{display:flex;gap:6px;flex:1;align-items:stretch}
/* miss-tag-btn: outline style (consistent with btn--ghost taxonomy). Was filled
   coral — changed to outline so it reads as an interactive choice, not a status badge.
   The selected state was already outline; now both states share the same visual language.
   Specificity note: .recall-actions button sets background:var(--surface) at (0,1,1).
   Override with (0,2,0) to keep miss-tag transparent in all contexts. */
.miss-tag-btn{
  position:relative;
  flex:1;min-width:0;
  /* Card-redesign 2026-05-05 IMPROVE — match grade button height (44px floor)
     so miss-tag selector visually replaces the inverted-T at the same scale. */
  padding:12px 6px;min-height:44px;
  border:1.5px solid var(--coral-vivid);
  background:transparent;
  border-radius:var(--radius-sm);
  cursor:pointer;
  color:var(--coral-vivid);
  font-family:inherit;font-size:var(--font-size-md);font-weight:600;
  display:inline-flex;flex-direction:row;align-items:center;justify-content:center;
  gap:6px;min-height:0;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
/* specificity bump — beats .recall-actions button (0,1,1) */
.recall-actions .miss-tag-btn,.miss-tag-overlay .miss-tag-btn{background:transparent;border-color:var(--coral-vivid);color:var(--coral-vivid)}
.miss-tag-btn svg{width:16px;height:16px;flex-shrink:0}
.miss-tag-label{font-size:var(--font-size-md);font-weight:600;color:inherit}
.miss-tag-btn.selected .miss-tag-label{color:inherit}
.miss-tag-btn:hover{
  transform:translateY(-1px);
  background:color-mix(in srgb,var(--coral-vivid) 12%,transparent);
  border-color:var(--coral-vivid);
  color:var(--coral-vivid);
}
/* #2 — miss-tag-btn.selected=outline (graded, recedes) — transparent bg so
   the outline reads correctly on both --surface (Today) and --focus-overlay-bg (cinema). */
.miss-tag-btn.selected{
  background:transparent;color:var(--coral-vivid);
  border-color:var(--coral-vivid);
}
.miss-tag-shortcut{
  position:absolute;top:4px;right:6px;
  font-size:9px;font-weight:600;
  color:color-mix(in srgb,var(--coral-lift) 70%,transparent);
  font-variant-numeric:tabular-nums;
  pointer-events:none;
  /* patch-007 — shortcut indicator follows the shift-to-reveal policy.
     Hidden by default; visible only while Shift is held. */
  opacity:0;
  transition:opacity .15s ease;
}
body.shift-armed .miss-tag-shortcut{opacity:1}
.miss-tag-btn.selected .miss-tag-shortcut{color:color-mix(in srgb,var(--bg) 70%,transparent)}
@media (prefers-reduced-motion: reduce){.miss-tag-shortcut{transition:none}}

/* Cinema-mode pass 2026-05-26 — Hazy + Mixed are grade-2, so they read HONEY to
   match the grade-2 identity; Blank stays coral (grade 1). App-wide via the
   data-tag attribute (Today / Focus / Library). --honey-deep is the contrast-safe
   honey and flips with theme, matching the card surface in both modes. */
.miss-tag-btn[data-tag="hazy"],
.miss-tag-btn[data-tag="mixed"],
.recall-actions .miss-tag-btn[data-tag="hazy"],
.recall-actions .miss-tag-btn[data-tag="mixed"],
.miss-tag-overlay .miss-tag-btn[data-tag="hazy"],
.miss-tag-overlay .miss-tag-btn[data-tag="mixed"]{
  border-color:var(--honey-deep);
  color:var(--honey-deep);
}
.miss-tag-btn[data-tag="hazy"]:hover,
.miss-tag-btn[data-tag="mixed"]:hover{
  background:color-mix(in srgb,var(--honey-deep) 12%,transparent);
  border-color:var(--honey-deep);
  color:var(--honey-deep);
}
.miss-tag-btn[data-tag="hazy"].selected,
.miss-tag-btn[data-tag="mixed"].selected{
  border-color:var(--honey-deep);
  color:var(--honey-deep);
}
.miss-tag-btn[data-tag="hazy"] .miss-tag-shortcut,
.miss-tag-btn[data-tag="mixed"] .miss-tag-shortcut{
  color:color-mix(in srgb,var(--honey-deep) 70%,transparent);
}

/* Pulse animation — 240ms scale + brightness flash. Triggered by
   tagMiss() applying .miss-tag-pulse for one frame. */
@keyframes missTagPulse{
  0%  {transform:scale(1)}
  45% {transform:scale(1.12);filter:brightness(1.18)}
  100%{transform:scale(1);filter:none}
}
.miss-tag-btn.miss-tag-pulse{animation:missTagPulse .24s var(--ease-spring)}
@media(prefers-reduced-motion:reduce){.miss-tag-btn.miss-tag-pulse{animation:fadeIn var(--duration-sm) ease}}

/* Today-fix v4 — collapsed pill (Today only). Hidden by default;
   .recall-card.tag-collapsed reveals it (and the Today-only branch
   of buildMissTagOverlay only appends it for non-focus surfaces).
   Solid coral pill, centred 'Missed' + soft chip showing the chosen
   tag. Click anywhere → tap-to-change uncollapses the overlay.
   Selectors are scoped under .recall-actions so they outrank
   .recall-actions button (0,1,1) and the coral fill actually
   applies — bare .miss-tag-collapsed (0,1,0) lost the cascade. */
.recall-actions .miss-tag-collapsed{
  display:none;
  width:100%;height:42px;
  padding:0;
  border:none;border-radius:var(--radius-md);
  background:var(--coral-vivid);color:white;
  font-family:inherit;font-size:var(--font-size-md);font-weight:500;
  cursor:pointer;
  align-items:center;justify-content:center;gap:10px;
  transition:filter var(--duration-sm),transform var(--duration-sm);
  animation:fadeIn .18s ease both;
}
.recall-actions .miss-tag-collapsed:hover{
  filter:brightness(1.06);transform:none;box-shadow:none;
}
.recall-actions .miss-tag-collapsed:active{transform:scale(0.99)}
.recall-card.tag-collapsed .miss-tag-collapsed{display:flex}
.recall-actions .miss-tag-collapsed .mtc-x{font-weight:500;opacity:0.9;color:white}
.recall-actions .miss-tag-collapsed .mtc-label-l{font-weight:500;letter-spacing:0.2px;color:white}
.recall-actions .miss-tag-collapsed .mtc-chip{
  display:inline-flex;align-items:center;gap:6px;
  background:rgba(255,255,255,0.20);
  color:white;
  padding:5px 12px;border-radius:var(--radius-pill);
  font-size:var(--font-size-sm);font-weight:500;letter-spacing:0.2px;
}
.recall-actions .miss-tag-collapsed .mtc-chip svg{width:14px;height:14px;flex-shrink:0;color:white}

/* Focus-mode variant — bigger icons + bigger header so the overlay
   reads at the higher takeover scale. */
.miss-tag-overlay--focus{
  border-radius:0;border-left:none;border-right:none;
  padding:18px 20px;
}
.miss-tag-overlay--focus .miss-tag-header{font-size:var(--font-size-lg);margin-bottom:14px}
.miss-tag-overlay--focus .miss-tag-btn svg{width:18px;height:18px}
.miss-tag-overlay--focus .miss-tag-label{font-size:var(--font-size-lg)}
.miss-tag-overlay--focus .miss-tag-shortcut{font-size:var(--font-size-2xs);top:6px;right:8px}

/* Ring fill micro-interaction */
@keyframes ringFill{0%{transform:scale(1)}50%{transform:scale(1.15)}100%{transform:scale(1)}}
.ring-pop{animation:ringFill .25s ease-out}
@media (prefers-reduced-motion: reduce){.ring-pop{animation:none}}

/* Today-fix v4 — Today undo button. Mirrors the focus-mode undo
   visual but gets a peri tint (rewind = different intent from coral
   miss). Hidden via [hidden] attribute when state.todayUndo is
   empty; JS toggles it after the first grade lands in a session.
   On click, the entire viewport gets a single var(--duration-lg) peri veil
   pulse so the rewind feels acknowledged across the whole screen. */
.today-undo-btn[hidden]{display:none}
.today-undo-btn{color:var(--peri-deep);position:relative;animation:fadeIn .18s ease both}
.today-undo-btn:hover{background:var(--peri-fill);color:var(--peri)}

/* Today-fix v4b — veil flash on Today undo. Asymmetric pulse — fast
   ramp in (28% of duration), slower exhale (sustained mid-opacity at
   65%, fade to 0 by 100%). 440ms total. Background uses a radial
   gradient that's punchier at the centre + softer at the edges so
   the rewind reads as 'centred event' rather than a flat wash. */
@keyframes todayUndoVeilPulse{
  0%   {opacity:0;             transform:scale(1.04)}
  28%  {opacity:1;             transform:scale(1)}
  65%  {opacity:0.6;           transform:scale(1)}
  100% {opacity:0;             transform:scale(0.98)}
}
.today-undo-veil{
  position:fixed;inset:0;z-index:250; /* above tab bar (200) */
  background:radial-gradient(ellipse at center,
    color-mix(in srgb,var(--peri) 38%,transparent) 0%,
    color-mix(in srgb,var(--peri) 22%,transparent) 60%,
    color-mix(in srgb,var(--peri) 8%,transparent) 100%);
  pointer-events:none;
  transform-origin:center;
  animation:todayUndoVeilPulse .44s cubic-bezier(.4,0,.2,1) both;
}
@media(prefers-reduced-motion:reduce){
  .today-undo-veil{animation:fadeIn .15s ease both;background:color-mix(in srgb,var(--peri) 14%,transparent);transform:none}
}

/* --- SAQ card system (post-v9.1 audit redesign + saqflow rewrite) ---
   Sprint J: two-element structure (.saq.saq-card outer + .saq-card-face
   inner) merged into a single element with all classes combined.
   The .saq rules below keep the transparent positioning behaviour from
   the old outer wrapper; .saq-card-face rules carry the visual surface. */
.saq{
  position:relative;
  background:transparent;
  border:none;
  border-radius:0;
  transition:none;
}
.saq:hover{box-shadow:none}
.saq-question{font-weight:500;font-size:var(--font-size-xl);line-height:1.45;margin-bottom:0}
.saq-meta{font-size:var(--font-size-sm);color:var(--text-muted);margin-bottom:14px;display:flex;gap:6px;flex-wrap:wrap;align-items:center;padding-right:32px}
.pill{background:var(--surface-alt);padding:2px 8px;border-radius:var(--btn-radius);font-size:var(--font-size-xs);font-weight:500}
.pill-low{background:var(--red-bg);color:var(--red);font-weight:600}
.pill-mid{background:var(--amber-bg);color:var(--honey-deep);font-weight:600}
html.dark .pill-mid{color:var(--amber)}
.pill-high{background:var(--green-bg);color:var(--green);font-weight:600}

/* Flip-card scaffolding — grid-stacked faces. Both faces occupy the same
   1×1 grid cell, so the .saq-card-inner intrinsic height = max(front,
   back) content height. Cards GROW with content; never an internal
   scroll bar. backface-visibility hides the inactive face visually
   without removing its layout contribution, which is what makes the
   stacked-grid trick keep both heights in sync.
   Post-audit fix: the previous absolute-positioned + overflow-y:auto
   approach clipped long callout bodies behind a scroll bar. Grid
   stacking ditches both. */
.saq-card{
  margin:0;
  padding:0;
  position:relative; /* needed for absolute-positioned flag button */
}
/* Belt-and-suspenders: hide Show Answer btn via CSS on revealed state */
.saq-card.revealed .saq-answer-btn{display:none}
/* patch-007 — Today-tab SAQ now uses a drop-down reveal instead of a 3D
   flip. The header stays anchored; .saq-reveal expands below on .revealed. */
.saq-reveal{display:none}
.saq-card.revealed .saq-reveal{
  display:flex;flex-direction:column;gap:14px;margin-top:14px;
  animation:fcRevealAnswerIn var(--duration-lg) var(--ease-out) both;
}
@media(prefers-reduced-motion:reduce){
  .saq-card.revealed .saq-reveal{animation:fadeIn .15s ease both}
}
/* WS4 (2026-05-05): .saq-card-inner{display:contents} DEAD CODE DELETED.
   Vestigial flip-scaffolding wrapper — no JS emits .saq-card-inner. */
/* Each face carries the full visual treatment (bg + border + radius +
   peri left-stripe) so when the inner rotates, the whole frame rotates
   with it. backface-visibility hides the inactive face.
   Today-fix #8 — accent switched from var(--accent) (sage) to var(--peri)
   so SAQ identity is consistent with §4E and the focus mode SAQ card.
   patch-007 — SAQ identity migrated peri → indigo → honey (final, H1 swap).
   Peri retained for back-face Model Answer callout. Indigo took over Routine. */
.saq-card-face{
  grid-area:1/1;
  background:color-mix(in srgb,var(--rose) var(--card-tint-light),var(--surface-alt2)); /* WS11: --honey→--rose */
  border:1px solid var(--border);
  border-radius:var(--radius);
  /* Card-redesign IMPROVE: deeper stripe. */
  border-left:var(--card-stripe-width) solid var(--rose-deep);
  padding:var(--card-padding-block) var(--card-padding-inline);
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
  display:flex;flex-direction:column;
  /* WS4 (Q3): min-height:240 dropped. Short SAQs no longer need the
     floor now that Today uses a drop-down reveal (not a 3D flip).
     Skeleton already has its own 240px floor for the loading state. */
  box-shadow:var(--card-shadow);
  transition:background var(--duration-sm) var(--ease-out),border-color var(--duration-sm) var(--ease-out),box-shadow var(--duration-sm) var(--ease-out),transform var(--duration-sm) var(--ease-out);
}
.saq-card-face:hover{box-shadow:var(--card-shadow-hover)}
/* patch-007 — Today SAQ flip retired in favour of drop-down. The .saq-card-front
   / .saq-card-back / .saq-back-head / .saq-flipback-btn / .saq-back-q rules
   here have been removed; the new drop-down rules live near .saq-reveal above.
   Removed: ~14 lines of CSS that no DOM still creates. */
.saq-card .saq-question{font-size:var(--font-size-xl);line-height:1.45;margin:4px 0 12px}

.saq-answer-btn{
  margin-top:auto;align-self:stretch;
  padding:12px 22px;border:none;border-radius:var(--radius-md);
  background:var(--accent);color:var(--accent-on);
  font-size:var(--font-size-lg);font-weight:700;font-family:inherit;cursor:pointer;
  box-shadow:0 2px 0 var(--accent-pressed);transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
}
.saq-answer-btn:hover{transform:translateY(-1px);box-shadow:var(--shadow-glow)}
.saq-answer-btn:active{transform:translateY(1px);box-shadow:0 1px 0 var(--accent-pressed)}

/* Today-fix v2 — Continuous-outline pattern (replaces fill + left-stripe).
   Active button: 2px coloured border on all sides, no background fill.
   Content panel: 2px coloured border on all sides matching the active
   button's colour. The two pieces visually bind because their borders
   share the same colour at the same width. Inactive buttons keep a
   neutral border so the active state stands out clearly. */
/* Connected-tab toggle — tabs span full content width (flex:1), active tab
   border "droops" into the panel below via border-bottom erase trick:
   unified panel: row (top half) + bodies (bottom half) share one continuous
   border. No per-button border; no hard rectangle on the active tab.
   Active tab bg matches the body below → seamless colour join. */
/* Unified panel: outer border wraps the row+bodies as one shape. */
.saq-callout-wrap{
  border:1.5px solid var(--border);
  border-radius:var(--radius-sm);
  overflow:hidden;
  margin-bottom:14px;
}
.saq-callout-row{display:flex;border-bottom:1.5px solid var(--border)}
.saq-callout-btn{
  flex:1;min-width:0;
  padding:9px 8px 10px;
  border:none;border-right:1.5px solid var(--border);
  background:color-mix(in srgb,var(--surface-alt) 55%,var(--surface));
  color:var(--text-muted);font-size:var(--font-size-md);font-weight:600;font-family:inherit;
  cursor:pointer;
  transition:background var(--duration-sm),color var(--duration-sm);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.saq-callout-btn:last-child{border-right:none}
.saq-callout-btn:hover{background:var(--surface-alt);color:var(--text)}
.saq-callout-btn:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--accent)}
.saq-callout-btn--sage.active {background:color-mix(in srgb,var(--sage)  10%,var(--surface));color:var(--sage-deep)}
.saq-callout-btn--peri.active {background:color-mix(in srgb,var(--peri)  10%,var(--surface));color:var(--peri-deep)}
.saq-callout-btn--honey.active{background:color-mix(in srgb,var(--honey) 10%,var(--surface));color:var(--honey-deep)}
.saq-callout-body{
  font-size:var(--font-size-md);line-height:1.55;color:var(--text);
  background:var(--surface);
  padding:12px 14px;
  animation:fadeIn .18s ease both;
}
.saq-callout-body[hidden]{display:none}
.saq-callout-body--sage {background:color-mix(in srgb,var(--sage)  10%,var(--surface))}
.saq-callout-body--peri {background:color-mix(in srgb,var(--peri)  10%,var(--surface))}
.saq-callout-body--honey{background:color-mix(in srgb,var(--honey) 10%,var(--surface))}
.saq-callout-body p,
.fc-tab-panel p{margin:6px 0}
.saq-callout-body p:first-child,
.fc-tab-panel p:first-child{margin-top:0}
.saq-callout-body ul,
.fc-tab-panel ul{margin:6px 0;padding-left:18px}
.saq-callout-body h1,
.fc-tab-panel h1,.saq-callout-body h2,.fc-tab-panel h2,.saq-callout-body h3,.fc-tab-panel h3{font-size:var(--font-size-lg);font-weight:600;margin:8px 0 4px}
.saq-callout-header{display:flex;justify-content:flex-end;margin-bottom:6px}

/* P0·1 — Sticky-pin the confidence row to the bottom of the back face.
   When the card grows past the viewport (long callout body), the four
   Critical/Low/Intermediate/High pills stick to the bottom edge of the
   card so the rating is always reachable. The backdrop fade + border-top
   read as anchored, not floating. margin-top:auto pushes the footer to
   the bottom of the flex column when content is shorter than the card. */
/* F8-A-05 — SAQ Today/lib rate footer: tile layout matching fc-grade-btn rhythm.
   Fixes the "Honed floating disconnected" layout drift (F8-B-09 subsumed).
   WS4 (Q4): sticky behaviour preserved; margins use card-padding tokens so
   the footer hugs the card edge regardless of card padding value. */
.saq-card-cf-footer{
  margin:0 calc(var(--card-padding-inline) * -1) calc(var(--card-padding-block) * -1);
  margin-top:auto;
  padding:8px var(--card-padding-inline) var(--card-padding-block);
  background:var(--surface);
  border-top:1px solid var(--border);
  z-index:2;
}
.saq-card-cf-footer .recall-actions{margin-top:0;gap:6px;flex-wrap:nowrap}

/* Notes empty-state link buttons */
/* saq-notes-links kept for backwards compat (v172 focus card renderer) */
.saq-notes-links{display:flex;gap:8px;flex-wrap:wrap}
.saq-notes-link{
  display:inline-flex;align-items:center;gap:6px;
  padding:8px 12px;border:1px solid var(--border);border-radius:var(--radius-sm);
  background:var(--surface);color:var(--text);
  font-size:var(--font-size-md);font-weight:500;text-decoration:none;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.saq-notes-link:hover{border-color:var(--accent);color:var(--accent)}

/* patch-030 — empty-state text in Notes panel */
.saq-notes-empty{color:var(--text-muted);font-style:italic;font-size:var(--font-size-md);margin:0 0 10px}

/* patch-030 — compact reference chip row */
.saq-ref-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:10px;padding-top:10px;border-top:1px solid var(--border)}
.saq-ref-chip{
  display:inline-flex;align-items:center;gap:4px;
  padding:3px 8px;border-radius:var(--radius-pill);
  font-size:var(--font-size-xs);font-weight:500;line-height:1.4;
  background:var(--surface-2,var(--surface));color:var(--text-muted);
  border:1px solid var(--border);text-decoration:none;white-space:nowrap;
  transition:color var(--duration-sm),border-color var(--duration-sm);
}
.saq-ref-chip:hover,.saq-ref-chip:focus-visible{color:var(--accent);border-color:var(--accent)}
.saq-ref-chip--btn{cursor:pointer;background:var(--surface-2,var(--surface))}
.saq-ref-chip--static{cursor:default;opacity:.7}
/* patch-032 — drug-card chip recolours hover state to peri so it reads
   as an in-app cross-link rather than an external resource. */
.saq-ref-chip--drug:hover,.saq-ref-chip--drug:focus-visible{color:var(--peri);border-color:var(--peri)}
/* patch-032 — inline chip row at bottom of the model-body. Tighter top
   margin than the Notes-panel version (which separates from a prose
   block); the model-body version separates from the answer's last list
   or paragraph so the visual gap can be smaller. */
.saq-ref-chips--inline{margin-top:14px;padding-top:10px;border-top:1px dashed var(--border)}
/* patch-032 — landing pulse when a drug card is opened from a SAQ chip */
@keyframes pharma-cross-link-pulse{
  0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--peri) 60%,transparent)}
  60%{box-shadow:0 0 0 8px color-mix(in srgb,var(--peri) 0%,transparent)}
  100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--peri) 0%,transparent)}
}
.pharma-drug-card--cross-linked{
  animation:pharma-cross-link-pulse 1.6s ease-out;
  border-color:var(--peri) !important;
}

/* patch-030 — learning history pill in SAQ meta row */
.saq-history-pill{font-size:var(--font-size-xs);font-weight:600;letter-spacing:0.01em}
/* AUDIT-2026-05-06 #21 — SAQ history pill palette. Foreground from --saq-*
   tokens (theme-aware); bg + border derived via color-mix at use sites. */
.saq-history-pill--mastered2{background:color-mix(in srgb,var(--saq-pass) 15%,transparent);color:var(--saq-pass);border:1px solid color-mix(in srgb,var(--saq-pass) 30%,transparent)}
.saq-history-pill--mastered1{background:color-mix(in srgb,var(--saq-borderline) 12%,transparent);color:var(--saq-borderline);border:1px solid color-mix(in srgb,var(--saq-borderline) 25%,transparent)}
.saq-history-pill--missed{background:color-mix(in srgb,var(--saq-fail) 12%,transparent);color:var(--saq-fail);border:1px solid color-mix(in srgb,var(--saq-fail) 25%,transparent)}

/* Today-fix v2 — SAQ paginated view shows up to 2 cards per page.
   Single-card pages get full width; two-card pages split 50/50. Below
   2 cards it just shows what's there full-width. Pagination steps in
   pairs: page 1 = SAQs 1+2, page 2 = SAQs 3+4, etc. Both .active
   cards on a page render together via grid auto-fit. */
/* patch-032 round 5 — col-stack mosaic primitive. One layout for every
   surface that arranges cards into independent flex columns (Today
   recall/SAQ/pharma/facts, SAQ library, Pharma library, skeleton grid).
   Round-robin distribution preserves L→R reading order; expanding a card
   in column A never pushes column B down (mosaic behaviour).

   Variants:
     .col-stack--cols-2 — 2 cols ≥880px, 1 col below
     .col-stack--cols-3 — 3 cols ≥880px, 2 cols + row at 880, 1 col ≤600

   The container also overrides .lib-list (which is a CSS Grid at min-width
   ≥1100), so .lib-list.col-stack works for the SAQ + Pharma libraries. */
.col-stack,
.lib-list.col-stack{
  display:flex;
  flex-direction:row;
  flex-wrap:wrap;
  grid-template-columns:none;
  gap:var(--col-stack-gap, 11px);
  align-items:flex-start;
}
.col-stack > .col-stack__col{
  flex:1 1 0;
  min-width:0;
  display:flex;
  flex-direction:column;
  gap:var(--col-stack-gap, 11px);
}
.col-stack--cols-2 > .col-stack__col{flex-basis:calc(50% - var(--col-stack-gap, 11px) / 2)}
.col-stack--cols-3 > .col-stack__col{flex-basis:calc(33.333% - var(--col-stack-gap, 11px) * 2/3)}
/* Sparse-section centering (opt-in via makeColStack centerSparse) — when a
   section has fewer cards than columns, the wrapper builds only that many
   columns; centering them keeps a lone card in the middle of the row rather
   than jammed into the leftmost column. Columns keep their normal width
   (flex-basis from the --cols-N class) but don't grow to fill the row. */
.col-stack--centered{justify-content:center}
.col-stack--centered > .col-stack__col{flex-grow:0}
@media(max-width:880px){
  .col-stack--cols-2 > .col-stack__col{flex:0 0 100%}
  .col-stack--cols-3 > .col-stack__col:nth-child(1),
  .col-stack--cols-3 > .col-stack__col:nth-child(2){flex-basis:calc(50% - var(--col-stack-gap, 11px) / 2)}
  /* 3rd col flows to a full-width row of 2-up — preserves the legacy
     .recall-group-cards mosaic ergonomic at the tablet breakpoint. */
  .col-stack--cols-3 > .col-stack__col:nth-child(3){
    flex:0 0 100%;
    flex-direction:row;
    flex-wrap:wrap;
    gap:var(--col-stack-gap, 11px);
  }
  .col-stack--cols-3 > .col-stack__col:nth-child(3) > *{
    flex:0 0 calc(50% - var(--col-stack-gap, 11px) / 2);
    min-width:0;
  }
}
@media(max-width:768px){
  /* Phone + small tablet: collapse to single column. nth-child selectors
     match the specificity of the max-width:880 rule above (0,2,1) so the
     general `> .col-stack__col` selector cannot lose the cascade. */
  .col-stack--cols-3 > .col-stack__col,
  .col-stack--cols-3 > .col-stack__col:nth-child(1),
  .col-stack--cols-3 > .col-stack__col:nth-child(2),
  .col-stack--cols-3 > .col-stack__col:nth-child(3),
  .col-stack--cols-2 > .col-stack__col,
  .col-stack--cols-2 > .col-stack__col:nth-child(1),
  .col-stack--cols-2 > .col-stack__col:nth-child(2){flex:0 0 100%;flex-basis:100%;flex-direction:column}
  .col-stack--cols-3 > .col-stack__col:nth-child(3) > *{flex:1 1 auto}
}
.review-bar{margin-top:9px;display:flex;justify-content:flex-end;gap:6px}
.review-bar button{padding:5px 12px;border:1.5px solid var(--border);background:var(--surface);border-radius:var(--btn-radius);cursor:pointer;font-size:var(--font-size-sm);font-weight:600;color:var(--text-muted)}
.review-bar button.review{color:var(--accent);border-color:var(--accent);background:var(--accent-soft)}
.review-bar button.editing{background:var(--accent);color:white;border-color:var(--accent)}
.review-bar .saved-note{font-size:var(--font-size-xs);color:var(--green);font-style:italic;align-self:center;margin-right:auto}
.model-body{outline:none}
.model-body[contenteditable="true"]{border:1.5px solid var(--accent);background:var(--accent-soft);border-radius:var(--btn-radius);padding:8px}

/* --- Axioms (patch-034) ---
   Replaces Key Facts. sky blue palette retained. col-stack(3) same as
   legacy facts. Old .key-facts / .fact classes removed; all selectors
   updated to .key-axioms / .axiom. */
.key-axioms{margin:11px 0}

/* Axiom card identity: lime left-border + lime tinted bg (WS11: --sky→--lime).
   WS4: stripe unified to var(--card-stripe-width) (4px). Hover added
   (was absent — now consistent with recall/saq/pharma).
   position:relative anchors the absolutely-positioned .card-flag-btn (R-030). */
.axiom{
  position:relative;
  background:color-mix(in srgb,var(--saltbush) var(--card-tint-light),var(--surface-alt2));
  border:1px solid var(--border);
  /* Card-redesign IMPROVE: deeper stripe — --lime mid-tone (#8A9E1A) blends
     into warm paper; --lime-deep (#546400) gives a clear olive identity. */
  border-left:var(--card-stripe-width) solid var(--saltbush-deep);
  border-radius:var(--radius);
  padding:14px;
  transition:background var(--duration-sm) var(--ease-out),border-color var(--duration-sm) var(--ease-out),box-shadow var(--duration-sm) var(--ease-out),transform var(--duration-sm) var(--ease-out);
}
.axiom:hover{box-shadow:var(--card-shadow-hover)}
.axiom-header{font-weight:600;font-size:15px;margin-bottom:8px;line-height:1.3;display:flex;align-items:center;gap:6px;padding-right:32px}
.axiom-header .axiom-icon{opacity:0.75;font-size:var(--font-size-lg)}
/* Tier rendered as a pill tag (replaces raw emoji/text from Notion data).
   Awaiting full Axiom card redesign — pill is the interim preferred style. */
.axiom-tier{display:none} /* legacy — hidden; replaced by axiom-tier-pill */
.axiom-tier-pill{
  display:inline-flex;align-items:center;
  padding:1px 7px;border-radius:var(--radius-pill);
  font-size:var(--font-size-2xs);font-weight:700;letter-spacing:0.04em;
  border:1.5px solid currentColor;line-height:1.5;flex-shrink:0;
}
.axiom-tier-pill[data-tier="high"]  {color:var(--coral);background:color-mix(in srgb,var(--coral)  10%,var(--surface))}
.axiom-tier-pill[data-tier="medium"]{color:var(--honey);background:color-mix(in srgb,var(--honey)  10%,var(--surface))}
.axiom-tier-pill[data-tier="low"]   {color:var(--sage); background:color-mix(in srgb,var(--sage)   10%,var(--surface))}

/* Reveal button — WS4 (Q10): migrated to .btn taxonomy (.btn--ghost .btn--md
   [data-fullwidth][data-axiom-reveal]). Sky tint applied via [data-axiom-reveal]
   scoped rule. Original .axiom-reveal-btn rule preserved as fallback for any
   non-JS path; display:none hides it post-reveal. */
.btn[data-axiom-reveal]{
  width:100%;
  background:color-mix(in srgb,var(--sky) 12%,var(--surface));
  border:1px solid color-mix(in srgb,var(--sky) 40%,var(--border));
  border-radius:var(--radius-sm);
  font-size:var(--font-size-md);font-weight:500;color:var(--text);
  cursor:pointer;margin:8px 0;
  transition:background var(--duration-sm) var(--ease-out),opacity var(--duration-sm) var(--ease-out);
  display:flex;align-items:center;justify-content:center;
  padding:8px 12px;
}
.btn[data-axiom-reveal]:hover{background:color-mix(in srgb,var(--saltbush) 20%,var(--surface))}
.axiom.revealed .btn[data-axiom-reveal]{display:none}

/* Formula reveal section */
.axiom-reveal{display:none;flex-direction:column;gap:8px;margin:8px 0 4px;width:100%;animation:saq-reveal-in .18s ease both}
.axiom.revealed .axiom-reveal{display:flex}

/* Grades hidden until reveal — reuses the existing .post-reveal component; only the visibility gate is new. */
.axiom:not(.revealed) .post-reveal{display:none}

/* Formula display */
.axiom-formula{
  font-size:15px;line-height:1.7;
  background:color-mix(in srgb,var(--saltbush) 8%,var(--surface));
  border-radius:var(--radius-sm);
  padding:10px 12px;
  overflow-x:auto;
}
.axiom-formula-label{font-size:var(--font-size-xs);font-weight:600;text-transform:uppercase;letter-spacing:0.06em;color:var(--text-muted);margin-bottom:4px}

/* Stage 2 audit (2026-05-04, Run 2) — dark-mode card body chroma lift.
   8% type tint produces only ~0.013 Y delta on `--bg #0F1E1A` vs ~0.04 on
   light cream paper, leaving cards near-monochrome with the bg in dark
   mode (root cause of "dark mode is ugly"). 12% restores the type identity
   signal in dark without spilling into light mode (which already reads
   correctly at 8% on warm paper). One scoped block, five selectors. */
/* Stage 2 audit (2026-05-04, Run 2) — dark-mode card body chroma lift.
   WS4: tint percentage tokenised to var(--card-tint-dark) = 12%. */
/* WS11: DM token corrections. recall border override (LM base now uses --sky which = lime-gold in DM). */
html.dark .recall-card    {background:color-mix(in srgb,var(--sage)   var(--card-tint-dark),var(--surface-alt2));border-left-color:var(--sage)}
html.dark .recall-card.keyboard-focused{background:color-mix(in srgb,var(--sage) 10%,var(--surface-alt2));box-shadow:0 4px 14px -4px color-mix(in srgb,var(--sage) 40%,transparent)}
html.dark .pharma-card    {background:color-mix(in srgb,var(--violet) var(--card-tint-dark),var(--surface-alt2))}
html.dark .saq-card-face  {background:color-mix(in srgb,var(--rose)   var(--card-tint-dark),var(--surface-alt2))} /* WS11: --honey→--rose */
html.dark .axiom          {background:color-mix(in srgb,var(--saltbush)   var(--card-tint-dark),var(--surface-alt2))} /* WS11: --sky→--lime (semantic; same DM value) */
html.dark .axiom-formula  {background:color-mix(in srgb,var(--saltbush)   18%,var(--surface))}     /* WS11: --sky→--lime. Card-redesign 2026-05-05: decoupled from --card-tint-dark (now 6%) to preserve formula vs card-bg distinction. */

/* Variable panel */
.axiom-variables{display:flex;flex-direction:column;gap:3px;margin-top:2px}
.axiom-variable-row{display:flex;gap:8px;font-size:var(--font-size-md);line-height:1.4}
.axiom-var-sym{font-family:var(--font-mono);font-weight:600;color:var(--saltbush-deep);min-width:40px;flex-shrink:0} /* v10: --lime-deep→--saltbush-deep */
.axiom-var-def{color:var(--text-muted)}

/* Clinical context line */
.axiom-context{
  font-size:var(--font-size-md);color:var(--text-muted);
  border-left:2px solid var(--saltbush); /* WS11: --sky→--lime */
  padding:4px 8px;margin-top:4px;
  line-height:1.5;font-style:italic;
}

/* Chips row — named-after + related equations */
.axiom-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px}
.axiom-chip{
  font-size:var(--font-size-xs);padding:2px 8px;
  background:color-mix(in srgb,var(--sky) 14%,var(--surface));
  border:1px solid color-mix(in srgb,var(--sky) 30%,var(--border));
  border-radius:var(--radius-pill);color:var(--text-muted);white-space:nowrap;
}
.axiom-chip.named-after{color:var(--text);font-weight:500}

/* --- Routine list ---
   Today-fix v2 — bordered-card list with the entire row as a clickable
   label. Each <li> is the visible card frame; the inner <label> spans
   the full width and carries the flex layout + padding, so clicking
   anywhere in the card toggles the checkbox.
   Time text uses Albert Sans tabular-nums (was reading as code on mono).
   Checked items demote to surface-alt + muted text so completed work
   stays visible without competing. */
.routine-list{list-style:none;padding:0;margin:11px 0;display:flex;flex-direction:column;gap:8px}
.routine-list li{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  font-size:var(--font-size-lg);color:var(--text);
  transition:background var(--duration-sm),border-color var(--duration-sm);
  overflow:hidden;          /* keep label corners flush with li radius */
}
.routine-list li:hover{border-color:color-mix(in srgb,var(--indigo) 35%,var(--border))}
.routine-row{
  display:flex;align-items:center;gap:14px;
  padding:12px 14px;
  cursor:pointer;
  width:100%;
  user-select:none;         /* clicks on text shouldn't drag-select */
}
.routine-row input[type=checkbox]{width:18px;height:18px;cursor:pointer;accent-color:var(--accent);flex-shrink:0;margin:0}
.routine-row .time{
  font-family:var(--font-sans);font-size:var(--font-size-md);font-weight:500;
  font-variant-numeric:tabular-nums;letter-spacing:0.02em;
  color:var(--text-muted);min-width:96px;flex-shrink:0;
}
/* Checked-state demotion — applied at the li level so the whole card
   shifts colour, not just the inner label. */
.routine-list li:has(input:checked){background:var(--surface-alt);color:var(--text-muted)}
.routine-list li:has(input:checked) .time{color:var(--text-faint)}

.next-review{font-size:var(--font-size-xs);color:var(--text-faint);font-family:var(--font-mono)}

/* patch-007 — Reusable EmptyState component (per Strategic Brief §3).
   First consumer is the Pharma Today section; will be reused across tabs
   as more empty states are designed. Style is illustrative + warm; copy
   handled by the consumer to honour the playful/dark-humoured tone. */
.empty-state{
  display:flex;flex-direction:column;align-items:center;
  padding:28px 20px;text-align:center;gap:8px;
  border:1px dashed var(--border);border-radius:var(--radius);
  background:color-mix(in srgb,var(--surface) 70%,transparent);
  color:var(--text-muted);
}
.empty-state-icon{width:56px;height:56px;color:var(--text-faint);margin-bottom:4px}
.empty-state-icon svg{width:100%;height:100%}
.empty-state-heading{font-size:var(--font-size-lg);font-weight:500;color:var(--text);line-height:1.4}
.empty-state-body{font-size:var(--font-size-md);line-height:1.55;max-width:380px;font-style:italic}
.empty-state-actions{display:flex;gap:8px;margin-top:8px;flex-wrap:wrap;justify-content:center}
.empty-state-btn{
  font-family:inherit;font-size:var(--font-size-md);font-weight:500;
  padding:7px 14px;border-radius:var(--radius-sm);cursor:pointer;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.empty-state-btn--primary{
  border:1px solid var(--accent);background:var(--accent);color:var(--accent-on);
}
.empty-state-btn--primary:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.empty-state-btn--secondary{
  border:1px solid var(--border);background:transparent;color:var(--text-muted);
}
.empty-state-btn--secondary:hover{color:var(--text);border-color:var(--border-strong)}

/* patch-007 — Shift-to-reveal keyboard shortcut hints.
   .kbd renders a chip-style key (always visible, e.g. inside settings).
   .kbd-hint is a contextual hint shown ONLY while Shift is held — keeps
   button labels uncluttered by default but full keymap surfaces on demand. */
.kbd{display:inline-block;font-family:var(--font-mono);font-size:var(--font-size-xs);padding:1px 5px;
     border-radius:var(--radius-tiny);border:0.5px solid var(--border-strong);background:var(--surface-alt);
     color:var(--text-muted);line-height:1.4;margin-left:4px;vertical-align:1px}
.kbd-hint{display:inline-block;font-family:var(--font-mono);font-size:var(--font-size-2xs);padding:1px 5px;
          border-radius:var(--radius-tiny);border:0.5px solid currentColor;opacity:0;margin-left:4px;
          transition:opacity .15s ease;vertical-align:1px;pointer-events:none}
body.shift-armed .kbd-hint{opacity:0.85}
@media (prefers-reduced-motion: reduce){
  .kbd-hint{transition:none}
}

.ref-link{font-size:var(--font-size-md);color:var(--text-muted);margin-top:8px}
.ref-link a{color:var(--accent);text-decoration:none;font-weight:500}

/* T-P1-04 — Pharmacopia empty-state stub. Shown in place of the card grid
   when no drug fields are due today (rather than silently hiding the section). */
.today-empty-stub{font-size:var(--font-size-md);color:var(--text-faint);padding:8px 2px;margin:0;font-style:italic}

/* --- Footer + save bar --- */
.footer{margin-top:30px;padding-top:18px;border-top:1px solid var(--border);font-size:var(--font-size-sm);color:var(--text-muted)}
.footer h3{font-size:var(--font-size-md);color:var(--text);margin:0 0 8px;font-weight:600}
.footer dl{display:grid;grid-template-columns:max-content 1fr;gap:6px 14px;margin:5px 0}
.footer dt{font-weight:600;color:var(--text)}
.footer dd{margin:0}
/* Today-fix — Run metadata details: card framing follows the global
   details rule, but we tighten the typography so it reads as 'config
   info' rather than 'code dump'. Keys + non-numeric values stay sans;
   only ISO timestamps + numeric IDs get mono via .footer-dl-mono. */
.footer-meta{margin:11px 0 13px;font-size:var(--font-size-sm);color:var(--text-muted)}
.footer-meta>summary{font-size:var(--font-size-md);color:var(--text-muted)}
.footer-dl{
  display:grid;
  /* Audit fix — minmax(90px, max-content) lets the keys column auto-size
     to longest key but never falls below 90px (so 'generator' / 'D' style
     short keys don't collapse the grid) and never exceeds the widest key
     (so the value column gets the maximum space). On <400px viewports
     this gracefully shrinks instead of overflowing. */
  grid-template-columns:minmax(90px,max-content) 1fr;
  gap:8px 14px;
  margin:0;font-family:var(--font-sans);font-size:var(--font-size-sm);
}
.footer-dl dt{font-weight:600;color:var(--text-muted);letter-spacing:0.01em}
.footer-dl dd{margin:0;color:var(--text);overflow-wrap:anywhere}
.footer-dl dd.footer-dl-mono{font-family:var(--font-mono);font-size:var(--font-size-xs);color:var(--text-muted)}
.save-bar{
  margin-top:14px;padding:14px;
  background:linear-gradient(135deg,var(--green-bg) 0%,var(--green-soft) 100%);
  border-radius:var(--radius);display:flex;align-items:center;gap:11px;flex-wrap:wrap;
  border:1px solid var(--green);border-left-width:4px;
}
.save-bar button{
  padding:10px 22px;border:none;background:var(--accent);color:white;
  border-radius:var(--radius-md);cursor:pointer;font-size:var(--font-size-lg);font-weight:700;
  box-shadow:0 2px 0 var(--accent-pressed);transition:background .1s,color .1s,border-color .1s,box-shadow .1s,transform .1s,opacity .1s;
}
.save-bar button:hover{transform:translateY(-1px);box-shadow:0 3px 0 var(--accent-pressed)}
.save-bar button:active{transform:translateY(2px);box-shadow:0 0 0 var(--accent-pressed)}
.save-bar button:disabled{opacity:0.5;cursor:not-allowed;background:var(--surface);color:var(--text-muted);border:1px solid var(--border);box-shadow:none}
/* v176 — save-log capped at 64px tall (was 140) so the .save-bar doesn't
   grow into a wall of red retry-failed lines blocking page actions. */
.save-log{font-family:var(--font-mono);font-size:var(--font-size-xs);line-height:1.5;color:var(--text-muted);max-height:64px;overflow-y:auto;width:100%;margin-top:6px;padding:7px 9px;background:var(--surface);border-radius:var(--btn-radius);display:none}
.save-log.visible{display:block}
.save-log .ok{color:var(--green)}
.save-log .err{color:var(--red)}
/* v176 — When the save-conflict overlay is open, hide the redundant
   inline save-bar (same info, more prominent). Also hide the corner
   save-queue toast under the same condition. */
body:has(#saveConflictOverlay) .save-bar,
body:has(#saveConflictOverlay) .save-queue-toast{display:none!important}
/* Also hide save-bar when a sheet/modal is active (extends P1·1 scoping
   that targeted only .save-queue-toast). */
body:has([aria-modal="true"]) .save-bar,
body.focus-mode-active .save-bar{display:none!important}

/* --- Stats grid (history) --- */
.stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(155px,1fr));gap:11px;margin:13px 0}
.stat-card{background:var(--surface-alt2);border:1px solid var(--border);border-radius:var(--radius);padding:13px;transition:transform .15s}
.stat-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.stat-label{font-size:var(--font-size-xs);color:var(--text-muted);text-transform:uppercase;letter-spacing:0.05em;font-weight:600;margin-bottom:4px}
.stat-value{font-size:26px;font-weight:700;line-height:1;font-variant-numeric:tabular-nums;color:var(--text)}
.stat-sub{font-size:var(--font-size-xs);color:var(--text-muted);margin-top:4px}

.charts-row{display:grid;grid-template-columns:1fr;gap:11px;margin:13px 0}
@media(min-width:780px){.charts-row{grid-template-columns:1.4fr 1fr}}
.chart-card{background:var(--surface-alt2);border:1px solid var(--border);border-radius:var(--radius);padding:13px}
.chart-card h3{margin:0 0 10px;font-size:var(--font-size-md);color:var(--text)}
.chart-wrap{position:relative;height:200px}

/* .heatmap layout is set inline by buildHeatmap() — grid-template-rows:repeat(7,1fr)
   grid-auto-flow:column; grid-auto-columns:1fr — 12-week calendar grid */
.heatmap{overflow-x:auto}
.heatmap-cell{width:14px;height:14px;border-radius:3px;cursor:pointer}
/* §1 Heatmap ramp — single-accent intensity ramp per v9.1 ("var(--accent)
   ramp for intensity, no extra colour ramps"). 4 steps from sage-fill →
   accent via color-mix opacity. Light/dark resolve automatically. */
.heatmap-cell[data-score="0"]{background:var(--surface-alt)}
.heatmap-cell[data-score="1"]{background:var(--sage-fill)}
.heatmap-cell[data-score="2"]{background:color-mix(in srgb,var(--accent) 35%,var(--surface))}
.heatmap-cell[data-score="3"]{background:color-mix(in srgb,var(--accent) 65%,var(--surface))}
.heatmap-cell[data-score="4"]{background:var(--accent)}
.heatmap-legend{display:flex;align-items:center;gap:6px;font-size:var(--font-size-xs);color:var(--text-muted);margin-top:6px;justify-content:flex-end}
.heatmap-legend .swatch{width:11px;height:11px;border-radius:var(--radius-2xs)}

/* ── Calendar history sheet (sub-block 1.12) ──────────────────────────────────
   Opens from the history glyph button (todayUndoBtn). A full-screen/bottom
   sheet containing the 12-week calendar grid plus per-day drill-down panel. */
/* Filter toggle row */
.cal-filter{display:flex;align-items:center;gap:8px;margin-bottom:12px;font-size:var(--font-size-xs);color:var(--text-muted)}
.cal-filter-toggle{display:inline-flex;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-pill);padding:2px;gap:2px}
.cal-filter-btn{border:none;background:transparent;cursor:pointer;font-family:inherit;font-size:var(--font-size-xs);color:var(--text-muted);padding:3px 10px;border-radius:var(--radius-pill);transition:background var(--duration-sm),color var(--duration-sm);white-space:nowrap}
.cal-filter-btn[aria-pressed="true"]{background:var(--surface-elevated);color:var(--text);font-weight:600;box-shadow:0 1px 2px rgba(0,0,0,.06)}
/* Month labels row above grid */
.cal-month-labels{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:3px;margin-bottom:2px;font-size:10px;color:var(--text-faint);font-variant-numeric:tabular-nums;height:14px}
.cal-month-label{text-align:left;padding-left:2px;white-space:nowrap;overflow:hidden}
/* Day-of-week labels column (Mon/Thu/Sun on alternating rows) */
.cal-grid-wrap{display:flex;gap:6px;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px}
.cal-dow-col{display:grid;grid-template-rows:repeat(7,var(--cal-cell-size,12px));gap:3px;flex-shrink:0}
.cal-dow-label{height:var(--cal-cell-size,12px);font-size:9px;color:var(--text-faint);display:flex;align-items:center;justify-content:flex-end;padding-right:4px;white-space:nowrap}
/* The actual grid */
.cal-grid{display:grid;grid-template-rows:repeat(7,var(--cal-cell-size,12px));grid-auto-flow:column;grid-auto-columns:var(--cal-cell-size,12px);gap:3px;flex-shrink:0}
/* Cell states */
.cal-cell{width:var(--cal-cell-size,12px);height:var(--cal-cell-size,12px);border-radius:var(--radius-2xs);cursor:pointer;outline:none;position:relative;transition:transform .1s;border:1px solid transparent}
.cal-cell[data-score="0"]{background:var(--surface-alt);border-color:transparent}
.cal-cell[data-score="1"]{background:var(--sage-fill)}
.cal-cell[data-score="2"]{background:color-mix(in srgb,var(--accent) 35%,var(--surface))}
.cal-cell[data-score="3"]{background:color-mix(in srgb,var(--accent) 65%,var(--surface))}
.cal-cell[data-score="4"]{background:var(--accent)}
.cal-cell[data-inprogress]{background:color-mix(in srgb,var(--honey,#f0a500) 30%,var(--surface));border:1px dashed var(--honey,#f0a500)}
.cal-cell--today{box-shadow:0 0 0 2px var(--accent);animation:cal-today-pulse 2s ease infinite}
.cal-cell--today[data-score="0"]{background:var(--surface-alt)}
@keyframes cal-today-pulse{0%,100%{box-shadow:0 0 0 2px var(--accent)}50%{box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 55%,transparent)}}
@media(prefers-reduced-motion:reduce){.cal-cell--today{animation:none;box-shadow:0 0 0 2px var(--accent)}}
.cal-cell[aria-selected="true"],.cal-cell:focus-visible{box-shadow:0 0 0 2px var(--text),0 0 0 3.5px var(--accent);z-index:1}
.cal-cell:hover:not([disabled]){transform:scale(1.2);z-index:2}
.cal-cell[disabled]{pointer-events:none;background:transparent;border-color:transparent}
/* Summary stats row (streak + total) below grid */
.cal-stats{display:flex;align-items:center;gap:16px;margin:10px 0 6px;flex-wrap:wrap;font-size:var(--font-size-xs);color:var(--text-muted)}
.cal-stats strong{color:var(--text);font-variant-numeric:tabular-nums}
/* Day drill-down panel */
.cal-day-panel{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-elevated);overflow:hidden;margin-top:8px;animation:cal-panel-in .18s ease}
@keyframes cal-panel-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
@media(prefers-reduced-motion:reduce){.cal-day-panel{animation:none}}
.cal-day-hdr{display:flex;align-items:center;gap:10px;padding:10px 14px;border-bottom:1px solid var(--border);background:var(--surface)}
.cal-day-hdr-date{font-size:var(--font-size-md);font-weight:700;color:var(--text)}
.cal-day-hdr-close{margin-left:auto;background:none;border:none;cursor:pointer;color:var(--text-muted);font-size:16px;padding:2px 6px;border-radius:var(--radius-tiny);line-height:1}
.cal-day-hdr-close:hover{background:var(--surface-alt);color:var(--text)}
.cal-day-body{padding:12px 14px}
.cal-day-loading{display:flex;align-items:center;gap:8px;padding:20px 0;justify-content:center;color:var(--text-faint);font-size:var(--font-size-sm)}
.cal-day-empty{padding:20px 0;text-align:center;color:var(--text-faint);font-size:var(--font-size-sm)}
/* Per-type counts chips */
.cal-day-types{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.cal-day-type{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:var(--radius-pill);font-size:var(--font-size-xs);font-weight:600;background:var(--surface-alt);color:var(--text-muted);border:1px solid var(--border)}
.cal-day-type--recall{background:color-mix(in srgb,var(--accent) 10%,var(--surface));color:var(--accent);border-color:color-mix(in srgb,var(--accent) 30%,transparent)}
.cal-day-type--saq{background:color-mix(in srgb,var(--sky,#5b8dee) 10%,var(--surface));color:var(--sky-deep,#2d5fb0);border-color:color-mix(in srgb,var(--sky,#5b8dee) 30%,transparent)}
.cal-day-type--pharma{background:color-mix(in srgb,var(--violet,#8b5cf6) 10%,var(--surface));color:var(--violet,#8b5cf6);border-color:color-mix(in srgb,var(--violet,#8b5cf6) 30%,transparent)}
.cal-day-type--axiom{background:color-mix(in srgb,var(--honey,#f0a500) 10%,var(--surface));color:var(--honey-deep,#a67000);border-color:color-mix(in srgb,var(--honey,#f0a500) 30%,transparent)}
/* Meta row (XP, time, sessions) */
.cal-day-meta{display:flex;gap:16px;flex-wrap:wrap;font-size:var(--font-size-xs);color:var(--text-muted);margin-bottom:12px;padding-bottom:10px;border-bottom:1px solid var(--border)}
.cal-day-meta span{white-space:nowrap}
.cal-day-meta strong{color:var(--text)}
/* Session ribbon expand blocks */
.cal-day-session{border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;margin-bottom:8px}
.cal-day-session-hdr{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--surface);cursor:pointer;font-size:var(--font-size-sm)}
.cal-day-session-hdr:hover{background:var(--surface-alt)}
.cal-day-session-title{font-weight:600;flex:1;color:var(--text)}
.cal-day-session-meta{font-size:var(--font-size-xs);color:var(--text-muted)}
.cal-day-session-toggle{font-size:11px;color:var(--text-faint);transition:transform .15s}
.cal-day-session-toggle[aria-expanded="true"]{transform:rotate(90deg)}
.cal-day-session-ribbon{padding:6px 8px;background:var(--surface-elevated)}
/* Session pill label colours reuse sh-card-status palette */
.cal-status{font-size:var(--font-size-2xs);font-weight:700;letter-spacing:.05em;text-transform:uppercase;padding:2px 7px;border-radius:var(--radius-pill)}
.cal-status.completed{background:color-mix(in srgb,var(--accent) 14%,transparent);color:var(--accent)}
.cal-status.in_progress{background:color-mix(in srgb,var(--honey,#f0a500) 14%,transparent);color:var(--honey-deep,#a67000)}
.cal-status.draft{background:var(--surface-alt);color:var(--text-faint)}
/* Tooltip for cells on hover (using title attr; see JS for custom tooltip fallback) */
@media(max-width:480px){
  :root{--cal-cell-size:11px}
  .cal-dow-label{font-size:8px}
}
@media(min-width:600px){
  :root{--cal-cell-size:14px}
}

/* --- Save queue toast + conflict panel ---
   v176 — Toast is now a SMALL, UNOBTRUSIVE corner pill that never blocks.
   Anchored bottom-right, minimal width, low z-index. User can drag-dismiss
   or just ignore — saves drain in the background. Was: large centred bar
   with full-width Retry/Discard buttons. */
.save-queue-toast{
  position:fixed;bottom:calc(72px + env(safe-area-inset-bottom,0px));
  right:14px;left:auto;transform:none;
  display:inline-flex;align-items:center;gap:6px;
  background:var(--surface-card);border:1px solid var(--border);
  border-radius:var(--radius-sm);padding:6px 10px;
  box-shadow:0 2px 8px rgba(0,0,0,.10);
  font-size:var(--font-size-sm);color:var(--text-muted);z-index:60;
  white-space:nowrap;
  animation:sqSlideUp var(--duration-md) ease;
  opacity:.85;
}
.save-queue-toast:hover{opacity:1}
/* v172 — Hide save toast under modal/sheet overlays + when focus mode
   is active. body.focus-mode-active is set by the focus overlay open
   handler; existing modals carry [aria-modal="true"] per the dialog-a11y
   skill recipe. The :has() selector is supported on all evergreen
   browsers; iOS 15.4+. Falls back to "always visible" pre-:has(). */
body.focus-mode-active .save-queue-toast,
body:has([aria-modal="true"]) .save-queue-toast,
body:has(.focus-overlay.active) .save-queue-toast{
  display:none!important;
}
.save-queue-msg{color:var(--text-muted);flex:0 1 auto;font-variant-numeric:tabular-nums}
/* v176 — Tiny status dot. Pulses while a background save is in flight. */
.save-queue-dot{
  width:7px;height:7px;border-radius:50%;
  background:var(--honey);flex:0 0 7px;
  animation:sqDot 1.6s ease-in-out infinite;
}
@keyframes sqDot{0%,100%{opacity:.4}50%{opacity:1}}

/* Phase 1.2 — Sync status chip (Figma-style silent save).
   Visible only on syncing (>1.5s) / offline / failed. Steady-state success = hidden. */
.sync-chip{
  position:fixed;top:calc(12px + env(safe-area-inset-top,0px));
  right:14px;
  display:inline-flex;align-items:center;gap:7px;
  background:var(--surface-card);border:1px solid var(--border);
  border-radius:var(--radius-pill);padding:5px 11px 5px 9px;
  box-shadow:0 2px 8px rgba(0,0,0,.08);
  font-size:var(--font-size-xs);color:var(--text-muted);
  z-index:55;white-space:nowrap;
  animation:syncChipFade .18s ease;
  font-variant-numeric:tabular-nums;
}
.sync-chip[hidden]{display:none}
.sync-chip-dot{width:7px;height:7px;border-radius:50%;flex:0 0 7px;background:var(--honey)}
.sync-chip[data-state="syncing"] .sync-chip-dot{animation:sqDot 1.4s ease-in-out infinite}
.sync-chip[data-state="offline"] .sync-chip-dot{background:var(--text-faint)}
.sync-chip[data-state="failed"]  .sync-chip-dot{background:var(--coral, #d65a4a)}
.sync-chip[data-state="failed"]{border-color:var(--coral, #d65a4a)}
.sync-chip[data-state="failed"]:hover{background:color-mix(in srgb, var(--coral, #d65a4a) 8%, var(--surface-card))}
@keyframes syncChipFade{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
/* Hide under modal/focus overlays for the same reason as save-queue-toast */
body.focus-mode-active .sync-chip,
body:has([aria-modal="true"]) .sync-chip,
body:has(.focus-overlay.active) .sync-chip{display:none!important}
/* Phase 1.15 — Sync queue outbox panel (inside settings) */
.sq-panel{padding:2px 0 8px}
.sq-empty{font-size:var(--font-size-sm);color:var(--text-muted);padding:6px 0}
.sq-row{display:flex;flex-direction:column;gap:6px;padding:8px 0;border-bottom:1px solid var(--border)}
.sq-row:last-of-type{border-bottom:none}
.sq-row-meta{font-size:var(--font-size-sm);color:var(--text)}
.sq-row-count{font-weight:600}
.sq-row-age,.sq-row-session{color:var(--text-muted)}
.sq-row-actions{display:flex;gap:6px}
.sq-discard-btn{color:var(--coral,#d65a4a);border-color:var(--coral,#d65a4a)}
.sq-discard-btn:hover{background:color-mix(in srgb,var(--coral,#d65a4a) 8%,var(--surface-card))}
.sq-failures{margin-top:10px;font-size:var(--font-size-xs)}
.sq-failures summary{cursor:pointer;color:var(--text-muted);padding:4px 0;user-select:none}
.sq-fail-entry{padding:4px 0;border-bottom:1px solid var(--border-faint,var(--border));display:flex;flex-wrap:wrap;gap:2px 4px}
.sq-fail-date{color:var(--text-muted);font-variant-numeric:tabular-nums}
.sq-fail-reason{color:var(--coral,#d65a4a)}
.sq-fail-count{color:var(--text-faint,var(--text-muted))}
/* Phase 1.15 — Replay-mode corner pill */
.replay-pill{
  position:fixed;top:calc(12px + env(safe-area-inset-top,0px));
  right:14px;
  display:inline-flex;align-items:center;gap:6px;
  background:color-mix(in srgb,var(--coral,#d65a4a) 12%,var(--surface-card));
  border:1px solid var(--coral,#d65a4a);
  border-radius:var(--radius-pill);padding:5px 12px 5px 10px;
  font-size:var(--font-size-xs);color:var(--coral,#d65a4a);font-weight:600;
  z-index:56;white-space:nowrap;
  animation:syncChipFade .18s ease;
  pointer-events:none;user-select:none;
}
@media(prefers-reduced-motion:reduce){.replay-pill{animation:none}}
/* Phase 1.15 — Replay-mode fc-card dashed border */
.fc-card--replay{border-style:dashed!important;opacity:.88}
/* Phase 1.15 — Replay-mode greyscale grade buttons */
.fc-action-bar--replay{filter:grayscale(1);transition:filter .18s ease}
.fc-action-bar--replay:hover{filter:grayscale(0)}
@media(prefers-reduced-motion:reduce){.fc-action-bar--replay{transition:none}}
.save-queue-btn{
  padding:3px 8px;border-radius:var(--btn-radius);font-size:var(--font-size-xs);
  font-weight:600;border:1px solid var(--border);cursor:pointer;
  background:var(--surface-alt);color:var(--text);
  margin-left:4px;
}
.sqb-retry{background:var(--accent);color:white;border-color:var(--accent)}
.sqb-retry:hover{opacity:.85}
.sqb-discard:hover{background:var(--surface)}
@keyframes sqSlideUp{
  from{opacity:0;transform:translateX(-50%) translateY(10px)}
  to  {opacity:1;transform:translateX(-50%) translateY(0)}
}
.save-conflict-overlay{
  position:fixed;inset:0;
  background:var(--backdrop-sheet);
  display:flex;align-items:flex-end;justify-content:center;
  z-index:1100; /* system-tier alert: intentionally above loading screen (1000) */
  padding-bottom:env(safe-area-inset-bottom,0px);
  animation:backdropIn var(--duration-md) ease;
}
.save-conflict-panel{
  background:var(--surface-card);
  border-radius:16px 16px 0 0;
  padding:24px 20px 20px;
  width:100%;max-width:480px;
  box-shadow:0 -4px 24px rgba(0,0,0,.15);
  position:relative;
}
/* v176 — Close button on the conflict overlay. Top-right of the sheet. */
.save-conflict-close{
  position:absolute;top:10px;right:12px;
  width:32px;height:32px;border-radius:50%;
  border:none;background:var(--surface-alt);color:var(--text-muted);
  font-size:18px;line-height:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  transition:background var(--duration-sm),color var(--duration-sm);
}
.save-conflict-close:hover{background:var(--border);color:var(--text)}
.save-conflict-title{font-weight:700;font-size:var(--font-size-xl);margin:0 0 6px;color:var(--text)}
.save-conflict-desc{font-size:var(--font-size-md);color:var(--text-muted);margin:0 0 16px}
.save-conflict-choice{
  display:flex;flex-direction:column;gap:3px;
  width:100%;text-align:left;
  background:var(--surface-alt);border:1px solid var(--border);
  border-radius:var(--radius-md);padding:12px 14px;cursor:pointer;
  margin-bottom:10px;
}
.save-conflict-choice:last-child{margin-bottom:0}
.save-conflict-choice:hover{border-color:var(--accent);background:var(--surface)}
.save-conflict-choice-title{font-weight:600;font-size:var(--font-size-lg);color:var(--text)}
.save-conflict-choice-sub{font-size:var(--font-size-sm);color:var(--text-muted)}

/* --- Badge haul toast (out-of-Focus earns) --- */
.badge-haul-toast{
  position:fixed;bottom:calc(68px + env(safe-area-inset-bottom,0px));
  left:50%;transform:translateX(-50%);
  background:var(--surface-card);border:1px solid var(--gold);
  border-radius:var(--radius-lg);padding:12px 16px 14px;
  box-shadow:0 4px 20px rgba(0,0,0,.2),0 0 0 3px rgba(255,217,61,.12);
  z-index:910;width:min(340px,90vw);
  animation:sqSlideUp .3s var(--ease-spring);
}
.badge-haul-toast-title{
  font-size:var(--font-size-xs);font-weight:700;color:var(--axiom-honey);
  text-transform:uppercase;letter-spacing:.06em;margin-bottom:10px;
  display:flex;align-items:center;gap:6px;
}
.badge-haul-toast-row{display:flex;justify-content:center;gap:12px;flex-wrap:wrap}
.badge-haul-toast-close{
  position:absolute;top:8px;right:10px;
  background:none;border:none;color:var(--text-muted);
  font-size:var(--font-size-xl);cursor:pointer;padding:2px 4px;line-height:1;
}
.badge-haul-toast-close:hover{color:var(--text)}


/* --- Planner --- */
.phase-progress{display:flex;flex-direction:column;gap:10px;margin:13px 0}
.phase-row{
  background:var(--surface-alt2);border:1px solid var(--border);border-radius:var(--radius);
  padding:14px;border-left:4px solid var(--border-strong);transition:background .15s,color .15s,border-color .15s,box-shadow .15s,transform .15s,opacity .15s;cursor:pointer;
}
.phase-row:hover{box-shadow:var(--shadow-sm)}
.phase-row.current{border-left-color:var(--accent);background:var(--accent-soft);box-shadow:var(--shadow-glow)}
.phase-row.done{border-left-color:var(--green);opacity:0.95}
.phase-row.upcoming{filter:saturate(0.45);opacity:0.85}
.phase-row.upcoming:hover{filter:saturate(0.7);opacity:1}
.phase-row.expanded .phase-detail{display:block}
.phase-detail{display:none;margin-top:12px;padding-top:11px;border-top:1px dashed var(--border)}
.phase-head{display:flex;align-items:baseline;justify-content:space-between;gap:9px;flex-wrap:wrap}
.phase-title{font-weight:600;font-size:14.5px}
.phase-dates{font-family:var(--font-mono);font-size:var(--font-size-sm);color:var(--text-muted)}
.phase-meta{font-size:var(--font-size-md);color:var(--text-muted);margin-top:5px}

.progress-bar{height:9px;background:var(--surface-alt);border-radius:var(--btn-radius);margin:9px 0 5px;overflow:hidden;display:flex}
.progress-bar .seg{height:100%}
/* patch-008 — segment colour ramp for the universal grade vocabulary. */
.progress-bar .seg--mastered {background:var(--green)}
.progress-bar .seg--honed    {background:var(--amber)}
.progress-bar .seg--missed   {background:var(--red)}
.progress-bar .seg--unrated  {background:var(--surface-alt)}
.progress-legend{display:flex;gap:9px;flex-wrap:wrap;font-size:var(--font-size-xs);color:var(--text-muted);margin-top:6px}
.progress-legend span{display:inline-flex;align-items:center;gap:4px}
.progress-legend i{width:9px;height:9px;border-radius:var(--radius-2xs);display:inline-block}

/* --- Macroschedule editor (Planner tab) --- */
.planner-head h2{font-size:18px}
/* WS2 (Phase 9, 2026-05-05) — Button taxonomy.
   .btn = base; .btn--{primary,ghost,destructive,pill} = variants;
   .btn--{xs,sm,md,lg} = sizes. data-accent / data-shape / data-tone
   / data-icon-only / data-fullwidth / data-grade / data-cinema / data-segment
   / data-style / data-state / data-stage = modifiers. */
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  gap:6px;
  font-family:inherit;font-weight:var(--btn-font-weight);
  border:1px solid transparent;
  border-radius:var(--btn-radius);
  cursor:pointer;user-select:none;
  white-space:nowrap;
  line-height:1.2;
  background:var(--surface);color:var(--text);
  transition:background var(--duration-sm) var(--ease-out),
             color var(--duration-sm) var(--ease-out),
             border-color var(--duration-sm) var(--ease-out),
             box-shadow var(--duration-sm) var(--ease-out),
             transform var(--duration-sm) var(--ease-out),
             opacity var(--duration-sm) var(--ease-out);
}
.btn:disabled{opacity:0.5;cursor:not-allowed}
.btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.btn:active:not(:disabled){transform:translateY(1px)}

/* Sizes */
.btn--xs{padding:var(--btn-padding-block-xs) var(--btn-padding-inline-xs);font-size:var(--btn-font-size-xs);min-height:24px;min-width:24px} /* WCAG 2.5.8 */
.btn--sm{padding:var(--btn-padding-block-sm) var(--btn-padding-inline-sm);font-size:var(--btn-font-size-sm)}
.btn--md{padding:var(--btn-padding-block-md) var(--btn-padding-inline-md);font-size:var(--btn-font-size-md)}
.btn--lg{padding:var(--btn-padding-block-lg) var(--btn-padding-inline-lg);font-size:var(--btn-font-size-lg)}

/* Touch tap-target floor on coarse pointers. */
@media(pointer:coarse){
  .btn:not(.btn--xs){min-height:var(--btn-min-tap)}
  .account-btn,.icon-btn{min-width:44px;min-height:44px}
}

/* Variants */
.btn--primary{
  background:var(--btn-bg-primary);
  color:var(--btn-text-primary);
  box-shadow:0 2px 0 var(--accent-pressed);
}
.btn--primary:hover:not(:disabled){
  background:color-mix(in srgb, var(--btn-bg-primary) 90%, black);
}
.btn--primary:active:not(:disabled){
  box-shadow:0 0 0 var(--accent-pressed);
}

.btn--ghost{
  background:var(--btn-bg-ghost);
  color:var(--btn-text-ghost);
  border-color:var(--btn-border-ghost);
}
.btn--ghost:hover:not(:disabled){
  background:color-mix(in srgb, var(--btn-text-ghost) 8%, transparent);
}

.btn--destructive{
  background:var(--btn-bg-destructive);
  color:var(--btn-text-destructive);
  box-shadow:0 2px 0 color-mix(in srgb, var(--btn-bg-destructive) 70%, black);
}
.btn--destructive:hover:not(:disabled){
  background:color-mix(in srgb, var(--btn-bg-destructive) 88%, black);
}

.btn--pill{
  background:var(--btn-bg-pill);
  color:var(--btn-text-pill);
  border-color:var(--btn-border-pill);
  border-radius:var(--btn-radius-pill);
}
.btn--pill:hover:not(:disabled){
  background:var(--surface-elevated);
  color:var(--text);
}
.btn--pill.is-active{
  background:var(--accent-soft);
  color:var(--accent);
  border-color:var(--accent);
}

/* Per-accent ghost modifiers via [data-accent] */
.btn--ghost[data-accent="peri"]  {color:var(--peri-deep);  border-color:var(--peri)}
.btn--ghost[data-accent="sky"]   {color:var(--sky-deep);   border-color:var(--sky)}
.btn--ghost[data-accent="honey"] {color:var(--honey-deep); border-color:var(--honey)}
.btn--ghost[data-accent="coral"] {color:var(--coral-deep); border-color:var(--coral)}
.btn--ghost[data-accent="peri"]:hover:not(:disabled)  {background:color-mix(in srgb, var(--peri-deep) 8%, transparent)}
.btn--ghost[data-accent="sky"]:hover:not(:disabled)   {background:color-mix(in srgb, var(--sky-deep) 8%, transparent)}
.btn--ghost[data-accent="honey"]:hover:not(:disabled) {background:color-mix(in srgb, var(--honey-deep) 8%, transparent)}
.btn--ghost[data-accent="coral"]:hover:not(:disabled) {background:color-mix(in srgb, var(--coral-deep) 8%, transparent)}

/* Per-accent primary modifiers — pharma + saq-exam tile flavours */
.btn--primary[data-accent="peri"]{
  background:var(--peri);color:white;
  box-shadow:0 2px 0 var(--peri-deep);
}
.btn--primary[data-accent="peri"]:hover:not(:disabled){background:color-mix(in srgb, var(--peri) 90%, black)}

/* Modifiers */
.btn[data-fullwidth]{width:100%}
.btn[data-icon-only]{gap:0;padding:6px}
.btn[data-icon-only].btn--xs{padding:4px}
.btn[data-shape="round"]{border-radius:var(--radius-pill)}
.btn[data-shape="pill"]{border-radius:var(--btn-radius-pill)}
.btn[data-style="dashed"]{border-style:dashed}
.btn[data-tone="muted"]{color:var(--text-muted);border-color:var(--border)}
.btn[data-tone="muted"]:hover:not(:disabled){color:var(--text);border-color:var(--border-strong);background:var(--surface-elevated)}

/* Grade-coloured ghost (post-reveal recall + exam grade rows). Uses
   data-grade so cinema scope can override via .focus-overlay .btn[data-grade]. */
.btn[data-grade="missed"]   {color:var(--coral-deep); border-color:var(--coral)}
.btn[data-grade="hazy"]     {color:var(--honey-deep); border-color:var(--honey)}
.btn[data-grade="honed"]    {color:var(--sage-deep);  border-color:var(--sage)}
.btn[data-grade="mastered"] {color:var(--grade-mastered); border-color:var(--grade-mastered)}
.btn[data-grade="missed"].is-active   {background:var(--coral-fill);  color:var(--coral-deep)}
.btn[data-grade="hazy"].is-active     {background:var(--honey-fill);  color:var(--honey-deep)}
.btn[data-grade="honed"].is-active    {background:var(--sage-fill);   color:var(--sage-deep)}
.btn[data-grade="mastered"].is-active {background:color-mix(in srgb, var(--grade-mastered) 18%, transparent); color:var(--grade-mastered)}

/* Cinema scope override — primary buttons in .focus-overlay get
   the cream-on-midnight treatment. Show Answer + grade buttons covered.
   Ghost buttons in cinema (close, undo) inherit --fc-chrome-* tokens. */
.focus-overlay .btn--primary{
  background:#1F6B4D;
  color:white;
  box-shadow:0 3px 0 #145437;
}
.focus-overlay .btn--primary:hover:not(:disabled){
  background:color-mix(in srgb, #1F6B4D 92%, black);
}
.focus-overlay .btn--primary[data-grade="missed"]   {background:var(--fc-badge-missed);   box-shadow:0 3px 0 color-mix(in srgb, var(--fc-badge-missed) 70%, black)}
.focus-overlay .btn--primary[data-grade="honed"]    {background:var(--fc-badge-honed);    box-shadow:0 3px 0 color-mix(in srgb, var(--fc-badge-honed) 70%, black)}
.focus-overlay .btn--primary[data-grade="mastered"] {background:var(--fc-badge-mastered); box-shadow:0 3px 0 color-mix(in srgb, var(--fc-badge-mastered) 70%, black)}
.focus-overlay .btn--ghost{
  color:var(--fc-chrome-fg);
  border-color:var(--fc-chrome-border);
  background:var(--fc-chrome-bg);
}
.focus-overlay .btn--ghost:hover:not(:disabled){
  background:color-mix(in srgb, white 12%, transparent);
  color:white;
}
.phase-row-edit{cursor:default}
.phase-row-edit:hover{box-shadow:none}
.phase-row-edit input[type="text"]:focus,
.phase-row-edit input[type="date"]:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent)}
/* Wave 1 — Planner expand: chapter + topic rows */
.planner-tri{font-size:9px;color:var(--text-muted);margin-right:5px;display:inline-block;transition:transform var(--duration-sm);flex-shrink:0}
.planner-chapters{display:flex;flex-direction:column;gap:2px}
.planner-chapter-row{border-radius:var(--radius-sm);overflow:hidden}
.planner-chapter-head{display:flex;align-items:flex-start;gap:7px;flex-wrap:wrap;padding:7px 6px;cursor:pointer;border-radius:var(--radius-sm);transition:background .12s}
.planner-chapter-head:hover{background:var(--surface)}
.planner-ch-label{font-size:var(--font-size-md);flex:1;min-width:0;word-break:break-word}
.planner-fsrs-counts{display:inline-flex;gap:6px;font-size:var(--font-size-xs);font-weight:600;font-family:var(--font-mono);flex-shrink:0;align-items:center}
.planner-hours{font-size:var(--font-size-xs);color:var(--text-muted);font-family:var(--font-mono);flex-shrink:0}
.planner-saq-chip{font-size:var(--font-size-xs);background:var(--surface-alt);color:var(--text-muted);padding:1px 6px;border-radius:var(--btn-radius);flex-shrink:0;white-space:nowrap}
.planner-topics-wrap{display:flex;flex-direction:column;gap:1px;padding:2px 0 4px 22px;border-left:2px solid var(--border);margin:2px 0 4px 14px}
.planner-topic-row{display:flex;align-items:flex-start;gap:7px;flex-wrap:wrap;padding:4px 6px;border-radius:var(--btn-radius);font-size:var(--font-size-sm)}
.planner-topic-row:hover{background:var(--surface)}

/* ── Wave 3 — Planner analytics layer ───────────────────────────────────────
   Coverage heatmap strip (W3a), readiness panel + burn-up (W3b/c/f),
   daily-quota chip (W3d), gap-alert chips (W3e), month calendar (W3g).
   Reuses --surface-*, --accent-*, --green/--amber/--red — no new primitives. */

/* W3a — Coverage heatmap strip (collapsible) */
.planner-coverage{margin:14px 0 4px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-alt);overflow:hidden}
.planner-coverage>summary{padding:9px 12px;cursor:pointer;list-style:none;font-weight:500;font-size:var(--font-size-md);color:var(--text);display:flex;align-items:center;gap:8px}
.planner-coverage>summary::-webkit-details-marker{display:none}
.planner-coverage>summary::before{content:'▶';font-size:9px;color:var(--text-muted);margin-right:2px;transition:transform .12s}
.planner-coverage[open]>summary::before{transform:rotate(90deg)}
.planner-coverage[open]>summary{border-bottom:1px solid var(--border)}
.planner-coverage-grid{padding:10px 12px;display:flex;flex-wrap:wrap;gap:6px}
.planner-coverage-cell{
  flex:0 0 auto;min-width:52px;padding:7px 9px;border-radius:var(--radius-sm);
  border:1px solid var(--border);background:var(--surface);
  display:flex;flex-direction:column;align-items:flex-start;gap:3px;
  cursor:pointer;transition:transform var(--duration-sm),box-shadow var(--duration-sm),border-color var(--duration-sm);
  font-size:var(--font-size-sm);line-height:1.1;color:var(--text);
}
.planner-coverage-cell:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm);border-color:var(--accent)}
.planner-coverage-cell .pcc-code{font-family:var(--font-mono);font-weight:700;font-size:var(--font-size-md)}
.planner-coverage-cell .pcc-tier{font-size:var(--font-size-2xs)}
.planner-coverage-cell .pcc-bar{display:flex;width:100%;height:5px;border-radius:3px;overflow:hidden;background:var(--border);margin-top:2px}
.planner-coverage-cell .pcc-bar i{display:block;height:100%}
.planner-coverage-cell .pcc-bar i.m{background:var(--green)}
.planner-coverage-cell .pcc-bar i.l{background:var(--amber)}
.planner-coverage-cell .pcc-bar i.x{background:var(--red)}
.planner-coverage-cell .pcc-bar i.n{background:var(--border-strong)}
/* Frequency-tier brightness stripe down the left edge */
.planner-coverage-cell.t-red{box-shadow:inset 4px 0 0 var(--red)}
.planner-coverage-cell.t-amber{box-shadow:inset 4px 0 0 var(--amber)}
.planner-coverage-cell.t-green{box-shadow:inset 4px 0 0 var(--green)}
.planner-coverage-cell.empty{opacity:0.5}
.planner-coverage-legend{padding:0 12px 9px;display:flex;flex-wrap:wrap;gap:10px;font-size:var(--font-size-xs);color:var(--text-muted)}
.planner-coverage-legend span{display:inline-flex;align-items:center;gap:4px}
.planner-coverage-legend i{display:inline-block;width:9px;height:9px;border-radius:var(--radius-2xs)}

/* W3b — Readiness panel header */
.planner-readiness{margin:13px 0 12px;padding:13px 14px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface)}
.planner-readiness-row{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;font-size:var(--font-size-md);color:var(--text)}
.planner-readiness-row strong{font-size:15px}
.planner-readiness-row .sep{color:var(--text-faint);font-size:var(--font-size-sm)}
.planner-readiness-bar{position:relative;height:8px;border-radius:var(--radius-tiny);background:var(--surface-alt);margin:8px 0 4px;overflow:hidden}
.planner-readiness-bar i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--green));border-radius:var(--radius-tiny);transition:width .35s ease}
.planner-readiness-target{position:absolute;top:-2px;bottom:-2px;width:2px;background:var(--text-faint);border-radius:1px;opacity:0.55}
.planner-readiness-quota{margin-top:6px;font-size:var(--font-size-md);color:var(--text-muted)}
.planner-readiness-quota.ahead{color:var(--green)}
.planner-readiness-quota.behind{color:var(--red)}
.planner-readiness-toggle{margin-top:9px;display:flex;gap:6px;font-size:var(--font-size-sm);color:var(--text-muted);align-items:center}
.planner-readiness-toggle button{font-size:var(--font-size-sm);padding:4px 9px;border:1px solid var(--border);border-radius:var(--btn-radius);background:transparent;color:var(--text-muted);cursor:pointer}
.planner-readiness-toggle button.active{background:var(--accent-soft);color:var(--accent-pressed);border-color:var(--accent)}

/* W3c — Burn-up trajectory chart canvas */
.planner-burnup-wrap{margin-top:10px;height:160px;position:relative}
.planner-burnup-empty{font-size:var(--font-size-sm);color:var(--text-muted);padding:16px 4px;text-align:center}

/* W3f — Per-section breakdown */
.planner-section-breakdown{margin-top:10px;display:flex;flex-direction:column;gap:4px;border-top:1px dashed var(--border);padding-top:9px}
.planner-section-row{display:flex;align-items:center;gap:8px;font-size:var(--font-size-sm);padding:4px 4px;border-radius:5px}
.planner-section-row:hover{background:var(--surface-alt)}
.planner-section-row .psb-code{font-family:var(--font-mono);font-weight:700;min-width:22px}
.planner-section-row .psb-name{flex:1;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.planner-section-row .psb-pct{font-family:var(--font-mono);min-width:42px;text-align:right;color:var(--text-muted)}
.planner-section-row .psb-status{font-size:var(--font-size-xs);padding:1px 6px;border-radius:var(--btn-radius);border:1px solid var(--border)}
.planner-section-row .psb-status.on_track{color:var(--green);border-color:var(--green-bg);background:var(--green-bg)}
.planner-section-row .psb-status.at_risk{color:var(--amber);border-color:var(--amber-bg);background:var(--amber-bg)}
.planner-section-row .psb-status.behind{color:var(--red);border-color:var(--red-bg);background:var(--red-bg)}

/* W3e — Coverage gap alert chips */
.planner-gap-chip{display:inline-flex;align-items:center;gap:5px;padding:2px 8px;border-radius:var(--btn-radius);font-size:var(--font-size-xs);font-weight:500;background:var(--amber-bg);color:var(--amber);border:1px solid var(--amber-bg);margin:3px 4px 0 0;flex-shrink:0}
.planner-gap-chip.high{background:var(--red-bg);color:var(--red);border-color:var(--red-bg)}

/* W3d — Today header daily quota chip */
.today-quota-chip{display:inline-flex;align-items:center;gap:5px;padding:2px 8px;border-radius:var(--btn-radius);font-size:var(--font-size-xs);font-weight:500;background:var(--accent-soft);color:var(--accent-pressed);border:1px solid var(--accent-soft);margin-left:6px;flex-shrink:0}
.today-quota-chip.ahead{background:var(--green-bg);color:var(--green);border-color:var(--green-bg)}
.today-quota-chip.behind{background:var(--red-bg);color:var(--red);border-color:var(--red-bg)}

/* W3g — Month calendar view */
.planner-view-toggle{display:flex;gap:4px;background:var(--surface-alt);padding:3px;border-radius:var(--radius-sm);border:1px solid var(--border)}
.planner-view-toggle button{font-size:var(--font-size-sm);padding:5px 11px;border:none;border-radius:var(--btn-radius);background:transparent;color:var(--text-muted);cursor:pointer;font-weight:500}
.planner-view-toggle button.active{background:var(--surface);color:var(--text);box-shadow:var(--shadow-sm,0 1px 2px rgba(0,0,0,0.08))}
.planner-month-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;margin:14px 0;font-size:var(--font-size-xs)}
.planner-month-grid .pmg-dow{font-weight:600;color:var(--text-muted);font-size:var(--font-size-xs);text-align:center;padding:3px 0}
.planner-month-grid .pmg-cell{
  aspect-ratio:1/1;min-height:44px;border:1px solid var(--border);border-radius:7px;
  background:var(--surface);padding:4px;display:flex;flex-direction:column;justify-content:space-between;
  cursor:pointer;transition:transform var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm);
}
.planner-month-grid .pmg-cell:hover{transform:translateY(-1px);border-color:var(--accent);box-shadow:var(--shadow-sm)}
.planner-month-grid .pmg-cell.outside{opacity:0.35;cursor:default}
.planner-month-grid .pmg-cell.outside:hover{transform:none;border-color:var(--border);box-shadow:none}
.planner-month-grid .pmg-cell.today{outline:2px solid var(--accent);outline-offset:-2px}
.planner-month-grid .pmg-day{font-family:var(--font-mono);font-weight:600;font-size:var(--font-size-xs);color:var(--text)}
.planner-month-grid .pmg-band{display:block;height:6px;border-radius:3px;background:var(--border-strong)}
.planner-month-grid .pmg-band.rest{background:var(--text-faint)}
.planner-month-grid .pmg-band.light{background:var(--green)}
.planner-month-grid .pmg-band.standard{background:var(--accent)}
.planner-month-grid .pmg-band.intense{background:var(--amber)}
.planner-month-grid .pmg-band.exam-prep{background:var(--red)}
.planner-month-grid .pmg-band.break,
.planner-month-grid .pmg-band.integration{background:transparent;border:1px dashed var(--border-strong)}
.planner-month-grid .pmg-dot{width:6px;height:6px;border-radius:50%;background:var(--accent);align-self:flex-end}
.planner-month-grid .pmg-cell.has-block .pmg-day{color:var(--accent-pressed)}
.planner-month-month-head{display:flex;align-items:center;justify-content:space-between;margin:10px 0 6px;font-weight:600;color:var(--text)}

/* ── Wave 4 — Commit / Retrospective / Rebalancing ─────────────────────────── */
.planner-commit-banner{
  margin:8px 0 0;padding:10px 12px;border-radius:var(--radius-md);
  background:var(--accent-soft);border:1px solid var(--accent);
  color:var(--accent-pressed);font-size:var(--font-size-md);display:flex;flex-wrap:wrap;align-items:center;gap:10px;
}
.planner-commit-banner .pcb-msg{flex:1;min-width:0}
.planner-commit-banner button{
  font-size:var(--font-size-md);padding:6px 12px;border-radius:var(--radius-sm);border:1px solid var(--accent);
  background:var(--accent);color:var(--accent-on);font-weight:600;cursor:pointer;flex-shrink:0;
}
.planner-commit-banner button:disabled{opacity:0.6;cursor:wait}
.planner-commit-banner.locked{background:var(--green-bg);border-color:var(--green);color:var(--green)}

.planner-retro{
  margin:10px 0 0;padding:11px 13px;border:1px solid var(--border);border-radius:var(--radius-md);
  background:var(--surface-alt);color:var(--text);
}
.planner-retro-head{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}
.planner-retro-head strong{font-size:var(--font-size-lg)}
.planner-retro-stats{display:flex;flex-wrap:wrap;gap:8px;margin-top:7px;font-size:var(--font-size-sm);color:var(--text-muted)}
.planner-retro-stats span{display:inline-flex;align-items:center;gap:4px}
.planner-retro-stats b{color:var(--text);font-weight:600}
.planner-retro-coverage{height:6px;border-radius:3px;background:var(--border);overflow:hidden;margin:6px 0;display:flex}
.planner-retro-coverage i{display:block;height:100%}
.planner-retro-coverage i.m{background:var(--green)}
.planner-retro-coverage i.l{background:var(--amber)}
.planner-retro-coverage i.x{background:var(--red)}
.planner-retro-velocity{font-size:var(--font-size-sm);color:var(--text-muted);margin-top:4px}
.planner-retro-velocity.behind{color:var(--red)}
.planner-retro-velocity.ahead{color:var(--green)}

.planner-rebalance{display:flex;flex-direction:column;gap:6px;margin-top:8px;border-top:1px dashed var(--border);padding-top:8px}
.planner-rebalance-row{display:flex;align-items:center;gap:8px;font-size:var(--font-size-sm);flex-wrap:wrap}
.planner-rebalance-row .prr-msg{flex:1;min-width:120px;color:var(--text)}
.planner-rebalance-row button{
  font-size:var(--font-size-sm);padding:4px 10px;border-radius:var(--btn-radius);border:1px solid var(--accent);
  background:transparent;color:var(--accent);font-weight:500;cursor:pointer;
}
.planner-rebalance-row button:hover{background:var(--accent-soft)}

.planner-velocity-line{font-size:var(--font-size-sm);color:var(--text-muted);margin:4px 0 0;font-family:var(--font-mono)}
.planner-velocity-line.warn{color:var(--amber)}
.planner-velocity-line.behind{color:var(--red)}

/* ── Planner C-redesign — pinned rows, runway, dots, stats disclosure ────── */

/* Today / Tomorrow pinned rows */
.planner-pinned{margin:6px 0 12px;display:flex;flex-direction:column;gap:6px}
.planner-pin-row{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:11px 14px;border-radius:var(--radius);border:1px solid var(--border);
  background:var(--surface);
}
.planner-pin-row.today{
  background:var(--accent-soft);border-color:var(--accent);
}
.planner-pin-row .ppr-mark{
  font-size:var(--font-size-xs);font-weight:700;letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);min-width:74px;
}
.planner-pin-row.today .ppr-mark{color:var(--accent-pressed)}
.planner-pin-row .ppr-meta{font-size:var(--font-size-lg);color:var(--text);flex:1;min-width:0}
.planner-pin-row .ppr-meta b{font-weight:600}
.planner-pin-row .ppr-meta .sep{color:var(--text-faint);margin:0 6px}
.planner-pin-row .ppr-action{
  font-size:var(--font-size-md);padding:6px 13px;border-radius:var(--radius-sm);border:1px solid var(--accent);
  background:var(--accent);color:var(--accent-on);font-weight:600;cursor:pointer;flex-shrink:0;
}
.planner-pin-row .ppr-action:hover{filter:brightness(1.08)}
.planner-pin-row.tomorrow{opacity:0.86}
.planner-pin-row .ppr-workload-dot{display:inline-block;width:8px;height:8px;border-radius:50%;vertical-align:middle;margin:0 2px}
.planner-pin-row .ppr-workload-dot.rest{background:var(--text-faint)}
.planner-pin-row .ppr-workload-dot.light{background:var(--green)}
.planner-pin-row .ppr-workload-dot.standard{background:var(--accent)}
.planner-pin-row .ppr-workload-dot.intense{background:var(--amber)}
.planner-pin-row .ppr-workload-dot.exam-prep{background:var(--red)}

/* Exam runway — horizontal proportional strip */
.planner-runway-wrap{margin:10px 0 16px}
.planner-runway-head{display:flex;align-items:baseline;justify-content:space-between;font-size:var(--font-size-sm);color:var(--text-muted);margin-bottom:4px;font-family:var(--font-mono)}
.planner-runway{
  position:relative;display:flex;align-items:stretch;
  height:54px;border-radius:var(--radius-md);background:var(--surface);
  border:1px solid var(--border);overflow:hidden;
  user-select:none;
}
.planner-runway-block{
  position:relative;flex:1 1 0;min-width:0;
  border-right:1px solid var(--border);
  display:flex;flex-direction:column;justify-content:space-between;
  padding:6px 8px;cursor:pointer;
  transition:background .15s,filter .15s;
  overflow:hidden;
}
.planner-runway-block:last-child{border-right:none}
.planner-runway-block:hover{background:var(--accent-soft);filter:brightness(1.04)}
.planner-runway-block.current{background:var(--accent-soft);border-left:3px solid var(--accent)}
.planner-runway-block.done{opacity:0.55}
/* v236 Fix 4 — `studying` ≠ `current`. Date-active block uses sage accent
   (var(--accent)). User-active block uses peri so they're distinguishable
   at a glance when they diverge. When both coincide on the same block,
   `.current.studying` keeps the sage for date primacy + peri ring overlay. */
.planner-runway-block.studying:not(.current){
  background:color-mix(in srgb,var(--peri) 14%,var(--surface));
  border-left:3px solid var(--peri);
}
.planner-runway-block.studying.current{
  box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--peri) 60%,transparent);
}
.planner-runway-block .prb-studying-pill{
  position:absolute;top:4px;right:4px;
  font-size:9px;font-weight:600;letter-spacing:0.04em;text-transform:uppercase;
  padding:1px 6px;border-radius:var(--radius-sm);
  background:var(--peri);color:var(--bg);
  cursor:pointer;line-height:1.4;z-index:2;
  box-shadow:0 1px 0 color-mix(in srgb,var(--peri-deep,var(--peri)) 50%,transparent);
}
.planner-runway-block .prb-studying-pill:hover{filter:brightness(1.1)}
.planner-runway-block .prb-label{
  font-size:var(--font-size-sm);font-weight:600;color:var(--text);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.planner-runway-block .prb-meta{
  font-size:var(--font-size-2xs);color:var(--text-muted);font-family:var(--font-mono);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.planner-runway-block .prb-progress{
  position:absolute;left:0;bottom:0;height:3px;background:var(--accent);
  border-radius:0 1px 0 0;
}
/* Drag handle on right edge of each block (admin-edit mode only) */
.planner-runway-block .prb-handle{
  position:absolute;top:0;right:-3px;bottom:0;width:6px;
  cursor:col-resize;background:transparent;z-index:2;
}
.planner-runway-edit .planner-runway-block .prb-handle{background:var(--accent);opacity:0;transition:opacity .15s}
.planner-runway-edit .planner-runway-block:hover .prb-handle{opacity:0.45}
.planner-runway-edit .planner-runway-block .prb-handle:hover{opacity:1}
.planner-runway-block.dragging{background:var(--accent-soft)}
/* Gap segment for break days between blocks */
.planner-runway-gap{
  flex:1 1 0;min-width:0;background:repeating-linear-gradient(135deg,transparent,transparent 6px,var(--border) 6px,var(--border) 7px);
  display:flex;align-items:center;justify-content:center;
  font-size:var(--font-size-2xs);color:var(--text-muted);font-style:italic;
  border-right:1px solid var(--border);
}
.planner-runway-today{
  position:absolute;top:-2px;bottom:-2px;width:2px;background:var(--accent-pressed);
  pointer-events:none;z-index:3;
}
.planner-runway-today::before{
  content:'';position:absolute;top:-3px;left:-3px;width:8px;height:8px;border-radius:50%;
  background:var(--accent-pressed);
}
.planner-runway-axis{display:flex;justify-content:space-between;font-size:var(--font-size-2xs);color:var(--text-faint);font-family:var(--font-mono);margin-top:3px}

/* Narrow / iOS — runway stacks vertically. Each block becomes a full-width
   row whose HEIGHT (not width) is proportional to days. The today marker
   becomes a horizontal line. Drag handles still work — they just resize
   along the vertical axis. */
@media (max-width: 700px){
  .planner-runway{
    flex-direction:column;align-items:stretch;height:auto;min-height:auto;
    border-radius:var(--radius-md);
  }
  .planner-runway-block{
    border-right:none;border-bottom:1px solid var(--border);
    flex-direction:row;align-items:center;justify-content:space-between;
    padding:9px 12px;
    /* Use min-height proportional to days. flex-grow:<days> still applies, so
       a long block gets more vertical space within the column. */
    min-height:38px;
  }
  .planner-runway-block:last-child{border-bottom:none}
  .planner-runway-block.current{border-left:3px solid var(--accent)}
  .planner-runway-block .prb-label{font-size:var(--font-size-md)}
  .planner-runway-block .prb-meta{font-size:var(--font-size-xs)}
  .planner-runway-block .prb-progress{
    /* Vertical progress bar on the left edge instead of bottom */
    top:0;bottom:0;height:auto;width:3px;border-radius:0 0 1px 0;
  }
  .planner-runway-block .prb-handle{
    /* Bottom edge handle in vertical mode */
    top:auto;right:0;left:0;bottom:-3px;width:auto;height:6px;cursor:row-resize;
  }
  .planner-runway-gap{
    border-right:none;border-bottom:1px solid var(--border);min-height:24px;
    background:repeating-linear-gradient(135deg,transparent,transparent 6px,var(--border) 6px,var(--border) 7px);
  }
  .planner-runway-today{
    /* Horizontal line in vertical stack */
    top:auto;left:-2px;right:-2px;width:auto;height:2px;
  }
  .planner-runway-today::before{
    top:-3px;left:-3px;
  }
  .planner-runway-axis{display:none}
}

/* v237.1 — Queue picker. Each queue is a stacked row: clickable launch
   header on top + collapsible item list below. Items get a left stripe
   coloured by card type so the user can see the mix at a glance. */
.queue-picker-row{
  border:1px solid var(--border);background:var(--surface-alt2);
  border-radius:var(--radius-md);overflow:hidden;
  transition:border-color var(--duration-sm),background var(--duration-sm);
}
.queue-picker-row:hover{border-color:color-mix(in srgb,var(--sky) 35%,var(--border))}
.queue-picker-row[data-color="peri"]{border-left:3px solid var(--peri)}
.queue-picker-row[data-color="sky"]{border-left:3px solid var(--sky)}
.queue-picker-row[data-color="sage"]{border-left:3px solid var(--accent)}
.queue-picker-row[data-color="honey"]{border-left:3px solid var(--honey)}
.queue-picker-row[data-color="coral"]{border-left:3px solid var(--coral)}
.queue-picker-row-top{
  display:flex;align-items:center;gap:10px;width:100%;
  padding:10px 12px;background:transparent;border:none;color:inherit;
  cursor:pointer;font-family:inherit;text-align:left;
}
.queue-picker-row-top:hover{background:color-mix(in srgb,var(--sky) 6%,transparent)}
.qpr-title-col{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.qpr-name{font-size:var(--font-size-md);font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.qpr-meta{font-size:var(--font-size-xs);color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.qpr-launch{font-size:var(--font-size-xs);color:var(--sky);font-weight:600;flex-shrink:0}
.qpr-expand{
  width:100%;padding:6px 12px;
  background:transparent;border:none;border-top:1px dashed var(--border);
  color:var(--text-faint);font-size:var(--font-size-xs);font-weight:500;font-family:inherit;
  cursor:pointer;letter-spacing:0.02em;text-transform:uppercase;
}
.qpr-expand:hover{color:var(--text-muted);background:color-mix(in srgb,var(--sky) 4%,transparent)}
.qpr-expanded .qpr-expand{color:var(--sky-deep,var(--text))}
html.dark .qpr-expanded .qpr-expand{color:var(--sky)}
.qpr-items{padding:0 8px 8px;display:flex;flex-direction:column;gap:4px}
.qpr-items-loading{padding:8px 12px;color:var(--text-muted);font-size:var(--font-size-sm)}
.qpr-item{
  display:flex;align-items:center;gap:8px;
  padding:7px 10px;border-radius:7px;
  background:var(--surface);border:1px solid var(--border);
  cursor:grab;
  transition:transform .1s,box-shadow var(--duration-sm),border-color var(--duration-sm),background var(--duration-sm);
}
.qpr-item:hover{box-shadow:var(--shadow-sm)}
.qpr-item.qpr-dragging{opacity:0.45;cursor:grabbing}
.qpr-item.qpr-drop-target{border-color:var(--sky);background:color-mix(in srgb,var(--sky) 8%,var(--surface))}
/* Card-type stripe — colour matches the surface accent used elsewhere. */
.qpr-item--recall{border-left:3px solid var(--accent)}
.qpr-item--saq   {border-left:3px solid var(--honey)}
.qpr-item--pharma{border-left:3px solid var(--violet)}
.qpr-item--axiom {border-left:3px solid var(--saltbush-deep)}
.qpr-item--fact  {border-left:3px solid var(--peri)}
.qpr-grip{
  font-size:var(--font-size-xs);color:var(--text-faint);letter-spacing:-1px;
  cursor:grab;user-select:none;padding:0 2px;flex-shrink:0;
}
.qpr-item-meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.qpr-item-title{font-size:var(--font-size-md);font-weight:500;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.qpr-item-sub{font-size:var(--font-size-xs);color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.qpr-item-del{
  width:24px;height:24px;flex-shrink:0;
  border:none;background:transparent;color:var(--text-faint);
  border-radius:var(--btn-radius);cursor:pointer;font-size:var(--font-size-lg);line-height:1;
  font-family:inherit;
  transition:background .1s,color .1s;
}
.qpr-item-del:hover{background:color-mix(in srgb,var(--coral) 12%,transparent);color:var(--coral)}

/* Coverage dots — one row, 17 sections */
.planner-dots{display:flex;flex-wrap:wrap;gap:6px;margin:4px 0 14px;align-items:center}
.planner-dots-label{font-size:var(--font-size-xs);color:var(--text-muted);margin-right:4px;font-weight:500}
.planner-dot{
  display:inline-flex;align-items:center;gap:3px;font-size:var(--font-size-2xs);font-family:var(--font-mono);
  color:var(--text-muted);cursor:pointer;padding:2px 6px;border-radius:var(--btn-radius);
  border:1px solid var(--border);transition:transform var(--duration-sm),border-color var(--duration-sm);
}
.planner-dot:hover{transform:translateY(-1px);border-color:var(--accent)}
.planner-dot i{display:inline-block;width:8px;height:8px;border-radius:50%}
.planner-dot.t-red    i{background:var(--red)}
.planner-dot.t-amber  i{background:var(--amber)}
.planner-dot.t-green  i{background:var(--green)}
.planner-dot.empty i{background:var(--border-strong)}
.planner-dot b{color:var(--text);font-weight:600}

/* Stats disclosure — collapses Wave-3 panels */
.planner-stats{margin:14px 0 0;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-alt);overflow:hidden}
.planner-stats>summary{padding:10px 14px;cursor:pointer;list-style:none;font-weight:500;font-size:var(--font-size-md);color:var(--text);display:flex;align-items:center;gap:8px}
.planner-stats>summary::-webkit-details-marker{display:none}
.planner-stats>summary::before{content:'▸';font-size:9px;color:var(--text-muted);margin-right:2px;transition:transform .12s}
.planner-stats[open]>summary::before{transform:rotate(90deg)}
.planner-stats[open]>summary{border-bottom:1px solid var(--border)}
.planner-stats-body{padding:10px 14px;display:flex;flex-direction:column;gap:12px}

/* Setup footer — moved out of the top of the page */
.planner-footer{margin:18px 0 8px;padding:10px 14px;border-top:1px solid var(--border);font-size:var(--font-size-sm);color:var(--text-muted);display:flex;flex-wrap:wrap;gap:10px;align-items:center}

/* Backlog panel — unassigned topics inside expanded block detail */
.gantt-backlog{margin:6px 0 8px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);overflow:hidden}
.gantt-backlog>summary{padding:8px 12px;cursor:pointer;list-style:none;font-weight:500;font-size:var(--font-size-md);color:var(--text);display:flex;align-items:center;gap:8px}
.gantt-backlog>summary::-webkit-details-marker{display:none}
.gantt-backlog>summary::before{content:'▶';font-size:9px;color:var(--text-muted);margin-right:2px;transition:transform .12s}
.gantt-backlog[open]>summary::before{transform:rotate(90deg)}
.gantt-backlog[open]>summary{border-bottom:1px solid var(--border)}
.gantt-backlog-counter{margin-left:auto;color:var(--text-muted);font-family:var(--font-mono);font-size:var(--font-size-xs)}
.gantt-backlog-filters{padding:8px 12px;display:flex;flex-wrap:wrap;gap:5px;border-bottom:1px solid var(--border)}
.gantt-backlog-filters button{
  font-size:var(--font-size-xs);padding:3px 9px;border-radius:var(--btn-radius);border:1px solid var(--border);background:transparent;color:var(--text-muted);cursor:pointer;
}
.gantt-backlog-filters button.active{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-pressed);font-weight:500}
.gantt-backlog-list{padding:6px 8px;display:flex;flex-direction:column;gap:3px;max-height:240px;overflow-y:auto}
.gantt-backlog-item{
  display:flex;align-items:center;gap:6px;padding:5px 8px;border-radius:var(--btn-radius);cursor:pointer;font-size:var(--font-size-sm);
  transition:background var(--duration-sm);
}
.gantt-backlog-item:hover{background:var(--surface-alt)}
.gantt-backlog-item.selected{background:var(--accent-soft);outline:1px solid var(--accent);outline-offset:-1px}
.gantt-backlog-item .gbi-tier{font-size:var(--font-size-xs);width:14px;text-align:center;flex-shrink:0}
.gantt-backlog-item .gbi-code{font-family:var(--font-mono);font-weight:600;color:var(--text);min-width:48px;flex-shrink:0;font-size:var(--font-size-sm)}
.gantt-backlog-item .gbi-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-muted)}
.gantt-backlog-item .gbi-size{font-family:var(--font-mono);font-size:var(--font-size-xs);color:var(--text-faint);flex-shrink:0}
.gantt-backlog-empty{padding:10px;color:var(--text-muted);font-size:var(--font-size-sm);text-align:center;font-style:italic}
.gantt-backlog-help{padding:6px 12px;font-size:var(--font-size-xs);color:var(--text-muted);font-style:italic;border-top:1px solid var(--border);background:var(--surface-alt)}

/* Bottom-sheet overlay — used by plannerCarryForwardSheet,
   plannerAutoDistributeSheet, and others. WS5: tokens + canonical animations.
   z-index:var(--z-sheet)=250 clears tab bar (200). */
.sheet-overlay{
  position:fixed;inset:0;background:var(--backdrop-sheet);z-index:var(--z-sheet);
  display:flex;align-items:flex-end;justify-content:center;
  backdrop-filter:blur(2px);animation:backdropIn .15s ease;
}
.sheet-overlay .sheet,.sheet-overlay .sheet--bottom{
  width:100%;max-width:480px;background:var(--surface-elevated);
  border-radius:var(--radius-lg) var(--radius-lg) 0 0;
  /* Bottom padding clears the in-app tab bar (~64px) AND iOS safe area. */
  padding:18px 18px calc(24px + env(safe-area-inset-bottom,0px) + 64px);
  box-shadow:var(--shadow-lg);
  max-height:90dvh;overflow-y:auto;overscroll-behavior:contain;
  animation:sheetUp var(--duration-md) ease-out;
}
.sheet-overlay .sheet--bottom{max-width:560px}
/* Desktop / wide viewports — drop the tab-bar offset. */
@media (min-width: 700px){
  .sheet-overlay .sheet,.sheet-overlay .sheet--bottom{
    padding:18px 18px 24px;
  }
}
@media (prefers-reduced-motion: reduce){
  .sheet-overlay,.sheet-overlay .sheet,.sheet-overlay .sheet--bottom{animation:none}
}

/* AUDIT-2026-05-06 #9 — confirmDialog / promptDialog (.dlg-*) */
.sheet-overlay .sheet.dlg{padding:22px 20px calc(22px + env(safe-area-inset-bottom,0px) + 64px)}
@media (min-width: 700px){
  .sheet-overlay .sheet.dlg{padding:24px 22px 24px}
}
.dlg-title{font-size:var(--font-size-2xl);font-weight:500;color:var(--text);margin:0 0 6px;line-height:1.3}
.dlg-body{font-size:var(--font-size-md);color:var(--text-muted);margin:0 0 18px;line-height:1.55}
.dlg-input{
  display:block;width:100%;background:var(--surface-bright);color:var(--text);
  border:1px solid var(--border);border-radius:var(--btn-radius);
  padding:10px 12px;font-size:var(--font-size-md);font-family:inherit;
  margin:0 0 6px;
}
.dlg-input:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:transparent}
.dlg-error{font-size:var(--font-size-sm);color:var(--coral-deep);margin:0 0 12px;min-height:1em;line-height:1.4}
.dlg-error:empty{margin:0 0 6px}
.dlg-actions{display:flex;gap:10px;margin-top:6px}
.dlg-btn{
  flex:1;font-family:inherit;font-size:var(--btn-font-size-md);font-weight:500;
  padding:11px 14px;border-radius:var(--btn-radius);cursor:pointer;
  transition:background var(--duration-sm) ease,border-color var(--duration-sm) ease,opacity var(--duration-sm) ease;
}
.dlg-btn--cancel{background:transparent;color:var(--text-muted);border:1px solid var(--border)}
.dlg-btn--cancel:hover{background:var(--surface);border-color:var(--border-strong)}
.dlg-btn--ok{background:var(--accent);color:var(--accent-on);border:1px solid transparent}
.dlg-btn--ok:hover{filter:brightness(1.05)}
.dlg-btn--ok:disabled{opacity:0.45;cursor:not-allowed}
.dlg-btn--destructive{background:var(--btn-bg-destructive);color:var(--btn-text-destructive)}

/* Drag-and-drop — backlog items + assigned chips. touch-action:none prevents
   iOS from scrolling while dragging. Drop targets get a halo while drag is
   active. */
.gantt-backlog-item,.gantt-chip{touch-action:none}
.gantt-cell.drop-target{outline:2px dashed var(--accent);outline-offset:-2px;background:var(--accent-soft)}
.gantt-backlog-list.drop-target{outline:2px dashed var(--red);outline-offset:-2px;background:var(--red-bg)}
.planner-drag-ghost{
  position:fixed;pointer-events:none;z-index:9999;padding:4px 9px;
  border-radius:var(--btn-radius);background:var(--accent);color:var(--accent-on);font-weight:600;
  font-family:var(--font-mono);font-size:var(--font-size-sm);box-shadow:0 4px 12px rgba(0,0,0,0.18);
  transform:translate(-50%,-50%);transition:none;opacity:0.95;
}
.gantt-chip.dragging,.gantt-backlog-item.dragging{opacity:0.4}

/* Header counter pill — N unassigned across upcoming blocks */
.planner-head-pill-warn{display:inline-flex;align-items:center;gap:5px;font-size:var(--font-size-sm);color:var(--amber);padding:3px 10px;border-radius:7px;border:1px solid var(--amber);background:var(--amber-bg);cursor:pointer}
.planner-head-pill-warn:hover{filter:brightness(1.05)}

/* Readiness chip in planner header */
.planner-head-chip{display:inline-flex;align-items:center;gap:6px;font-size:var(--font-size-sm);color:var(--text-muted);padding:3px 10px;border-radius:7px;border:1px solid var(--border);background:var(--surface)}
.planner-head-chip b{color:var(--text);font-weight:600}
.planner-head-chip .phc-bar{display:inline-block;width:42px;height:4px;border-radius:var(--radius-2xs);background:var(--border);overflow:hidden;vertical-align:middle}
.planner-head-chip .phc-bar i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--green))}

.topic-list{margin:11px 0 4px;display:grid;grid-template-columns:repeat(auto-fit,minmax(245px,1fr));gap:6px}
.topic-row{display:flex;align-items:center;padding:7px 11px;border-radius:var(--btn-radius);background:var(--surface);border:1px solid var(--border);font-size:var(--font-size-md);gap:8px;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity .12s}
.topic-row:hover{border-color:var(--accent);background:var(--accent-soft)}
.topic-row .topic-status{font-size:var(--font-size-md);line-height:1;flex:0 0 auto}
.topic-row .topic-code{font-family:var(--font-mono);font-size:var(--font-size-xs);color:var(--text-muted);min-width:54px;flex:0 0 auto;font-weight:600}
.topic-row .topic-name{flex:1;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.topic-row a{display:flex;align-items:center;gap:8px;text-decoration:none;color:inherit;flex:1;overflow:hidden;cursor:pointer}
.topic-row a:hover .topic-name{color:var(--accent)}
.topic-row .topic-stats{font-size:var(--font-size-xs);color:var(--text-faint);font-family:var(--font-mono)}


/* --- Library tabs --- */
.lib-toolbar{display:flex;flex-wrap:wrap;gap:7px;align-items:center;margin:11px 0;padding:10px 12px;background:var(--surface-alt);border:1px solid var(--border);border-radius:var(--radius);font-size:var(--font-size-sm)}
/* §3 R6 — collapsed-defaults disclosure for the recall library toolbar.
   Default-defaults state hides the four selects behind a `Filter ▾`
   summary; details[open] reveals them with §7 fadeIn. */
.lib-filter-disclosure{margin:11px 0;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-alt);overflow:hidden}
.lib-filter-disclosure>summary{padding:10px 13px;cursor:pointer;list-style:none;font-weight:500;font-size:var(--font-size-md);color:var(--text-muted);display:flex;align-items:center;gap:8px}
.lib-filter-disclosure>summary::-webkit-details-marker{display:none}
.lib-filter-disclosure[open]>summary{border-bottom:1px solid var(--border)}
.lib-toolbar--inset{margin:0;border:none;border-radius:0;background:transparent;animation:fadeIn .18s ease both}
.lib-toolbar select{font-family:inherit;font-size:var(--font-size-sm);padding:5px 8px;border:1px solid var(--border);background:var(--surface);color:var(--text);border-radius:var(--btn-radius)}
.lib-toolbar .lib-count{margin-left:auto;color:var(--text-muted);font-size:var(--font-size-xs)}
/* patch-032 round 5 — first .lib-list rule (display:flex column) removed.
   It was unreferenced — the second .lib-list definition (display:grid,
   ~3081) overrode it via cascade. .lib-row rows below are used only by
   the openTopic modal, where they sit inside .topic-block, not .lib-list. */
.lib-row{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:11px 13px;cursor:pointer;display:flex;flex-direction:column;gap:5px;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity .12s}
.lib-row:hover{border-color:var(--accent);box-shadow:var(--shadow-sm)}
.lib-row .lib-title{font-weight:500;font-size:var(--font-size-md);line-height:1.35}
.lib-row .lib-meta{display:flex;gap:6px;flex-wrap:wrap;font-size:var(--font-size-xs);color:var(--text-muted)}
.lib-row .lib-stats{font-family:var(--font-mono);color:var(--text-muted)}
.lib-row.expanded{background:var(--surface-alt2);border-color:var(--accent)}
.lib-row.expanded .lib-detail{display:block}
.lib-row .lib-detail{display:none;padding-top:10px;margin-top:8px;border-top:1px dashed var(--border);font-size:var(--font-size-md);color:var(--text)}
.lib-empty{padding:32px 16px;text-align:center;color:var(--text-muted);background:var(--surface-alt);border-radius:var(--radius)}
/* Library card meta strip — two compact rows: identity + activity. Each
   stat has a Lucide icon anchoring the eye, replacing the squashed
   "1✓ / 0✗ · 100% seen 2026-04-27" string with scannable chunks. */
/* v177 — Was: negative margin pulled the strip OUTSIDE the card padding,
   making it look detached above the card surface. Now: sits flush inside
   the card with a thin solid divider below. */
.lib-meta-strip{
  display:flex;flex-direction:column;gap:5px;
  margin:0 0 10px;padding:0 0 8px;
  border-bottom:1px solid var(--border);font-size:var(--font-size-xs);
}
.lib-meta-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.lib-meta-strip .pill,.lib-meta-strip .badge{font-size:var(--font-size-xs)}
.lib-meta-strip .pill-domain{
  font-family:var(--font-mono);font-weight:700;letter-spacing:0.04em;
  background:var(--surface-alt);color:var(--text);
}
.lib-meta-strip .pill-status{text-transform:capitalize}
.lib-meta-stats{font-family:var(--font-mono);color:var(--text-muted)}
.lib-meta-strip .lib-stat{
  display:inline-flex;align-items:center;gap:4px;font-size:var(--font-size-xs);
  color:var(--text);font-weight:600;
}
.lib-meta-strip .lib-stat .icn{width:11px;height:11px;color:var(--accent);flex-shrink:0}
.lib-meta-strip .lib-stat-faint{color:var(--text-muted);font-weight:400}
.lib-meta-strip .lib-stat-faint .icn{color:var(--text-faint)}
.lib-meta-strip .lib-stat-pct{color:var(--text-muted);font-weight:400;margin-left:1px}

/* ============================================================
   v54-library — Recall library restructure (Direction A)
   ============================================================
   Stats strip → toolbar (search icon, chip groups, dropdowns,
   select toggle) → 3-col card grid → optional Load more →
   sticky bulk-action bar (body-level fixed positioning). */


/* v56-libfix2 — toolbar with 3 child rows (filters, stats, sort).
   On narrow viewports the rows stack vertically (filters → sort →
   stats per user preference). On wide (≥1100px) the rows
   collapse into a single horizontal track with stats centred and
   sort right-aligned. */
.lib-toolbar-v54{
  display:flex;flex-direction:column;gap:10px;
  padding:10px 12px;margin:0 0 14px;
  background:var(--surface-alt);
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
}
.lib-toolbar-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.lib-toolbar-row--filters{justify-content:flex-start;flex:1}
.lib-toolbar-row--sort{justify-content:center}
.lib-toolbar-row--stats{justify-content:center;flex-wrap:nowrap;overflow:hidden;gap:6px}
@media(min-width:1100px){
  .lib-toolbar-v54{flex-direction:row;align-items:center;flex-wrap:nowrap;gap:10px}
  .lib-toolbar-row--filters{flex:0 1 auto;flex-wrap:nowrap;order:1}
  .lib-toolbar-row--stats{flex:0 1 auto;margin:0 auto;order:2}
  .lib-toolbar-row--sort{flex:0 0 auto;order:3}
}
.lib-toolbar-spacer{flex:1;min-width:0}

/* Search wrap — collapsed state shows just the icon button. Open
   state grows the input inline (flex:1) so the chip rows reflow. */
.lib-search-wrap{display:inline-flex;align-items:center;gap:6px;transition:flex-grow .15s}
.lib-search-wrap.is-open{flex:1;min-width:200px}
.lib-search-btn{
  width:32px;height:32px;flex-shrink:0;
  border:1px solid var(--border);background:var(--surface);
  border-radius:var(--radius-sm);cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;
  color:var(--text-muted);transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.lib-search-btn:hover{color:var(--accent);border-color:var(--accent)}
.lib-search-wrap.is-open .lib-search-btn{color:var(--accent);border-color:var(--accent);background:var(--accent-soft)}
.lib-search-btn svg{width:16px;height:16px}
.lib-search-input{
  flex:1;min-width:0;
  font-family:inherit;font-size:var(--font-size-md);
  padding:6px 10px;border:1px solid var(--border);background:var(--surface);
  color:var(--text);border-radius:var(--radius-sm);
  animation:fadeIn .18s ease both;
}
.lib-search-input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}

/* v56-libfix2 — Option B chip format (label inside the chip,
   lowercase muted prefix + bullet sep + value + caret). Used by
   both libChipGroup (custom buttons) and filterSelect (native
   select wrapper) so all toolbar elements share one visual
   language. Active state (non-All) uses sky-blue palette so it's
   distinct from the peri practise hero / select mode. */
.lib-chip-group{display:inline-flex;flex-wrap:wrap;gap:6px;align-items:center;animation:fadeIn .18s ease both}
.lib-chip{
  font-family:inherit;font-size:var(--font-size-sm);font-weight:500;
  padding:5px 10px;border-radius:var(--btn-radius);cursor:pointer;
  border:1px solid var(--border);background:var(--surface);
  color:var(--text);
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
  white-space:nowrap;
  display:inline-flex;align-items:center;gap:5px;
}
.lib-chip:hover{border-color:var(--border-strong)}

/* Expanded chip-group state — multiple chips visible; current
   selection inverts to accent fill so it pops within the row. */
.lib-chip.is-current{
  background:var(--accent-soft);border-color:var(--accent);
  color:var(--accent);font-weight:600;
}

/* Collapsed Option B format: prefix · value caret */
.lib-chip--collapsed{padding:5px 9px}
.lib-chip--collapsed .chip-prefix{
  font-size:var(--font-size-xs);font-weight:500;color:var(--text-muted);
  text-transform:lowercase;letter-spacing:0.02em;
}
.lib-chip--collapsed .chip-sep{
  color:var(--text-muted);opacity:0.55;
  margin:0 1px;
}
.lib-chip--collapsed .chip-val{font-weight:500;color:var(--text)}
.chip-caret{width:11px;height:11px;opacity:0.55;flex-shrink:0;margin-left:2px}

/* Active states — three semantic chip types:
   filter → sky-blue  |  sort → no change  |  group → sage-green */
.lib-chip--collapsed.is-active{
  background:var(--sky-fill,color-mix(in srgb,var(--sky,#2E7EAA) 14%,transparent));
  border-color:color-mix(in srgb,var(--sky,#2E7EAA) 40%,transparent);
}
.lib-chip--collapsed.is-active .chip-prefix{color:var(--sky,#2E7EAA);opacity:1}
.lib-chip--collapsed.is-active .chip-sep   {color:var(--sky,#2E7EAA);opacity:0.75}
.lib-chip--collapsed.is-active .chip-val   {color:var(--sky,#2E7EAA);font-weight:600}
.lib-chip--collapsed.is-active .chip-caret {color:var(--sky,#2E7EAA);opacity:0.75}
/* Cards|List segmented control */
.lib-view-seg{display:flex;align-items:center}
.lib-view-seg__btn{border-radius:0}
.lib-view-seg__btn:first-child{border-radius:6px 0 0 6px}
.lib-view-seg__btn:last-child{border-radius:0 6px 6px 0;margin-left:-1px}
/* group chip: sage-green override */
.lib-chip--group.is-active{
  background:var(--sage-fill,color-mix(in srgb,var(--sage,#4F7050) 14%,transparent));
  border-color:color-mix(in srgb,var(--sage,#4F7050) 40%,transparent);
}
.lib-chip--group.is-active .chip-prefix{color:var(--sage,#4F7050);opacity:1}
.lib-chip--group.is-active .chip-sep   {color:var(--sage,#4F7050);opacity:0.75}
.lib-chip--group.is-active .chip-val   {color:var(--sage,#4F7050);font-weight:600}
.lib-chip--group.is-active .chip-caret {color:var(--sage,#4F7050);opacity:0.75}

/* ── Curriculum + Year picker sheets ─────────────────────────────── */
#curriculumPickerSheet{z-index:var(--z-picker)}
.curriculum-picker-sheet{display:flex;flex-direction:column;max-height:80vh;overflow:hidden}
.picker-header{padding:12px 14px 10px;flex-shrink:0}
.picker-title{font-size:14px;font-weight:700;margin-bottom:10px}
.picker-search{width:100%;padding:8px 12px;border:1px solid var(--border);border-radius:7px;font-family:inherit;font-size:13px;background:var(--surface-bright,#fff);color:var(--text)} /* WS11: removed outline:none; universal :focus-visible baseline now provides ring */
.picker-search:focus{border-color:var(--sky,#2E7EAA)}
.picker-search::placeholder{color:var(--text-faint)}
.picker-body{flex:1;min-height:0;overflow-y:auto;border-top:1px solid var(--border)}
.picker-loading{padding:24px;text-align:center;color:var(--text-muted);font-size:14px}
.picker-section{border-bottom:1px solid var(--border)}
.picker-section-row{display:flex;align-items:center;gap:8px;padding:9px 14px 9px 11px;cursor:pointer;user-select:none;position:relative}
.picker-section-row:hover{background:var(--bg)}
.picker-section-row.is-empty{opacity:.4}
/* v10 (2026-05-19) — phase-color left bar on picker rows. When the row's
   --phase-color is set via inline style (resolved from sectionColor(letter)),
   show a 3 px × 16 px bar at the left edge as a folder-color cue.
   Tier-D discipline #5: never a row tint — hover is var(--accent). */
.picker-section-row[style*="--phase-color"]::before{
  content:'';position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:3px;height:16px;border-radius:var(--radius-2xs);background:var(--phase-color)
}
.picker-toggle{font-size:9px;color:var(--text-faint);width:12px;flex-shrink:0;display:inline-block;transition:transform .15s}
.picker-toggle.open{transform:rotate(90deg)}
.picker-section-name{flex:1;font-size:13px;font-weight:600;color:var(--text)}
.picker-section-meta{font-size:11px;color:var(--text-muted)}
.picker-check{width:16px;height:16px;border:1.5px solid var(--border-strong);border-radius:3px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:10px;color:transparent;transition:background .1s,border-color .1s}
.picker-check.checked {background:var(--sky,#2E7EAA);border-color:var(--sky,#2E7EAA);color:#fff}
.picker-check.indeterm{background:var(--sky-fill,color-mix(in srgb,#2E7EAA 14%,transparent));border-color:var(--sky,#2E7EAA)}
.picker-check.indeterm::after{content:'';display:block;width:8px;height:2px;background:var(--sky,#2E7EAA);border-radius:1px}
.picker-chapters{display:none}
.picker-chapters.open{display:block}
.picker-chapter-row{display:flex;align-items:center;gap:8px;padding:7px 14px 7px 30px;cursor:pointer;background:color-mix(in srgb,var(--bg) 55%,var(--surface));user-select:none}
.picker-chapter-row:hover{background:var(--bg)}
.picker-chapter-row.is-empty{opacity:.35;pointer-events:none}
.picker-chapter-name{flex:1;font-size:12px;color:var(--text-muted);font-weight:500}
.picker-chapter-meta{font-size:11px;color:var(--text-faint)}
.picker-check-sm{width:14px;height:14px;border:1.5px solid var(--border-strong);border-radius:3px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:9px;color:transparent;transition:background .1s}
.picker-check-sm.checked {background:var(--sky,#2E7EAA);border-color:var(--sky,#2E7EAA);color:#fff}
.picker-check-sm.indeterm{background:var(--sky-fill,color-mix(in srgb,#2E7EAA 14%,transparent));border-color:var(--sky,#2E7EAA)}
.picker-check-sm.indeterm::after{content:'';display:block;width:6px;height:2px;background:var(--sky,#2E7EAA);border-radius:1px}
.picker-topics{display:none}
.picker-topics.open{display:block}
.picker-topic-row{display:flex;align-items:center;gap:8px;padding:6px 14px 6px 46px;cursor:pointer;user-select:none}
.picker-topic-row:hover{background:var(--bg)}
.picker-topic-row.is-empty{opacity:.35;pointer-events:none}
.topic-check{width:13px;height:13px;border:1.5px solid var(--border-strong);border-radius:3px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:8px;color:transparent;transition:background .1s}
.topic-check.checked{background:var(--sky,#2E7EAA);border-color:var(--sky,#2E7EAA);color:#fff}
.topic-code{font-size:10px;color:var(--text-faint);min-width:34px}
.topic-name{flex:1;font-size:12px;color:var(--text)}
.topic-count{font-size:10px;color:var(--text-faint)}
.picker-footer{display:flex;align-items:center;padding:10px 12px;border-top:1px solid var(--border);gap:6px;flex-shrink:0}
.picker-footer .btn-sm{background:none;border:1px solid var(--border);color:var(--text-muted);border-radius:7px;padding:7px 11px;font-size:12px;cursor:pointer;font-family:inherit;white-space:nowrap}
.picker-footer .btn-sm:hover{border-color:var(--border-strong)}
.picker-footer .btn-sm.is-active{border-color:var(--border-strong);color:var(--text);font-weight:600}
.picker-footer .btn-apply{flex:1;background:color-mix(in srgb,var(--sky,#2E7EAA) 82%,#000);border:none;color:#fff;border-radius:7px;padding:8px 12px;font-size:13px;font-weight:600;cursor:pointer;font-family:inherit}
/* Year multiselect grid */
.year-picker-grid{display:flex;flex-wrap:wrap;gap:8px;padding:14px}
.year-pill{padding:6px 13px;border:1px solid var(--border);border-radius:7px;background:var(--surface);font-size:13px;color:var(--text-muted);cursor:pointer;font-family:inherit;transition:background .1s,border-color .1s}
.year-pill:hover{border-color:var(--border-strong)}
.year-pill.active{background:var(--sky-fill,color-mix(in srgb,#2E7EAA 13%,transparent));border-color:color-mix(in srgb,var(--sky,#2E7EAA) 45%,transparent);color:var(--sky,#2E7EAA);font-weight:600}
/* Generic filter sheet pills (openFilterSheet) — same style as year-pills */
.filter-sheet-grid{display:flex;flex-wrap:wrap;gap:8px;padding:14px}
.filter-sheet-pill{padding:6px 13px;border:1px solid var(--border);border-radius:7px;background:var(--surface);font-size:13px;color:var(--text-muted);cursor:pointer;font-family:inherit;transition:background .1s,border-color .1s}
.filter-sheet-pill:hover{border-color:var(--border-strong)}
.filter-sheet-pill.active{background:var(--sky-fill,color-mix(in srgb,#2E7EAA 13%,transparent));border-color:color-mix(in srgb,var(--sky,#2E7EAA) 45%,transparent);color:var(--sky,#2E7EAA);font-weight:600}
/* Group header */
.lib-group-header{font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text-muted);padding:8px 4px 4px;border-bottom:1px solid var(--border);margin-bottom:4px;margin-top:12px}
.lib-group-header:first-child{margin-top:0}
/* Select mode card wrapper — bold outline + bg lift, no checkbox */
.lib-selectable-wrap{position:relative;cursor:pointer;border-radius:var(--radius);outline:2px solid transparent;transition:outline-color var(--duration-sm),background .12s}
.lib-selectable-wrap:hover{outline-color:var(--sky-fill,rgba(46,126,170,.18))}
.lib-selectable-wrap.is-selected{outline:2.5px solid var(--sky,#2E7EAA);background:var(--sky-fill,rgba(46,126,170,.08))}

/* filterSelect chip — wraps a native <select> styled as inline text
   with its own caret. Native arrow hidden via appearance:none. */
.lib-chip--select{cursor:pointer}
.chip-select-native{
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  border:none;background:transparent;
  font-family:inherit;font-size:var(--font-size-sm);font-weight:500;
  color:inherit;
  padding:0 2px 0 0;
  cursor:pointer;
  /* WS11: removed outline:none (base + :focus). Universal :focus-visible baseline now rings keyboard focus. */
}
.chip-select-native option{color:var(--text);background:var(--surface)}

/* Card grid — 3-up on wide, 2-up on tablet, 1-up on phone. The
   library-mode card class flag also disables a few Today-only
   affordances (review button, miss-tag overlay, etc.). */
.lib-list{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(280px,1fr));
  gap:12px;
  align-items:start;
  margin:0;
}
@media(min-width:1100px){
  .lib-list{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* Skeleton loading screens — shimmer animation on card outlines */
@keyframes skeleton-shimmer {
  0% { background-position: -1000px 0; }
  100% { background-position: 1000px 0; }
}

/* v172 — Skeleton grid mirrors .recall-group-cards exactly so loading +
   loaded states share dimensions (Issue #9). Was: auto-fill minmax(280px),
   which produced 5 narrow columns on desktop vs the real 3-column layout.
   Now: 3 flex columns on desktop, 2 on tablet, 1 on mobile — same as the
   real recall card grid. */
/* patch-032 round 5 — .skeleton-grid layout retired; renderSkeletonGrid
   uses col-stack(2|3) directly. .skeleton-grid is preserved as the
   col-stack extraClass for the margin reset. */
.skeleton-grid{margin:0}

.skeleton-card {
  /* Shimmer animation removed — skeleton outline sizes didn't match loaded card
     dimensions across all viewport widths. Static surface is more predictable. */
  background: var(--surface-alt2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px; /* v172 — match real .recall-card padding */
  min-height: 160px; /* v236 — recall browse cards median ~140; pad +20 */
  display: flex;
  flex-direction: column;
}
/* v236 — Variant heights re-tuned to current card medians.
   .saq-card-face has min-height:240 (index.html L1828); skeleton matches
   exactly so there's no card-pop on load. .pharma-drug-card collapsed is
   header-only (~50-60px); skeleton uses 72 with a left-stripe accent. */
.skeleton-card--saq{min-height:240px}
.skeleton-card--pharma{min-height:72px;border-left:3px solid color-mix(in srgb,var(--violet) 40%,var(--border))}
.skeleton-card{border-left:3px solid color-mix(in srgb,var(--sage) 40%,var(--border))}
.skeleton-card--saq{border-left:4px solid color-mix(in srgb,var(--honey) 40%,var(--border))}

.skeleton-card-planner {
  background: linear-gradient(
    90deg,
    var(--surface-alt2) 0%,
    color-mix(in srgb, var(--text-muted) 8%, var(--surface-alt2)) 50%,
    var(--surface-alt2) 100%
  );
  background-size: 1000px 100%;
  animation: skeleton-shimmer 2s infinite;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 13px;
  min-height: 100px;
  width: 100%;
}

/* v55-libfix — library-mode card. Single Show Answer button on the
   resting state; in select mode the whole card body becomes the
   selection target (Show Answer hidden, .is-selected paints peri). */
.recall-card--lib .recall-actions--lib{
  display:flex;flex-direction:column;gap:7px;margin-top:9px;
}
.recall-card--lib .recall-actions--lib button{
  padding:9px 13px;border:1.5px solid var(--border);border-radius:var(--radius-sm);
  background:var(--surface);font-size:var(--font-size-md);font-weight:600;color:var(--text);
  font-family:inherit;cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.recall-card--lib .recall-actions--lib button.show{
  color:var(--text);border-color:var(--border);background:var(--surface);
}
.recall-card--lib.revealed .recall-actions--lib button.show{display:none}
.recall-card--lib .recall-actions--lib button.show:hover{
  color:var(--accent);border-color:var(--accent);
}

/* Select mode — Show Answer hidden, whole card becomes a tap target.
   .is-selected paints the card peri (left border + tinted bg) so
   selection reads at a glance. Cursor flips to pointer on the whole
   card. */
.lib-select-mode .recall-card--lib{
  cursor:pointer;
  user-select:none;
}
.lib-select-mode .recall-card--lib .recall-actions--lib{display:none}
.recall-card--lib.is-selected{
  border-color:var(--peri);
  border-left:3px solid var(--peri);
  background:color-mix(in srgb,var(--peri) 12%,var(--surface));
  box-shadow:0 0 0 2px color-mix(in srgb,var(--peri) 25%,transparent);
}
.recall-card--lib.is-selected .recall-prompt,
.recall-card--lib.is-selected .recall-tag a{color:var(--peri-deep)}
html.dark .recall-card--lib.is-selected .recall-prompt,
html.dark .recall-card--lib.is-selected .recall-tag a{color:var(--peri)}

/* Practise hero — top-centred, card-width on desktop, full-width
   on phone. Idle state: peri-filled CTA. Select mode (0 selected):
   helper text on a muted track. Select mode (1+ selected): live
   counter on the peri fill. Cancel link sits below in select mode. */
/* WS2 (Phase 9, 2026-05-05) — .lib-practise-hero* family removed
   (dead code from session 67.1; HTML retired, JS guards never matched).
   Removed: .lib-practise-hero, .lib-practise-hero-main (+ states),
   .lib-practise-hero-cancel + media query. */

/* Load more — bottom-of-list affordance. Spans full width via grid
   column 1 / -1 so it doesn't get squished into a single column. */
.lib-loadmore-wrap{
  grid-column:1 / -1;
  display:flex;justify-content:center;
  margin-top:8px;
}
.lib-loadmore-btn{
  font-family:inherit;font-size:var(--font-size-md);font-weight:500;
  padding:10px 20px;border-radius:var(--radius-sm);
  border:1px dashed var(--border-strong);background:transparent;
  color:var(--text-muted);cursor:pointer;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.lib-loadmore-btn:hover{
  color:var(--accent);border-color:var(--accent);background:var(--accent-soft);
}
.lib-loadmore-btn:disabled{opacity:.6;cursor:default}
/* Sprint D D8 — count line under the show-more button. */
.lib-loadmore-count{
  grid-column:1 / -1;
  text-align:center;font-size:var(--font-size-xs,11px);color:var(--text-faint);
  margin-top:4px;font-variant-numeric:tabular-nums;
}

/* WS2 (Phase 9, 2026-05-05) — .lib-bulk-bar family removed. */
/* Unified library select bar (Phase 3, 2026-05-07) */
.lib-select-bar{position:fixed;bottom:0;left:0;right:0;z-index:200;display:flex;align-items:center;justify-content:space-between;padding:10px 16px calc(10px + env(safe-area-inset-bottom));background:var(--card-bg,var(--surface-elevated));border-top:1px solid var(--border);box-shadow:0 -4px 16px rgba(0,0,0,.12)}
.lib-select-count{font-size:14px;font-weight:600;color:var(--text)}
.lib-select-actions{display:flex;gap:8px}
.lib-select-btn{border:none;border-radius:var(--radius-sm);padding:7px 14px;font-size:14px;font-weight:600;cursor:pointer;transition:background .12s}
.lib-select-btn--ghost{background:var(--bg-secondary,var(--surface-alt));color:var(--text)}
.lib-select-btn--ghost:hover{background:var(--surface-alt)}
/* Sprint D D5 — Start = mint accent; Add-to-queue = sky-blue inserted between Cancel and Start. */
.lib-select-btn--primary{background:var(--mint,#157570);color:#fff}
.lib-select-btn--primary:hover{background:color-mix(in srgb,var(--mint,#157570) 85%,#000)}
.lib-select-btn--primary:disabled{opacity:.45;cursor:default}
.lib-select-btn--queue{background:var(--sage-deep,#2D6B95);color:#fff}
.lib-select-btn--queue:hover{background:color-mix(in srgb,var(--sage-deep,#2D6B95) 85%,#000)}
.lib-select-btn--queue:disabled{opacity:.45;cursor:default}

/* --- Modal overlay (WS5 unified) --- */
.overlay{position:fixed;inset:0;background:var(--backdrop-sheet);z-index:var(--z-sheet);display:none;align-items:flex-end;justify-content:center;backdrop-filter:blur(2px)}
.overlay.active{display:flex;animation:backdropIn .15s}
.overlay .sheet{background:var(--surface-elevated);border-radius:var(--radius-lg) var(--radius-lg) 0 0;width:100%;max-width:780px;max-height:90dvh;overflow-y:auto;overscroll-behavior:contain;box-shadow:var(--shadow-lg);padding:18px 18px max(24px,env(safe-area-inset-bottom));animation:sheetUp var(--duration-md) ease-out}
@media(min-width:600px){.overlay{align-items:center}.overlay .sheet{border-radius:var(--radius-lg);max-height:88dvh}}
@keyframes backdropIn{from{opacity:0}to{opacity:1}}
@keyframes sheetCentreIn{from{transform:translateY(20px);opacity:0}to{transform:none;opacity:1}}
.sheet-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;gap:8px}
.sheet-head h2{margin:0;padding:0;border:none;font-size:18px}
.sheet-close{background:none;border:none;color:var(--text-muted);cursor:pointer;font-size:var(--font-size-3xl);padding:0;width:30px;height:30px;border-radius:var(--btn-radius)}
.sheet-close:hover{background:var(--surface-alt);color:var(--text)}

/* --- Card preview overlay (patch-033 step A revision) ---
   Strong opaque backdrop so the underlying tab is fully isolated; card
   itself is solid (no cinema-mode alpha leakage). Close button moves INSIDE
   the card chrome top-right (sheet-close pattern), no floating outside. */
.preview-overlay{position:fixed;inset:0;background:var(--backdrop-preview);z-index:var(--z-preview);display:none;align-items:flex-start;justify-content:center;padding:max(6dvh,env(safe-area-inset-top,0)) max(16px,env(safe-area-inset-right,0)) max(6dvh,env(safe-area-inset-bottom,0)) max(16px,env(safe-area-inset-left,0));backdrop-filter:blur(10px);overflow-y:auto;overscroll-behavior:contain}
.preview-overlay.active{display:flex;animation:backdropIn .15s}
.preview-box{position:relative;width:100%;max-width:680px;margin:auto 0}
/* Modal-UI mode (exam builder, queue picker, compare overlay, sitting browser, etc.):
   #previewBody is the opaque surface. Card-preview mode strips this via .preview-body--card
   so the fc-card--preview provides its own surface. */
#previewBody{background:var(--surface-elevated);border-radius:var(--radius-lg);border:1px solid var(--border);overflow:hidden}
#previewBody.preview-body--card{background:transparent;border:none;border-radius:0;overflow:visible}
/* Floating × — only shown in card-preview mode; modal UI provides its own close button */
#previewCloseBtn{display:none}
.preview-box:has(#previewBody.preview-body--card) #previewCloseBtn{display:flex}
.preview-close{position:absolute;top:14px;right:14px;width:32px;height:32px;border-radius:50%;background:var(--surface);border:1px solid var(--border);color:var(--text-muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;z-index:5}
.preview-close:hover{color:var(--text);border-color:var(--accent);background:var(--bg)}
.preview-close .icn{width:14px;height:14px}
@media(prefers-reduced-motion:reduce){.preview-overlay.active{animation:none}}

/* Preview-mode fc-card: SOLID surfaces (override any cinema alpha), strong
   border + shadow, drop the focus-mode type-label pill. */
.fc-card--preview{
  background:var(--bg) !important;
  border:1px solid var(--border);
  box-shadow:var(--shadow-lg);
  max-width:100%;
  position:relative;
  padding-top:18px;
}
.fc-card--preview .fc-type-label,
.fc-card--preview .fc-type-row{display:none}
.fc-card--preview .fc-answer{
  display:block !important;
  background:var(--surface) !important;
  border:1px solid var(--border);
  margin:0 24px 18px;
}
/* Hide the focus-mode reveal-mode chrome inside preview */
.fc-card--preview .fc-show-btn,
.fc-card--preview .fc-confidence,
.fc-card--preview .fc-action-bar,
.fc-card--preview .fc-timer-pomodoro,
.fc-card--preview .fc-swipe-wash,
.fc-card--preview .miss-tag-overlay{display:none !important}

/* Sprint J — .browse-actions CSS DELETED. _browseActions() removed from all
   library/browse surfaces; Flip/Queue/Drill row no longer emitted. */

/* Cards in browse mode (library): cursor and grade-chain suppression */
.recall-card--browse,.fc-card--preview{cursor:default}
.recall-card--browse.revealed .recall-prompt{cursor:pointer}
/* Library cards: hide grade chain (cards are pre-revealed, read-only) */
.recall-card--browse .recall-actions{display:none}
/* Sprint J — .self-test and .browse-actions CSS DELETED (Flip button removed,
   self-test mode can no longer be entered). */
/* SAQ library: grade footer hidden */
.saq-card--browse .saq-card-cf-footer{display:none}

/* --- Search palette --- */
.search-palette{position:fixed;inset:0;background:var(--backdrop-sheet);z-index:var(--z-palette);display:none;align-items:flex-start;justify-content:center;padding-top:max(14dvh,env(safe-area-inset-top,14vh));padding-bottom:env(safe-area-inset-bottom,0);backdrop-filter:blur(2px)}
.search-palette.active{display:flex;animation:backdropIn .15s}
.search-box{background:var(--bg);border-radius:var(--radius);width:90%;max-width:560px;box-shadow:var(--shadow-lg);overflow:hidden}
.search-input-row{position:relative;display:flex;align-items:stretch;border-bottom:1px solid var(--border)}
.search-input-row input{flex:1;width:100%;padding:15px 18px;border:none;font-size:15px;background:var(--bg);color:var(--text);font-family:inherit;border-bottom:none} /* WS11: removed outline:none; universal :focus-visible baseline now provides ring */
.search-explore-btn{position:absolute;right:0;top:0;bottom:0;background:color-mix(in srgb,var(--sky,#38bdf8) 18%,var(--bg));color:color-mix(in srgb,var(--sky,#38bdf8) 80%,var(--text));border:none;border-left:1.5px solid color-mix(in srgb,var(--sky,#38bdf8) 35%,transparent);padding:0 18px;font-weight:600;font-size:14px;cursor:pointer;font-family:inherit;transition:background .12s}
.search-explore-btn:hover{background:color-mix(in srgb,var(--sky,#38bdf8) 28%,var(--bg))}
.search-explore-btn[hidden]{display:none}
.search-box input{width:100%;padding:15px 18px;border:none;outline:none;font-size:15px;background:var(--bg);color:var(--text);font-family:inherit;border-bottom:1px solid var(--border)}
.search-results{max-height:60vh;max-height:60dvh;overflow-y:auto}
.search-result{padding:11px 16px;cursor:pointer;display:flex;align-items:center;gap:11px;border-bottom:1px solid var(--border);font-size:var(--font-size-md);transition:background .1s}
.search-result:hover,.search-result.active{background:var(--accent-soft)}
.search-result .sr-icon{font-size:var(--font-size-lg);flex:0 0 auto}
.search-result .sr-type{font-size:var(--font-size-xs);color:var(--text-muted);text-transform:uppercase;letter-spacing:0.05em;margin-left:auto}
.search-empty{padding:20px;text-align:center;color:var(--text-muted);font-size:var(--font-size-md)}

/* --- Settings panel --- */
.settings-backdrop{position:fixed;inset:0;z-index:var(--z-settings);display:none}
.settings-backdrop.active{display:block}
.settings-panel{position:fixed;top:0;right:0;bottom:0;width:360px;max-width:92vw;background:var(--bg);border-left:1px solid var(--border);z-index:254;display:none;box-shadow:var(--shadow-lg);padding:max(18px,env(safe-area-inset-top,0)) 18px max(18px,env(safe-area-inset-bottom,0));overflow-y:auto;animation:slideRight var(--duration-md) ease-out}
.settings-panel.active{display:block}
/* Lore tab account section — reuses settings-row chrome */
.lore-account-section{border-top:1px solid var(--border);margin-top:24px;padding-top:4px}
/* Onboarding push notification sub-toggles */
.ob-push-row{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:6px}
.ob-hint--inline{font-size:var(--font-size-sm);color:var(--text-muted)}
.ob-optional{font-size:var(--font-size-xs);font-weight:400;color:var(--text-muted);margin-left:4px}
.ob-push-prefs{margin-top:8px;padding:8px 10px;background:var(--surface);border-radius:var(--radius-sm);display:flex;flex-direction:column;gap:8px}
.ob-push-sub{display:flex;align-items:center;justify-content:space-between;gap:8px}
/* Pomodoro durations disclosure */
.pom-durations-details{width:100%}
.pom-durations-summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:6px;user-select:none}
.pom-durations-summary::-webkit-details-marker{display:none}
.pom-durations-summary::after{content:'›';margin-left:auto;font-size:var(--font-size-xl);color:var(--text-muted);transition:transform .15s}
.pom-durations-details[open] .pom-durations-summary::after{transform:rotate(90deg)}
.pom-durations-grid{margin-top:12px}
/* Settings → "Profile & account" shortcut row */
.settings-lore-link{display:flex;align-items:center;justify-content:space-between;width:100%;padding:10px 0;background:none;border:none;border-top:1px solid var(--border);color:var(--accent);font-family:inherit;font-size:var(--font-size-md);font-weight:500;cursor:pointer;margin-top:4px;gap:6px}
.settings-lore-link:hover{opacity:.75}
@keyframes slideRight{from{transform:translateX(20px);opacity:0}to{transform:none;opacity:1}}
/* WS5 — prefers-reduced-motion guards for all sheet surfaces */
@media(prefers-reduced-motion:reduce){
  .settings-panel{animation:none}
  .search-palette.active{animation:none}
  .overlay.active{animation:none}
  .overlay .sheet{animation:none}
  .badge-sheet-backdrop{animation:none}
  .badge-sheet-inner{animation:none}
}
.settings-row{display:flex;align-items:center;justify-content:space-between;padding:12px 0;border-bottom:1px solid var(--border);gap:10px}
.settings-row:last-child{border-bottom:none}
.settings-row .s-label{font-size:var(--font-size-lg);font-weight:500}
.settings-row .s-desc{font-size:var(--font-size-sm);color:var(--text-muted);margin-top:2px}
/* S-P1-03 — toggle converted to <button role="switch">; reset button chrome */
.toggle{position:relative;width:42px;height:24px;background:var(--surface-alt);border-radius:var(--radius);cursor:pointer;flex:0 0 auto;border:1px solid var(--border);transition:background .15s;padding:0;outline:none;-webkit-appearance:none;appearance:none}
.toggle.on{background:var(--accent)}
.toggle::after{content:"";position:absolute;width:18px;height:18px;border-radius:50%;background:white;top:2px;left:2px;box-shadow:0 1px 3px rgba(0,0,0,0.18);transition:left .18s}
.toggle.on::after{left:21px}
.toggle:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 35%,transparent)}
/* AUDIT-2026-05-06 #30 — Touch hit area expansion. Visual chip stays slim
   (42×24) per design; ::before adds invisible 44×44 hit target on coarse
   pointers (iOS HIG mandate). Same pattern for icon-only xs buttons that
   previously rendered ~32×32 on touch. */
@media (pointer:coarse){
  .toggle::before{content:"";position:absolute;inset:-10px -1px;}
  .btn[data-icon-only].btn--xs{position:relative;}
  .btn[data-icon-only].btn--xs::before{content:"";position:absolute;inset:-6px;}
}
.settings-section-header{font-size:var(--font-size-xs);font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted);padding:18px 0 5px;margin-top:2px}
.settings-section-header:first-of-type{padding-top:8px;margin-top:0}
/* ── v107 grouped-inset settings ──────────────────────────────────
   Each section's rows sit in a .s-group card under its header.
   Rows keep their global border-bottom divider; the card clips them
   and the last child drops its divider. */
.s-group{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);margin:4px 0 12px;overflow:hidden}
.s-group .settings-row{padding-left:16px;padding-right:16px}
.s-group>.settings-row:last-child,.s-group>.settings-advanced:last-child{border-bottom:none}
.s-group>.settings-advanced{margin-top:0;border-top:none;padding:0 16px 4px}
.s-group>.settings-advanced .settings-row{padding-left:0;padding-right:0}
.s-group--danger{border-color:var(--coral)}
.settings-section-header--danger{color:var(--coral-deep)}
html.dark .settings-section-header--danger{color:var(--coral)}
/* Reveal rows (new-card limit, review-cap presets) — nested under their toggle */
.settings-row--reveal{border-left:3px solid var(--accent-soft);background:var(--surface-elevated)}
.s-group .settings-row--reveal{padding-left:20px}
.settings-row--reveal .s-label{font-size:var(--font-size-md);color:var(--text-muted-strong)}
/* patch-028 — drug reverse-card direction chips (Settings → Study) */
.settings-row--column{flex-direction:column;align-items:stretch;gap:10px}
.reverse-chips{display:flex;flex-wrap:wrap;gap:6px}
.reverse-chip{padding:6px 12px;border:1.5px solid var(--border);border-radius:var(--radius-pill);background:var(--surface);color:var(--text-muted);font-family:inherit;font-size:var(--font-size-sm);font-weight:500;cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),opacity .12s}
.reverse-chip[aria-checked="true"]{border-color:var(--violet);color:var(--violet-deep);background:color-mix(in srgb,var(--violet) 10%,var(--surface));font-weight:600}
.reverse-chip--locked{opacity:.55;cursor:not-allowed;border-style:dashed}
/* Retention slider (legacy single-slider, kept for non-Settings call sites) */
.retention-slider-wrap{display:flex;align-items:center;gap:8px}
.retention-slider-wrap input[type=range]{width:80px;accent-color:var(--accent);cursor:pointer}
.retention-slider-wrap span{font-size:var(--font-size-sm);font-weight:700;min-width:30px;text-align:right;color:var(--accent)}
/* C10d — Per-class FSRS retention sliders. Four-row stacked grid keyed by
   --type-* tokens so each class reads at a glance (recall=sky, saq=rose,
   pharma=violet, axiom=saltbush). */
.fsrs-class-sliders{display:grid;grid-template-columns:1fr;gap:8px;margin-top:6px}
.fsrs-class-slider{display:grid;grid-template-columns:84px 1fr 48px;align-items:center;gap:10px;padding:6px 10px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface)}
.fsrs-class-slider[data-class="recall"]{border-left:3px solid var(--type-recall,#2D6B95)}
.fsrs-class-slider[data-class="saq"]{border-left:3px solid var(--type-saq,#A82840)}
.fsrs-class-slider[data-class="pharma"]{border-left:3px solid var(--type-pharma,#5E3E9E)}
.fsrs-class-slider[data-class="axiom"]{border-left:3px solid var(--type-axiom,#5E6670)}
.fsrs-class-slider-label{font-size:var(--font-size-sm);font-weight:600;color:var(--text)}
.fsrs-class-slider-range{width:100%;accent-color:var(--accent);cursor:pointer}
.fsrs-class-slider-value{font-size:var(--font-size-sm);font-weight:700;text-align:right;color:var(--accent);font-variant-numeric:tabular-nums}
/* Settings display name input */
.settings-name-input{flex:1;padding:5px 8px;border:1px solid var(--border);border-radius:var(--btn-radius);font-size:var(--font-size-md);font-family:inherit;background:var(--surface);color:var(--text);min-width:0}
.settings-name-input:focus{outline:none;border-color:var(--accent)}
/* Reset study data — confirmation sheet */
.reset-study-data-backdrop{z-index:256;background:var(--backdrop-sheet);backdrop-filter:blur(2px)}
.reset-study-data-sheet{position:fixed;bottom:0;left:50%;transform:translateX(-50%) translateY(110%);width:100%;max-width:540px;background:var(--surface-elevated);border-radius:var(--radius-lg) var(--radius-lg) 0 0;z-index:258;transition:transform var(--duration-md) var(--ease-sheet-spring);max-height:90dvh;overflow-y:auto;overscroll-behavior:contain;display:flex;flex-direction:column}
.reset-study-data-sheet.active{transform:translateX(-50%) translateY(0)}
.reset-study-data-body{padding:0 20px max(32px, calc(20px + env(safe-area-inset-bottom,0px)));display:flex;flex-direction:column;gap:14px}
.reset-study-will{background:var(--bg);border-radius:var(--radius-md);padding:12px 14px}
.reset-study-will--preserve{background:var(--surface);border:1px solid var(--border)}
.reset-study-will-label{font-size:var(--font-size-xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;margin-bottom:8px}
.reset-study-will-label--delete{color:var(--coral)}
.reset-study-will-label--keep{color:var(--text-muted)}
.reset-study-list{margin:0;padding-left:16px;display:flex;flex-direction:column;gap:4px}
.reset-study-list li{font-size:var(--font-size-md);color:var(--text);line-height:1.45}
.reset-study-warning{margin:0;font-size:var(--font-size-md);font-weight:600;color:var(--coral);text-align:center}
.reset-study-actions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;margin-top:4px}
.reset-study-confirm-btn{padding:8px 18px;font-size:var(--font-size-md)}
/* Version footer */
.settings-version{text-align:center;padding:20px 0 6px;font-size:var(--font-size-sm);color:var(--text-muted);letter-spacing:.03em}
/* ════ Settings redesign (v106) — search, theme switcher, segmented controls, stepper ════ */
/* Settings search — live filter */
.settings-search-wrap{padding:2px 0 10px;border-bottom:1px solid var(--border);margin-bottom:2px}
.settings-search{position:relative;display:flex;align-items:center}
.settings-search .icn{position:absolute;left:10px;width:15px;height:15px;color:var(--text-faint);pointer-events:none}
.settings-search input{width:100%;padding:9px 12px 9px 32px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);font-family:inherit;font-size:var(--font-size-md);-webkit-appearance:none;appearance:none}
.settings-search input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 30%,transparent)}
.settings-search input::placeholder{color:var(--text-faint)}
.settings-row.s-hidden,.settings-advanced.s-hidden,.settings-section-header.s-hidden{display:none !important}
.settings-no-results{text-align:center;color:var(--text-faint);font-size:var(--font-size-md);padding:28px 0}
/* Full-width label-less theme switcher */
.theme-hero{padding:12px 0 4px}
.theme-seg{display:flex;width:100%;border:1px solid var(--border);border-radius:var(--radius-pill);padding:3px;gap:2px;background:var(--surface)}
.theme-seg-btn{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:9px 0;border:none;background:transparent;color:var(--text-muted);font-family:inherit;font-size:var(--font-size-md);font-weight:500;border-radius:var(--radius-pill);cursor:pointer;transition:background var(--duration-sm),color .12s}
.theme-seg-btn .icn{width:15px;height:15px}
.theme-seg-btn.on{background:var(--accent);color:var(--accent-on)}
/* Segmented control — text size, review-cap presets */
.seg-control{display:inline-flex;border:1px solid var(--border);border-radius:var(--radius-pill);padding:2px;gap:2px;background:var(--surface)}
.seg-control--start{align-self:flex-start}
.seg-btn{border:none;background:transparent;color:var(--text-muted);font-family:inherit;font-size:var(--font-size-sm);font-weight:600;padding:5px 14px;border-radius:var(--radius-pill);cursor:pointer;transition:background var(--duration-sm),color .12s}
.seg-btn.on{background:var(--accent);color:var(--accent-on)}
/* Numeric stepper — unified replacement for bare number inputs */
.s-stepper{display:inline-flex;align-items:center;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);overflow:hidden;flex:0 0 auto}
.s-stepper button{width:30px;height:32px;border:none;background:transparent;color:var(--text-muted);font-size:18px;line-height:1;cursor:pointer;display:grid;place-items:center;transition:background var(--duration-sm),color .12s}
.s-stepper button:hover{background:var(--surface-alt);color:var(--accent)}
.s-stepper-val{min-width:46px;text-align:center;font-size:var(--font-size-md);font-variant-numeric:tabular-nums;padding:0 6px;border-left:1px solid var(--border);border-right:1px solid var(--border);height:32px;display:grid;place-items:center}
/* Text size — scales every --font-size-* token (default M = 1.0; opt-in S/L/XL) */
html[data-text-size="s"]{--font-scale:.92}
html[data-text-size="m"]{--font-scale:1}
html[data-text-size="l"]{--font-scale:1.1}
html[data-text-size="xl"]{--font-scale:1.22}
html[data-text-size]{--font-size-2xs:calc(10px*var(--font-scale,1));--font-size-xs:calc(11px*var(--font-scale,1));--font-size-sm:calc(12px*var(--font-scale,1));--font-size-md:calc(13px*var(--font-scale,1));--font-size-lg:calc(14px*var(--font-scale,1));--font-size-xl:calc(16px*var(--font-scale,1));--font-size-2xl:calc(17px*var(--font-scale,1));--font-size-3xl:calc(22px*var(--font-scale,1));--font-size-2xs-plus:calc(11px*var(--font-scale,1));--font-size-sm-plus:calc(12.5px*var(--font-scale,1));--font-size-lg-plus:calc(15px*var(--font-scale,1))}
/* Reduce motion — user opt-in (complements prefers-reduced-motion). .001ms keeps transitionend firing. */
html[data-reduce-motion="1"] *,html[data-reduce-motion="1"] *::before,html[data-reduce-motion="1"] *::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;scroll-behavior:auto !important}
/* S-P1-04 — Settings utility button / input / select classes */
.btn-ghost--accent{padding:6px 14px;border:1.5px solid var(--accent);background:var(--surface);color:var(--accent);border-radius:var(--radius-sm);font-family:inherit;font-size:var(--font-size-sm);font-weight:600;cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);white-space:nowrap}
.btn-ghost--accent:disabled{opacity:.45;cursor:not-allowed}
.btn-debug{padding:7px 14px;border:1px solid var(--border);background:var(--surface);color:var(--text);border-radius:var(--btn-radius);cursor:pointer;font-family:inherit;font-size:var(--font-size-sm);transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm);white-space:nowrap}
.select-compact{padding:5px 8px;border:1px solid var(--border);background:var(--surface);color:var(--text);border-radius:var(--btn-radius);font-family:inherit;font-size:var(--font-size-sm)}
.input-compact{padding:5px 8px;border:1px solid var(--border);background:var(--surface);color:var(--text);border-radius:var(--btn-radius);font-family:inherit}
.input-time{width:54px;padding:4px 6px;border:1px solid var(--border);background:var(--surface);color:var(--text);border-radius:var(--radius-tiny);font-family:inherit;text-align:center}
/* S-P2-04 — display-name save note */
.saved-note{font-size:var(--font-size-xs);color:var(--sage);margin-left:6px;opacity:0;transition:opacity .2s}
.saved-note.visible{opacity:1}
/* S-P1-04 pass 2 — Settings structural / layout classes */
.sheet-head h2{margin:0;font-size:18px;border:none;padding:0;display:block}
.settings-row--block{display:block}
/* RICHCARDS v3 §14 — collapsible advanced toggles for the enrichments group. */
.settings-advanced{margin-top:6px;border-top:0.5px dashed var(--border);padding-top:4px}
.settings-advanced-summary{font-size:var(--font-size-sm);color:var(--text-muted);padding:8px 0;cursor:pointer;list-style:none;user-select:none}
.settings-advanced-summary::-webkit-details-marker{display:none}
.settings-advanced-summary::before{content:'▸ ';font-size:9px;display:inline-block;width:12px;color:var(--text-muted)}
.settings-advanced[open] .settings-advanced-summary::before{content:'▾ '}
.settings-advanced.is-disabled .settings-row{opacity:0.45;pointer-events:none}
.settings-advanced.is-disabled .settings-advanced-summary{opacity:0.6}
.s-row-fill{flex:1;min-width:0}
.s-input-row{display:flex;align-items:center;gap:0}
.s-label-icn{width:14px;height:14px;vertical-align:-2px;margin-right:6px}
.s-label--mb{margin-bottom:6px}
.s-label--mb-xs{margin-bottom:4px}
.s-label--mb-lg{margin-bottom:8px}
.s-label--spread{display:flex;align-items:center;justify-content:space-between;gap:10px}
.s-desc--mb{margin-bottom:6px}
.s-desc--mb-lg{margin-bottom:8px}
.s-desc--mb-xs{margin-bottom:4px}
.s-desc--mt{margin-top:6px}
.s-desc--mt-lg{margin-top:8px}
.s-kv-grid{display:grid;grid-template-columns:1fr auto;gap:6px 10px;font-size:var(--font-size-sm);align-items:center}
/* v172 P3 — narrow viewports stack label-above-input so longer labels
   ("Pomodoros per cycle") never collide with the number input (Issue #3). */
@media(max-width:480px){
  .s-kv-grid{grid-template-columns:1fr;gap:4px}
  .s-kv-grid > input,.s-kv-grid > select{justify-self:start;margin-bottom:6px}
}
.s-notif-prefs{margin-top:10px;padding:10px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface)}
.s-notif-grid{display:grid;grid-template-columns:1fr auto auto;gap:8px 12px;align-items:center;font-size:var(--font-size-sm)}
.s-notif-grid--2{grid-template-columns:1fr auto}
.s-notif-divider{margin-top:10px;padding-top:10px;border-top:1px dashed var(--border)}
.s-notif-label{color:var(--text);font-weight:600}
.s-notif-admin{margin-top:10px}
.s-action-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:10px}
.s-btn-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.s-chip-row{display:flex;gap:6px;flex-wrap:wrap}
.s-status{margin-top:6px;font-style:italic;min-height:1.2em}

/* --- Sign-in screen --- */
.signin-overlay{position:fixed;inset:0;background:var(--bg);z-index:200;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px}
.signin-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);padding:32px 28px;max-width:380px;width:100%;text-align:center;box-shadow:var(--shadow-md)}
.signin-card h2{margin:0 0 6px;font-size:var(--font-size-3xl);border:none;padding:0;display:block}
.signin-card .subtitle{font-size:var(--font-size-md);margin-bottom:22px;display:block}
.signin-card input{width:100%;padding:11px 13px;border:1.5px solid var(--border);border-radius:var(--radius-sm);font-size:15px;font-family:inherit;background:var(--surface);color:var(--text);margin-bottom:11px;outline:none}
.signin-card input:focus{border-color:var(--accent)}
/* WS2 (Phase 9, 2026-05-05): .signin-card button cascade removed
   (Ambiguity #5). #signinBtn now wears .btn .btn--primary .btn--md
   [data-fullwidth] explicitly. */
.signin-msg{margin-top:14px;font-size:var(--font-size-md);color:var(--text-muted)}
.signin-msg.success{color:var(--green)}
.signin-msg.error{color:var(--red)}
.signin-skip{margin-top:14px;background:none;border:none;color:var(--text-muted);font-size:var(--font-size-sm);cursor:pointer;text-decoration:underline;padding:0;width:auto;box-shadow:none}
.signin-skip:hover{color:var(--text)}
.signin-google-btn{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;padding:11px;border:1.5px solid var(--border);background:var(--surface);color:var(--text);border-radius:var(--radius-md);font-size:var(--font-size-lg);font-weight:600;cursor:pointer;box-shadow:none;margin-bottom:0}
.signin-google-btn:hover{background:var(--bg);border-color:var(--text-muted);transform:translateY(-1px)}
.signin-google-btn:active{transform:translateY(1px)}
.signin-google-btn:disabled{opacity:0.6;cursor:wait;transform:none}
.signin-divider{display:flex;align-items:center;gap:10px;margin:14px 0;color:var(--text-muted);font-size:var(--font-size-sm)}
.signin-divider::before,.signin-divider::after{content:'';flex:1;height:1px;background:var(--border)}
/* R-022 — restore-banner overlay card (pending-deletion boot path).
   Separate class so dark-mode tokens apply without inline styles. */
.restore-banner-card{max-width:380px;width:100%;text-align:center}
.restore-banner-card h2{margin:0 0 8px;font-size:20px}
.restore-banner-card p{margin:0 0 18px;font-size:var(--font-size-md);color:var(--text-muted);line-height:1.5}
.restore-banner-card .btn-restore{
  width:100%;padding:11px;border:none;background:var(--accent);color:white;
  border-radius:var(--radius-md);font-size:var(--font-size-lg);font-weight:700;cursor:pointer;margin-bottom:10px;
  box-shadow:0 2px 0 var(--accent-pressed);
}
.restore-banner-card .btn-restore:hover{transform:translateY(-1px);box-shadow:0 3px 0 var(--accent-pressed)}
.restore-banner-card .btn-signout{
  width:100%;padding:10px;border:1.5px solid var(--border);background:var(--surface);
  color:var(--text);border-radius:var(--radius-md);font-size:var(--font-size-md);cursor:pointer;
}

/* §4A v9.1 — the floating Pomodoro hub CSS retired. The .pom-* classes
   (.pom-hub, .pom-collapsed, .pom-panel, .pom-time, etc.) and the
   pomPulse keyframe were deleted with the markup in Phase 2. The state
   machine + duration settings live on so the Start Focus button label
   reflects the current focus length. AP13. */

/* Focus Mode old stubs — replaced by .fc-* system below */
.focus-end button{padding:12px 28px;border:none;background:var(--accent);color:white;border-radius:var(--radius-md);font-size:var(--font-size-lg);font-weight:700;cursor:pointer;box-shadow:0 3px 0 var(--accent-pressed)}

/* T-P1-02 — Focus trigger is the primary CTA on the Today tab.
   Formalised §4A hero-button variant (previously undocumented drift).
   Reduced from 14/32 pad → 11/24, 15px → 14px so it reads as a strong
   primary but doesn't compete visually with the streak bar above it.
   Glow ring removed (was 4px; added thickness to the chrome stack).
   DESIGN-SYSTEM §4A hero-button: see .focus-trigger as canonical ref. */
.focus-trigger{
  display:flex;align-items:center;justify-content:center;gap:10px;
  /* v55-libfix — hero buttons (Today's Focus, library's Practise)
     are card-width on desktop, full-width on phone. 340px matches
     the .lib-list grid's card minmax so the hero visually anchors
     above the cards without overshooting. */
  width:100%;max-width:340px;
  margin:var(--section-gap,12px) auto;padding:11px 24px;
  background:var(--accent);color:var(--accent-on);border:none;border-radius:var(--radius);
  font-size:var(--font-size-lg);font-weight:700;font-family:inherit;cursor:pointer;
  box-shadow:0 3px 0 var(--accent-pressed);
  transition:background .1s,color .1s,border-color .1s,box-shadow .1s,transform .1s,opacity .1s;
}
@media(max-width:600px){.focus-trigger{max-width:none}}
.focus-trigger .icn{width:16px;height:16px}
.focus-trigger:hover{
  transform:translateY(-1px);
  box-shadow:var(--shadow-glow);
}
.focus-trigger:active{
  transform:translateY(1px);
  box-shadow:0 1px 0 var(--accent-pressed);
}
.focus-trigger:disabled{background:var(--surface-alt);color:var(--text-muted);box-shadow:none;cursor:not-allowed}

/* F8-A-06 — Shared start-action button base. All four tab-start CTAs use
   this class; palette tokens (--start-btn-bg / --start-btn-shadow) differ
   per tab via data-palette attribute. Default = sage (var(--accent)). */
.start-action-btn{
  display:flex;align-items:center;justify-content:center;gap:10px;
  width:100%;max-width:340px;
  margin:var(--section-gap,12px) auto;padding:12px 24px;
  border:none;border-radius:var(--radius);
  font-size:15px;font-weight:700;font-family:inherit;cursor:pointer;
  background:var(--start-btn-bg,var(--accent));
  color:white;
  box-shadow:0 3px 0 var(--start-btn-shadow,var(--accent-pressed));
  transition:background .1s,color .1s,box-shadow .1s,transform .1s,opacity .1s;
}
.start-action-btn svg{width:16px;height:16px;flex-shrink:0}
.start-action-btn:hover{transform:translateY(-1px);box-shadow:0 4px 0 var(--start-btn-shadow,var(--accent-pressed))}
/* .start-action-btn:active — REMOVED, consolidated into the hero press binding (motion/motion.css #8). */
.start-action-btn:disabled{opacity:.45;cursor:default;transform:none;box-shadow:none}
@media(max-width:600px){.start-action-btn{max-width:none}}
.start-action-btn[data-palette="honey"] {--start-btn-bg:var(--honey);  --start-btn-shadow:var(--honey-deep)}
.start-action-btn[data-palette="violet"]{--start-btn-bg:var(--violet); --start-btn-shadow:var(--violet-deep)}

/* --- Badge shelf --- */
.badge-shelf{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:11px;margin:13px 0}
.badge-card{
  background:var(--surface-alt2);border:1px solid var(--border);border-radius:var(--radius);
  padding:14px;text-align:center;cursor:default;transition:background .15s,color .15s,border-color .15s,box-shadow .15s,transform .15s,opacity .15s;
}
.badge-card.earned{border-color:var(--accent);background:var(--accent-soft);box-shadow:var(--shadow-glow)}
.badge-card.locked{filter:saturate(0.2);opacity:0.55}
.badge-icon{font-size:36px;margin-bottom:8px;display:block;line-height:1}
.badge-name{font-size:var(--font-size-md);font-weight:700;color:var(--text)}
.badge-desc{font-size:var(--font-size-xs);color:var(--text-muted);margin-top:4px;line-height:1.4}
.badge-tier{font-size:var(--font-size-2xs);font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:var(--gold);margin-top:4px}
.badge-card.earned .badge-tier{color:var(--accent)}

/* --- Loading --- */
.spinner{display:inline-block;width:16px;height:16px;border:2.5px solid var(--border);border-top-color:var(--accent);border-radius:50%;animation:spin .8s linear infinite;vertical-align:middle}
@keyframes spin{to{transform:rotate(360deg)}}
/* Monitor loading screen — full viewport, theme background.
   v172 — safe-area inset top/bottom so the alarm bar text + footer
   message don't collide with the iOS status bar / home indicator. */
.loading-screen{position:fixed;inset:0;display:flex;flex-direction:column;background:var(--bg);z-index:1000;contain:layout style paint;padding-top:env(safe-area-inset-top,0);padding-bottom:env(safe-area-inset-bottom,0)}
#loadingMsg{color:var(--text-muted);font-size:var(--font-size-xs);margin:0;text-align:center;padding:9px 24px;font-family:SF Mono,Courier New,monospace;letter-spacing:.04em;font-style:italic;flex-shrink:0;border-top:1px solid var(--border)}
/* ls- = monitor channel classes (loading screen + auth background) */
#ls-channels{flex:1;display:flex;flex-direction:column;width:100%;min-height:0}
.ls-ch{position:relative;flex:1;overflow:hidden;border-top:1px solid var(--border);min-height:0}
#ls-channels .ls-ch:first-child{border-top:none}
.ls-trk{display:flex;position:absolute;top:0;left:0;height:100%;will-change:transform}
/* v172 — Safe-area-inset on left/right so vital labels don't hug the
   viewport edge (Issue #18). Matters in iPhone landscape with notch. */
.ls-lbl{position:absolute;left:max(12px,env(safe-area-inset-left,0px));top:5px;font-size:9px;letter-spacing:.1em;z-index:2;font-weight:600;font-family:SF Mono,Courier New,monospace}
.ls-val{position:absolute;right:max(12px,env(safe-area-inset-right,0px));top:5px;font-size:9px;z-index:2;text-align:right;line-height:1.4;font-family:SF Mono,Courier New,monospace}
.ls-grd{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;opacity:.18;color:var(--border)}
.ls-abar{display:none;padding:5px 14px;justify-content:space-between;align-items:center;background:rgba(180,0,0,.25);flex-shrink:0;border-bottom:1px solid rgba(255,40,40,.3)}
.ls-sbar{display:none;padding:5px 14px;justify-content:space-between;align-items:center;background:rgba(0,140,0,.2);flex-shrink:0;border-bottom:1px solid rgba(40,200,80,.3)}
/* Spacer — exact invisible clone of ls-abar so it has identical height.
   Always display:flex (in-flow), visibility:hidden so text/bg are invisible.
   JS sets display:none only when a real bar is shown, preventing double-height. */
#ls-phase-spacer{display:flex;padding:5px 14px;justify-content:space-between;align-items:center;flex-shrink:0;border-bottom:1px solid transparent;visibility:hidden}
/* Auth page — monitor traces behind signin card */
#auth-mon-bg{position:absolute;inset:0;display:flex;flex-direction:column;overflow:hidden;pointer-events:none;z-index:0;opacity:.5}
#auth-mon-bg .ls-ch{flex:1;min-height:0;border-top:1px solid var(--border)}
#auth-mon-bg .ls-ch:first-child{border-top:none}
.signin-card{position:relative;z-index:1}

/* --- Progressive disclosure (show-advanced toggle) --- */
/* By default, calibration/predict UI and miss-tag/review buttons are visible.
   When body has NO 'show-advanced' class (i.e. default), hide power-user widgets
   so the surface looks calmer for new users. The 'Calibration prompts' and
   'Force miss-tagging' settings still gate functionality independently. */
body:not(.show-advanced) .recall-actions button.review{display:none}
body:not(.show-advanced) .saq .review-bar{opacity:0.6}
body:not(.show-advanced) .miss-tag-row{font-size:var(--font-size-xs)}
/* When show-advanced is on, give predict & miss-tag a subtle highlight */
body.show-advanced .predict-row{background:var(--surface);padding:8px 10px;border-radius:var(--radius-sm);border:1px dashed var(--border)}

/* --- Planner phase status badges --- */
.badge-current{background:var(--accent-soft);color:var(--accent-pressed)}
html.dark .badge-current{color:var(--accent)}
.badge-done{background:var(--green-bg);color:var(--green)}
.badge-upcoming{background:var(--surface-alt);color:var(--text-muted)}
/* v236 Fix 4 — studying badge: peri so it visually contrasts with the
   sage-toned date-current badge. Used in phaseRow + planner pinned rows. */
.badge-studying{background:color-mix(in srgb,var(--peri) 18%,var(--surface-alt2));color:var(--peri-deep,var(--peri));border:1px solid color-mix(in srgb,var(--peri) 35%,var(--border))}
html.dark .badge-studying{color:var(--peri)}

/* --- Focus Mode action buttons --- */
.focus-counter{font-size:var(--font-size-xs);color:var(--text-muted);text-transform:uppercase;letter-spacing:0.06em;font-weight:700;margin-bottom:11px}
.focus-saq-q{font-size:var(--font-size-2xl);line-height:1.4}
.focus-answer{padding:14px;background:var(--surface-alt2);border:1px dashed var(--border);border-radius:var(--radius-sm);margin:13px 0;line-height:1.55}
.focus-buttons{display:flex;gap:8px;flex-wrap:wrap;margin-top:15px}
.focus-action{
  flex:1;min-width:110px;padding:13px;
  border:1.5px solid var(--border);background:var(--surface);color:var(--text);
  border-radius:var(--radius-md);font-size:var(--font-size-lg);font-weight:700;cursor:pointer;font-family:inherit;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.focus-action:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.focus-action:active{transform:scale(0.97)}
.focus-show{background:var(--accent);color:white;border-color:var(--accent);box-shadow:0 2px 0 var(--accent-pressed)}
.focus-got{color:var(--green);border-color:var(--green)}
.focus-got:hover{background:var(--green-bg)}
.focus-miss{color:var(--red);border-color:var(--red)}
.focus-miss:hover{background:var(--red-bg)}
.focus-cf-Critical:hover    {background:var(--red-bg);    color:var(--red);    border-color:var(--red)}
.focus-cf-Low:hover         {background:var(--orange-bg); color:var(--orange); border-color:var(--orange)}
.focus-cf-Intermediate:hover{background:var(--amber-bg);  color:var(--honey-deep); border-color:var(--amber)}
html.dark .focus-cf-Intermediate:hover{color:var(--amber)}
.focus-cf-High:hover        {background:var(--green-bg);  color:var(--green);  border-color:var(--green)}

/* Compact mobile sheet behaviour */

/* ==========================================================
   v59 — iOS / mobile rebuild
   ==========================================================
   Goals:
   - Header simplified on phone: profile + brand + actions on
     one tidy row, meta drops to a second line.
   - Tab bar moves to BOTTOM on phone (iOS native pattern).
     Hidden in focus mode via the focus overlay's z-index.
   - Safe-area insets applied to top/bottom so the dynamic
     island and home indicator don't crash into UI.
   - Settings + search panels honour env(safe-area-inset-top)
     so the close button is reachable.
   - Card 'keyboard-focused' green outline subtler. */

@media(max-width:600px){
  body{
    /* iOS-render audit 2026-05-23 — left/right now fold in safe-area-inset so
       header corner buttons clear the notch/island in landscape. Portrait is
       unchanged (insets resolve to 0 → max(14px,0)=14px). */
    padding:max(env(safe-area-inset-top), 8px) max(14px, env(safe-area-inset-right, 0px)) max(env(safe-area-inset-bottom), 12px) max(14px, env(safe-area-inset-left, 0px));
  }
  h1{font-size:20px}
  h2{font-size:var(--font-size-xl)}
  .stats-grid{grid-template-columns:repeat(2,1fr)}
  .saq{padding:12px}

  .app-header-left{gap:6px}
  .account-btn{width:32px;height:32px;font-size:var(--font-size-sm)}
  .icon-btn{width:32px;height:32px}
  .app-title h1{font-size:18px}
  .app-title .subtitle{font-size:var(--font-size-2xs);opacity:0.7;line-height:1.2}

  /* Bottom tab bar — fixed to the bottom of the viewport. The
     5 main tabs are evenly distributed. Account button hides
     out of the bar (still reachable via header).
     v67 — explicit `top: auto` clears the desktop `top: 0`
     inherited from the position:sticky variant; otherwise both
     top and bottom are set on the fixed bar and it stretches
     full-viewport, hiding all content behind it on mobile. */
  .tabs{
    position:fixed;left:0;right:0;top:auto;bottom:0;z-index:200;
    /* iOS-render: trim the top padding so the icon row sits closer to
       the home indicator. Bottom uses safe-area-inset (home bar) + 4px
       breathing room — was 8px which combined with 6px top added ~14pt
       of dead chrome on the bar. New total: 0 + 44pt min-height + 34pt
       safe-area = 78pt (was 88pt). */
    margin:0;padding:0 0 max(env(safe-area-inset-bottom), 4px);
    border-top:1px solid var(--border);border-bottom:none;
    /* v177 N12 — z-index bumped 50→200 so nothing else accidentally
       overlays the tab bar on iOS. Was: pharma-bulk-bar (z-index 120)
       and other elements could draw a white box above the tab icons.
       Now the tabs win the stacking contest by a wide margin.
       Translucent chrome uses translucency + blur per Apple HIG.
       ── Z-INDEX SCALE (canonical — do not add values below 210 for modals) ──
         200  tab bar + focus overlay (both intentionally tied; focus overlay
              wins by DOM order when open)
         210  focus-overlay children (status pill, combo badge)
         240  drag ghost, floating bars that must sit above focus overlay
         250  bulk-bars + undo-veil (above tab bar, below sheet modals)
         280  onboarding wizard + new-session modal
         300  badge-sheet backdrop, planner sheets
         500  all JS-created bottom-sheets & modal overlays (gantt pickers,
              calendar diff, morning check-in, image composer, etc.)
         999  search-palette, sign-in overlay
        1000  loading screen, new-card wizard
        9000+ toasts, context menus, tooltips
       ── Never add a modal/sheet below 250 — it will render behind the tab bar */
    background:color-mix(in srgb, var(--bg) 78%, transparent);
    backdrop-filter:saturate(200%) blur(20px);
    -webkit-backdrop-filter:saturate(200%) blur(20px);
    display:flex;justify-content:space-around;
    overflow-x:visible;
  }
  /* v177 N12 — Solid-bg fallback when backdrop-filter unsupported (older
     iOS, some Android). Otherwise the partially-transparent bg sits over
     content with nothing behind it = ugly box. */
  @supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
    .tabs{background:var(--bg)}
  }
  .tabs .tab{
    flex:1 1 0;
    flex-direction:column;
    gap:2px;
    /* min-height:44 (HIG) is enforced by the base .tab rule — this padding
       only affects how the icon centers inside the 44pt tap target. */
    padding:4px 0 2px;
    font-size:var(--font-size-2xs);
    border-bottom:none;
  }
  .tabs .tab.active{border-bottom:none;color:var(--accent)}
  .tabs .tab .icn{width:20px;height:20px}
  /* Bundle C #8 — override the global .tab-text{display:none} at line 379 of
     app-shell-head-pre-planner.css so mobile users see icon + label, not
     icon-only. Round 1 P-14 + Round 2 C-01 reconfirmed P1 violation. */
  .tabs .tab-text{display:block;font-size:var(--font-size-2xs);letter-spacing:0.02em;line-height:1.1}
  /* Reserve space at the bottom of body so content doesn't
     scroll under the fixed tab bar.
     iOS-render: tabs trimmed to 44pt min-height + 1pt border = 45pt.
     Reserve 60pt to give the last item ~15pt clearance above the bar
     (was 76pt for the old 6+43 chrome). Combined with safe-area inset
     this matches the new bar geometry. */
  /* iOS-render audit 2026-05-23 — reserve trimmed 60→52px. Bar is 44pt + 1px
     border ≈ 45pt; 52px leaves ~7pt clearance for the last list item above the
     bar (was ~15pt of dead whitespace). Reclaims ~8px of page height. */
  body{padding-bottom:calc(52px + max(env(safe-area-inset-bottom), 8px))}

  /* Focus overlay sits above the tab bar (z-index:200) so the
     tabs are visually hidden in focus mode. */

  /* Settings + search panels — push the X close button below
     the safe-area-inset-top so the iPhone notch / dynamic
     island doesn't eat it. */
  .settings-panel,
  .search-palette{padding-top:max(env(safe-area-inset-top), 14px)}
  .settings-panel .panel-close,
  .settings-panel .close-btn,
  .search-palette .close-btn{margin-top:0}

  /* Recall library toolbar rows centred on phone for a tidy
     stacked layout (filters / sort / stats). */
  .lib-toolbar-row--filters{justify-content:center}
}

/* Card 'keyboard-focused' subtler — was a 2px accent outline.
   Now a soft 1px tint that doesn't dominate the surface. */
.recall-card.keyboard-focused,
.saq-card.keyboard-focused{
  outline:none;
  box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent);
}

/* v60 — iOS-native polish. Disable double-tap zoom on every
   interactive element so rapidly-tapping a grade button doesn't
   pinch-zoom into the surrounding text. touch-action: manipulation
   keeps regular scroll/pan but kills double-tap-to-zoom + delays
   click resolution by ~300ms. */
button, .icon-btn, [role="button"], .lib-chip, .recall-card,
.saq-card, .miss-tag-btn, .fc-card, .lib-stat-pill, .tab,
.fc-timer-pomodoro, .focus-trigger,
.fc-show-btn, .fc-grade-btn, .r-grade,
.saq-callout-btn, .fc-callout-btn,
input, select, textarea{
  touch-action:manipulation;
}

/* Bottom-tab-bar geometry — Apple-HIG native compact bar.
   min-height:44px is the *hit-area* floor (HIG/Material tap target);
   it is NOT a visual-height target. Inner padding is trimmed to
   4px/2px so the icon+label stack (24+2+10 ≈ 36px) sits inside the
   44pt target without inflating the bar — content < 44 means
   min-height governs, so the visible bar is 44 + 1px border = 45pt
   (was ~48pt from the old 8px/6px padding). Bottom uses safe-area
   (home bar) + 8px floor.  iOS-render audit 2026-05-23. */
@media(max-width:600px){
  .tabs .tab{
    min-height:44px;
    padding:4px 0 2px;
  }
  .tabs .tab .icn{width:22px;height:22px}
  /* iOS-render audit 2026-05-23 — top padding trimmed 4→2px; the bar's bottom
     gap is the home-indicator safe-area (immovable). min-height:44 keeps the
     hit target. Net visual chrome ~2px tighter. */
  .tabs{padding:2px 0 max(env(safe-area-inset-bottom, 0px), 8px)}
}

/* iOS install banner — slides up from the bottom on first visit
   when the app is NOT already installed (no display-mode:standalone).
   Sits ABOVE the bottom tab bar so it doesn't get clipped. */
.ios-install-banner{
  position:fixed;left:12px;right:12px;
  bottom:calc(72px + max(env(safe-area-inset-bottom), 8px));
  z-index:55;
  display:flex;align-items:center;gap:12px;
  padding:12px 14px;
  background:var(--surface-elevated);
  border:1px solid var(--accent);
  border-radius:var(--radius);
  box-shadow:0 6px 20px color-mix(in srgb, var(--accent) 12%, transparent);
  font-size:var(--font-size-md);
  animation:iibSlideUp .32s var(--ease-spring) both;
}
.ios-install-banner[hidden]{display:none}
@keyframes iibSlideUp{
  from{opacity:0;transform:translateY(20px)}
  to{opacity:1;transform:translateY(0)}
}
.iib-icon{
  flex-shrink:0;
  width:36px;height:36px;border-radius:var(--radius-sm);
  background:var(--accent-soft);color:var(--accent);
  display:inline-flex;align-items:center;justify-content:center;
}
.iib-icon svg{width:20px;height:20px}
.iib-msg{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}
.iib-msg strong{font-size:var(--font-size-md);font-weight:600;color:var(--text)}
.iib-msg span{font-size:var(--font-size-sm);color:var(--text-muted);line-height:1.35}
.iib-msg .iib-share{
  display:inline-block;padding:0 4px;border:1px solid var(--text-muted);
  border-radius:3px;font-family:var(--font-mono);font-size:var(--font-size-xs);
  vertical-align:1px;
}
.iib-dismiss{
  width:28px;height:28px;flex-shrink:0;
  border:none;background:transparent;color:var(--text-muted);
  cursor:pointer;font-size:20px;line-height:1;border-radius:var(--btn-radius);
}
.iib-dismiss:hover{background:var(--surface-alt);color:var(--text)}
@media(min-width:600px){
  .ios-install-banner{
    /* Desktop: pin bottom-right rather than full-width. */
    left:auto;right:24px;max-width:380px;
    bottom:calc(24px + max(env(safe-area-inset-bottom), 0px));
  }
}

/* v60 — search palette polish. Group results by section with a
   small uppercase header; matched substring highlighted via
   <mark>. Keyboard hint chips at the bottom of the panel. */
.search-results .search-section-header{
  font-size:var(--font-size-2xs);font-weight:600;color:var(--text-muted);
  text-transform:uppercase;letter-spacing:0.06em;
  padding:8px 14px 4px;
}
.search-results .search-result{
  padding:9px 14px;
}
.search-results .search-result mark{
  background:var(--accent-soft);color:var(--accent);
  padding:0 2px;border-radius:3px;font-weight:600;
}
/* K-P2-73: .search-hint-row + kbd rules removed — no JS creates this element. */

/* patch-032 — Search v2: snippets, operator chips, smart decks, empty state */
.search-results .sr-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.search-results .sr-title{font-size:var(--font-size-md);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.search-results .sr-snippet{font-size:var(--font-size-sm);color:var(--text-muted);line-height:1.4;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.search-results .sr-snippet mark{background:var(--accent-soft);color:var(--accent);padding:0 2px;border-radius:3px;font-weight:600}
.search-results .sr-meta{display:flex;gap:6px;margin-top:2px}
.search-results .sr-code{font-size:var(--font-size-xs);color:var(--text-muted);background:var(--surface);padding:1px 6px;border-radius:var(--radius-sm);font-family:ui-monospace,SFMono-Regular,monospace}
.search-results .sr-tier{font-size:var(--font-size-xs);line-height:1}
/* sr-pearl: pin to recall-pearl-badge--system tokens so search matches badge everywhere */
.search-results .sr-pearl{font-size:11px;line-height:1;color:color-mix(in srgb,#fff 40%,var(--sky-deep));filter:drop-shadow(0 0 2px color-mix(in srgb,#fff 60%,var(--sky)))}
html.dark .search-results .sr-pearl{color:color-mix(in srgb,#fff 50%,var(--sky));filter:drop-shadow(0 0 2px color-mix(in srgb,#fff 40%,var(--sky)))}
.search-results .sr-type--warn{color:var(--coral)}
.search-results .sr-del{margin-left:6px;background:none;border:none;color:var(--text-muted);cursor:pointer;padding:2px 4px;border-radius:var(--radius-tiny);display:inline-flex;align-items:center}
.search-results .sr-del:hover{background:var(--surface);color:var(--text)}
.search-results .sr-del svg{width:12px;height:12px}
.search-results .search-meta{padding:6px 14px;font-size:var(--font-size-xs);color:var(--text-muted);text-transform:uppercase;letter-spacing:0.06em;border-bottom:1px solid var(--border)}

.search-empty-wrap{padding:0}

/* Two-zone empty state (Option B) — Resume (warm) above, Explore (cool) below.
   Uses --honey / --sky token tints already in the cinema palette so the two
   intents read as physically separate without introducing new colour. */
.search-zone{padding:14px 16px;border-bottom:1px solid var(--border)}
.search-zone:last-child{border-bottom:none}
.search-zone--resume{background:color-mix(in srgb, var(--honey) 8%, transparent)}
.search-zone--explore{background:color-mix(in srgb, var(--sky) 7%, transparent)}
.search-zone-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:10px}
.search-zone-label{font-size:var(--font-size-xs);font-weight:700;letter-spacing:0.08em;text-transform:uppercase}
.search-zone--resume .search-zone-label{color:var(--honey-deep)}
.search-zone--explore .search-zone-label{color:var(--sky-deep)}
.search-zone-sub{font-size:var(--font-size-xs);color:var(--text-muted)}
.search-zone-sub-label{font-size:var(--font-size-xs);color:var(--text-muted);margin:8px 0 6px;letter-spacing:0.04em}

/* Resume — 3-up stat tiles */
.search-zone-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:4px}
.search-zone-tile{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-md);padding:10px 12px;cursor:pointer;text-align:left;font-family:inherit;color:inherit;transition:border-color var(--duration-sm),background .12s}
.search-zone-tile:hover{border-color:var(--honey);background:color-mix(in srgb, var(--honey) 6%, var(--bg))}
.search-zone-tile .szt-num{font-size:18px;font-weight:600;line-height:1;color:var(--honey-deep)}
.search-zone-tile .szt-num--small{font-size:var(--font-size-md);font-weight:600}
.search-zone-tile .szt-lbl{font-size:var(--font-size-xs);color:var(--text-muted);margin-top:4px}

/* Resume — overdue card list */
.search-zone-list{display:flex;flex-direction:column;gap:3px}
.search-zone-card{display:flex;justify-content:space-between;align-items:center;gap:8px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:7px 10px;cursor:pointer;font-family:inherit;font-size:var(--font-size-md);color:var(--text);text-align:left}
.search-zone-card:hover{border-color:var(--honey)}
.search-zone-card .szc-title{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}
.search-zone-card .szc-badge{font-size:var(--font-size-xs);color:var(--coral);background:color-mix(in srgb, var(--coral) 14%, transparent);padding:2px 7px;border-radius:var(--radius-md);flex-shrink:0;font-weight:600}
.search-zone-card .szc-badge--mute{color:var(--text-muted);background:var(--surface);font-weight:500;font-family:ui-monospace,SFMono-Regular,monospace}

/* Explore — quick-filter chip row + section pills + smart-deck tiles */
.search-empty-tip{display:flex;flex-wrap:wrap;gap:6px;margin:0}
.search-tip-chip{background:var(--bg);border:1px solid var(--border);color:var(--text);padding:4px 10px;border-radius:var(--radius-lg);font-size:var(--font-size-sm);font-weight:500;cursor:pointer;font-family:inherit;transition:border-color var(--duration-sm),background .12s}
.search-tip-chip:hover{background:color-mix(in srgb, var(--sky) 10%, var(--bg));border-color:var(--sky)}
.search-tip-chip--recent{font-family:ui-monospace,SFMono-Regular,monospace;font-size:var(--font-size-sm);font-weight:400;color:var(--text-muted)}

.search-browse-btn{background:var(--sky);color:#fff;border:none;border-radius:var(--radius-sm);padding:5px 12px;font-size:var(--font-size-sm);font-weight:600;cursor:pointer;font-family:inherit;transition:opacity var(--duration-sm);flex-shrink:0}
.search-browse-btn:hover{opacity:.85}
.search-section-pills{display:flex;flex-direction:column;gap:3px;margin:0 0 4px}
.search-section-pill{display:flex;align-items:center;gap:10px;background:var(--bg);border:1px solid var(--border);color:var(--text);padding:6px 10px;border-radius:var(--radius-sm);font-size:var(--font-size-md);font-weight:500;cursor:pointer;font-family:inherit;text-align:left;width:100%;transition:border-color var(--duration-sm),background .12s}
.search-section-pill:hover{background:color-mix(in srgb, var(--sky) 10%, var(--bg));border-color:var(--sky)}
.search-section-pill .ssp-code{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:var(--btn-radius);background:var(--surface);border:1px solid var(--border);font-family:ui-monospace,SFMono-Regular,monospace;font-size:var(--font-size-xs);font-weight:700;flex:0 0 auto;color:var(--sky-deep)}
.search-section-pill:hover .ssp-code{background:var(--sky);color:var(--bg);border-color:var(--sky)}
.search-section-pill .ssp-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.search-zone-decks{display:grid;grid-template-columns:repeat(2,1fr);gap:6px;margin:0 0 4px}
.search-zone-deck{position:relative;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 28px 8px 10px;cursor:pointer;font-family:inherit;color:inherit;text-align:left;transition:border-color var(--duration-sm),background .12s}
.search-zone-deck:hover{border-color:var(--sky);background:color-mix(in srgb, var(--sky) 6%, var(--bg))}
.search-zone-deck .szd-label{font-size:var(--font-size-md);font-weight:600;color:var(--text)}
.search-zone-deck .szd-query{font-size:var(--font-size-xs);color:var(--text-muted);font-family:ui-monospace,SFMono-Regular,monospace;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.search-zone-deck .szd-del{position:absolute;top:6px;right:6px;background:none;border:none;color:var(--text-muted);cursor:pointer;padding:2px;border-radius:var(--radius-tiny);display:inline-flex;align-items:center}
.search-zone-deck .szd-del:hover{background:var(--surface);color:var(--text)}
.search-zone-deck .szd-del svg{width:11px;height:11px}

.search-ops-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center;padding:8px 14px;border-bottom:1px solid var(--border);background:var(--surface)}
.search-op-chip{display:inline-flex;align-items:center;gap:4px;background:var(--accent-soft);color:var(--accent);font-size:var(--font-size-sm);font-weight:600;padding:3px 9px;border-radius:var(--radius)}
.search-op-x{background:none;border:none;color:inherit;cursor:pointer;padding:0;display:inline-flex;align-items:center;line-height:1}
.search-op-x svg{width:10px;height:10px;stroke-width:2.5}
.search-op-save{margin-left:auto;background:none;border:1px solid var(--border);color:var(--text-muted);font-size:var(--font-size-xs);font-weight:500;padding:3px 9px;border-radius:var(--radius-md);cursor:pointer;font-family:inherit}
.search-op-save:hover{color:var(--accent);border-color:var(--accent)}

/* Permanent quick-filter chip row — always visible below search input */
.search-qf-row{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:8px 14px;border-bottom:1px solid var(--border);background:var(--surface)}
.search-qf-grade-row{display:flex;flex-wrap:wrap;gap:5px;padding:4px 14px 8px;border-bottom:1px solid var(--border);background:var(--surface)}
.search-qf-grade-row[hidden]{display:none}
/* Base chip */
.qf-chip{border:none;border-radius:14px;padding:4px 11px;font-size:var(--font-size-sm);font-weight:600;cursor:pointer;font-family:inherit;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm);white-space:nowrap}
/* Selected (left side) — sky blue */
.qf-chip--on{background:color-mix(in srgb,var(--sky) 18%,var(--bg));color:var(--sky-deep);border:1.5px solid color-mix(in srgb,var(--sky) 50%,transparent)}
.qf-chip--on:hover{background:color-mix(in srgb,var(--sky) 26%,var(--bg))}
/* Deselected (right side) — muted */
.qf-chip--off{background:var(--bg);color:var(--text-muted);border:1.5px solid var(--border)}
.qf-chip--off:hover{background:color-mix(in srgb,var(--sky) 8%,var(--bg));border-color:color-mix(in srgb,var(--sky) 35%,transparent);color:var(--text)}
/* Grade parent chip — slightly different shape */
.qf-chip--grade{border-radius:14px}
/* Grade sub-chips */
.qf-chip--sub{padding:3px 9px;font-size:12px;border-radius:var(--radius-md)}
/* Divider between selected and deselected groups */
.qf-divider{display:inline-block;width:1px;height:18px;background:var(--border);margin:0 4px;align-self:center;flex-shrink:0}

/* Active filter chip row — sits between search input and results */
.search-filter-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center;padding:8px 14px;border-bottom:1px solid var(--border);background:var(--surface)}
.search-filter-row[hidden]{display:none}
.search-filter-chip{display:inline-flex;align-items:center;gap:5px;background:color-mix(in srgb, var(--sky) 15%, var(--bg));color:var(--sky-deep);border:1.5px solid color-mix(in srgb, var(--sky) 40%, transparent);font-size:var(--font-size-sm);font-weight:600;padding:3px 4px 3px 10px;border-radius:14px;line-height:1.2}
.search-filter-chip-x{background:none;border:none;color:var(--sky-deep);cursor:pointer;padding:0 3px;display:inline-flex;align-items:center;opacity:.7}
.search-filter-chip-x:hover{opacity:1}
.search-filter-chip-x svg{width:10px;height:10px;stroke-width:2.5}

/* Quick-filter chip active state */
.search-tip-chip.is-active{background:color-mix(in srgb, var(--sky) 15%, var(--bg));border-color:var(--sky);color:var(--sky-deep);font-weight:600}
.search-tip-chip.is-active:hover{background:color-mix(in srgb, var(--sky) 22%, var(--bg))}

/* Inline expandable curriculum tree */
.sst-tree{display:flex;flex-direction:column;gap:1px;margin:2px 0 4px}
.sst-section-wrap,.sst-chapter-wrap{display:contents}
.sst-row{display:flex;align-items:center;gap:7px;padding:5px 6px;border-radius:7px;cursor:pointer;transition:background .1s;user-select:none}
.sst-row:hover{background:color-mix(in srgb, var(--sky) 9%, var(--bg))}
.sst-row.is-selected{background:color-mix(in srgb, var(--sky) 14%, var(--bg));outline:1.5px solid color-mix(in srgb, var(--sky) 50%, transparent)}
.sst-row.is-selected .sst-code{background:var(--sky);color:#fff;border-color:var(--sky)}
.sst-section-row{padding-left:4px}
.sst-chapter-row{padding-left:22px}
.sst-topic-row{padding-left:40px}
.sst-expand-btn{background:none;border:none;cursor:pointer;color:var(--text-muted);font-size:9px;padding:0 3px;flex:0 0 auto;line-height:1;border-radius:3px;transition:color .1s}
.sst-expand-btn:hover{color:var(--text)}
.sst-expand-spacer{display:inline-block;width:18px;flex:0 0 auto}
.sst-code{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 3px;border-radius:var(--btn-radius);background:var(--surface);border:1px solid var(--border);font-family:ui-monospace,SFMono-Regular,monospace;font-size:var(--font-size-xs);font-weight:700;flex:0 0 auto;color:var(--sky-deep);transition:background .1s,color .1s,border-color .1s}
.sst-code--sm{font-size:10px;min-width:32px;height:19px}
.sst-code--topic{font-size:9px;min-width:38px;height:17px;opacity:.85}
.sst-name{flex:1;font-size:var(--font-size-sm);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}
.sst-topic-row .sst-name{font-size:var(--font-size-xs);color:var(--text-muted)}
.sst-count{font-size:var(--font-size-xs);color:var(--text-muted);font-variant-numeric:tabular-nums;flex-shrink:0;background:var(--surface);padding:1px 6px;border-radius:var(--radius-sm);border:1px solid var(--border)}
.sst-topic-dot{width:5px;height:5px;border-radius:50%;background:var(--border);flex:0 0 auto;margin:0 2px}
.sst-children{display:flex;flex-direction:column;gap:1px}
.sst-children--topics{}

/* Search-result preview modal — uses #modalOverlay (same as openTopic).
   Sections: meta-pill row, h3 dividers, prompt/answer prose, ref chips,
   footer action row. Reuses --surface / --text / --accent tokens. */
#modalBody .preview-meta{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 14px}
#modalBody .preview-meta-pill{font-size:var(--font-size-xs);padding:3px 9px;background:var(--surface);color:var(--text-muted);border-radius:var(--radius-md);font-weight:500}
#modalBody .preview-h3{font-size:var(--font-size-xs);font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:var(--text-muted);margin:18px 0 6px}
#modalBody .preview-prompt{font-size:14.5px;line-height:1.5;font-weight:500;margin:0 0 10px}
#modalBody .preview-answer{font-size:var(--font-size-lg);line-height:1.6;color:var(--text)}
#modalBody .preview-answer p{margin:0 0 8px}
#modalBody .preview-answer ul,#modalBody .preview-answer ol{margin:6px 0 8px;padding-left:22px}
#modalBody .preview-answer li{margin:2px 0}
#modalBody .preview-refs{display:flex;flex-wrap:wrap;gap:6px}
#modalBody .preview-ref{display:inline-flex;align-items:center;font-size:var(--font-size-sm);padding:3px 10px;background:var(--surface);color:var(--accent);border-radius:var(--radius-md);text-decoration:none;font-weight:500;cursor:pointer}
#modalBody .preview-ref:hover{background:var(--accent-soft)}
#modalBody .preview-actions{display:flex;flex-wrap:wrap;gap:8px;margin:18px 0 4px;padding-top:14px;border-top:1px solid var(--border)}
#modalBody .preview-action-btn{font-family:inherit;font-size:var(--font-size-md);font-weight:500;padding:7px 14px;background:var(--surface);border:1px solid var(--border);color:var(--text);border-radius:var(--radius-sm);cursor:pointer}
#modalBody .preview-action-btn:hover{border-color:var(--accent);color:var(--accent)}
#modalBody .preview-action-btn--primary{background:var(--accent);color:var(--accent-on);border-color:var(--accent)}
#modalBody .preview-action-btn--primary:hover{background:var(--accent);color:var(--accent-on);opacity:0.9}

/* SAQ tab toggles inside preview — CICM / Model / Notes */
#modalBody .preview-tab-row{display:flex;gap:4px;margin:14px 0 10px;border-bottom:1px solid var(--border)}
#modalBody .preview-tab-btn{font-family:inherit;font-size:var(--font-size-sm);font-weight:500;padding:6px 14px;background:none;border:none;color:var(--text-muted);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}
#modalBody .preview-tab-btn:hover{color:var(--text)}
#modalBody .preview-tab-btn--active{color:var(--accent);border-bottom-color:var(--accent)}
#modalBody .preview-tab-body{min-height:80px}

/* Add-to-queue affordance */
/* preview-queue-row / preview-queue-btn + all queue-picker-* CSS deleted 2026-05-09.
   _renderQueueButton() + _openQueuePicker() had zero call sites after
   _browseActions() was removed — entire card-context "Add to queue" chain deleted.
   Active queue-picker flow (stacks management) uses _buildQueuePickerRow() separately. */

/* Queue tile variant in search empty-state Explore zone */
.search-zone-deck--queue{border-color:var(--peri,var(--accent));background:color-mix(in srgb, var(--peri,var(--accent)) 8%, var(--bg))}
.search-zone-deck--queue:hover{border-color:var(--peri,var(--accent));background:color-mix(in srgb, var(--peri,var(--accent)) 14%, var(--bg))}

/* Queue detail modal (#modalBody when openQueue() runs) */
#modalBody .queue-empty{padding:32px 16px;text-align:center;color:var(--text-muted);font-size:var(--font-size-md)}
#modalBody .queue-item-list{display:flex;flex-direction:column;gap:6px;margin:14px 0}
#modalBody .queue-item{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:10px 12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md)}
#modalBody .queue-item-title{flex:1;min-width:0}
#modalBody .qit-prompt{font-size:var(--font-size-lg);font-weight:500;color:var(--text);cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#modalBody .qit-prompt:hover{color:var(--accent)}
#modalBody .qit-meta{display:flex;gap:6px;margin-top:4px}
#modalBody .qit-meta span{font-size:var(--font-size-xs);color:var(--text-muted)}
#modalBody .qit-code{font-family:ui-monospace,SFMono-Regular,monospace;background:var(--bg);padding:1px 6px;border-radius:var(--btn-radius)}
#modalBody .queue-item-controls{display:flex;gap:4px;flex-shrink:0}
#modalBody .qit-btn{font-family:inherit;font-size:var(--font-size-md);font-weight:500;width:28px;height:28px;background:none;border:1px solid var(--border);color:var(--text-muted);border-radius:var(--btn-radius);cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
#modalBody .qit-btn:hover{border-color:var(--accent);color:var(--accent)}
#modalBody .qit-btn:disabled{opacity:0.4;cursor:default}
#modalBody .qit-btn--danger:hover{border-color:var(--coral);color:var(--coral)}

/* Stacks polish #3 — drag handle + reorder placeholder. The handle has its
   own touch-action via JS so iOS doesn't scroll the page during drag. */
#modalBody .qit-drag-handle{
  flex-shrink:0;width:18px;height:32px;display:flex;align-items:center;
  justify-content:center;color:var(--text-faint);font-size:var(--font-size-md);
  letter-spacing:-2px;cursor:grab;user-select:none;
}
#modalBody .qit-drag-handle:hover{color:var(--text-muted)}
#modalBody .qit-drag-handle:active,
#modalBody .queue-item.dragging-reorder .qit-drag-handle{cursor:grabbing;color:var(--accent)}
#modalBody .queue-item.dragging-reorder{
  box-shadow:0 6px 18px color-mix(in srgb,var(--accent) 24%,transparent);
  border-color:var(--accent);
}

/* WS4 (2026-05-05): .recall-card--browse .recall-actions--browse,
   .recall-act-queue, .recall-act-drill — DEAD CODE DELETED.
   Browse-only action buttons were never emitted by JS (confirmed in audit).
   .recall-card--browse display gate rules retained above. */

/* Browse-mode answer is always visible; suppress focus-mode Show-btn space */
.recall-card--browse .show,.recall-card--browse .post-reveal,.recall-card--browse .miss-tag-overlay{display:none}

/* patch-032 round 5 — .recall-cols + .recall-col layout retired. Recall
   library now uses col-stack(3) like every other card-grid surface. */

/* Queue-detail header — synthesised; sits inside #previewBody (preview overlay) */
#previewBody .queue-detail-header{padding:18px 20px 8px;background:var(--surface);border-radius:var(--radius-lg) var(--radius-lg) 0 0;border:1px solid var(--border);border-bottom:none}
#previewBody .queue-detail-title{margin:0;font-size:18px;font-weight:600}
#previewBody .queue-detail-desc{margin-top:4px;font-size:var(--font-size-md);color:var(--text-muted)}

/* Preview-overlay action buttons — mirror #modalBody styles so #previewBody
   reuses the same button chrome (used by openQueue + new-stack form). */
#previewBody .preview-actions{display:flex;flex-wrap:wrap;gap:8px;margin:18px 20px 18px;padding-top:14px;border-top:1px solid var(--border)}
#previewBody .preview-action-btn{font-family:inherit;font-size:var(--font-size-md);font-weight:500;padding:7px 14px;background:var(--surface);border:1px solid var(--border);color:var(--text);border-radius:var(--radius-sm);cursor:pointer}
#previewBody .preview-action-btn:hover{border-color:var(--accent);color:var(--accent)}
#previewBody .preview-action-btn--primary{background:var(--accent);color:var(--accent-on);border-color:var(--accent)}
#previewBody .preview-action-btn--primary:hover{opacity:0.9}

/* New-stack form (patch-034 — Plan A: rule-first creation). Lives in
   #previewBody alongside the queue-detail header. Smart/Static segmented
   control + name + rule + auto-prune + 5-color picker. */
#previewBody .stack-form{padding:18px 20px 4px;background:var(--surface);border:1px solid var(--border);border-bottom:none;border-radius:var(--radius-lg) var(--radius-lg) 0 0}
#previewBody .stack-form-row{display:flex;flex-direction:column;gap:6px;margin:14px 0 0}
#previewBody .stack-form-label{font-size:var(--font-size-xs);font-weight:600;text-transform:uppercase;letter-spacing:0.06em;color:var(--text-muted)}
#previewBody .stack-form-input{font-family:inherit;font-size:var(--font-size-lg);padding:8px 12px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:var(--radius-sm);outline:none}
#previewBody .stack-form-input:focus{border-color:var(--accent)}
#previewBody .stack-form-hint{font-size:var(--font-size-xs);color:var(--text-muted);font-family:ui-monospace,SFMono-Regular,monospace}
#previewBody .stack-form-segmented{display:flex;gap:0;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:2px;width:fit-content}
#previewBody .stack-form-seg{font-family:inherit;font-size:var(--font-size-md);font-weight:600;padding:6px 16px;background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--btn-radius)}
#previewBody .stack-form-seg.is-active{background:var(--accent);color:var(--accent-on)}
#previewBody .stack-form-toggle{display:inline-flex;align-items:center;gap:8px;font-size:var(--font-size-md);color:var(--text);cursor:pointer}
#previewBody .stack-form-pruneRow{flex-direction:row;align-items:center}
#previewBody .stack-form-colorRow{}
#previewBody .stack-form-swatches{display:flex;gap:8px;flex-wrap:wrap}
#previewBody .stack-form-swatch{width:24px;height:24px;border-radius:50%;border:2px solid var(--border);cursor:pointer;padding:0;background:var(--surface);transition:transform var(--duration-sm),border-color .12s}
#previewBody .stack-form-swatch:hover{transform:scale(1.1)}
#previewBody .stack-form-swatch.is-active{border-color:var(--text);transform:scale(1.1)}
#previewBody .stack-form-swatch--none{background:repeating-linear-gradient(45deg,var(--surface),var(--surface) 3px,var(--border) 3px,var(--border) 5px)}
#previewBody .stack-form-swatch[data-color="peri"]{background:var(--peri)}
#previewBody .stack-form-swatch[data-color="sky"]{background:var(--sky)}
#previewBody .stack-form-swatch[data-color="sage"]{background:var(--sage,var(--sage-deep,#7ea878))}
#previewBody .stack-form-swatch[data-color="honey"]{background:var(--honey,#e0a85a)}
#previewBody .stack-form-swatch[data-color="coral"]{background:var(--coral)}

/* Stacks polish #2 — in-stack 📎 chip. Rendered by _renderStackChips(itemId)
   on browse-mode card listings + bulk-add affordances. Compact, single-line,
   ellipsises long stack names. Color modifier tints background to the stack's
   own --color-*; matches .stacks-tile-pill convention below. */
.stack-chip-row{display:inline-flex;flex-wrap:nowrap;gap:4px;align-items:center;max-width:100%;min-width:0}
.stack-chip{
  display:inline-flex;align-items:center;gap:3px;
  padding:1px 6px;border-radius:var(--btn-radius);font-size:var(--font-size-xs);font-weight:500;
  background:color-mix(in srgb, var(--text-muted) 8%, var(--bg));
  border:1px solid var(--border);color:var(--text-muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:160px;
}
.stack-chip--peri{border-color:color-mix(in srgb,var(--peri) 30%,var(--border));background:color-mix(in srgb,var(--peri) 10%,var(--bg));color:var(--peri-deep,var(--peri))}
.stack-chip--sky{border-color:color-mix(in srgb,var(--sky) 30%,var(--border));background:color-mix(in srgb,var(--sky) 10%,var(--bg));color:var(--sky-deep,var(--sky))}
.stack-chip--sage{border-color:color-mix(in srgb,var(--sage,#7ea878) 30%,var(--border));background:color-mix(in srgb,var(--sage,#7ea878) 10%,var(--bg));color:var(--sage-deep,#5f8e58)}
.stack-chip--honey{border-color:color-mix(in srgb,var(--honey,#e0a85a) 30%,var(--border));background:color-mix(in srgb,var(--honey,#e0a85a) 10%,var(--bg));color:var(--honey-deep,#a87e3a)}
.stack-chip--coral{border-color:color-mix(in srgb,var(--coral) 30%,var(--border));background:color-mix(in srgb,var(--coral) 10%,var(--bg));color:var(--coral)}
/* Library card chip-row container — sits below .recall-tag, separate row so
   it doesn't clip against .recall-tag's overflow:hidden. Wraps when the card
   is in many stacks. */
.recall-stack-chips{margin:4px 0 0;display:flex;flex-wrap:wrap;gap:4px}

/* Today tab — Stacks tile (patch-034 — Plan A). Inserted dynamically above
   .section-recall by renderStacksTile(). Compact pills row, max 3 visible. */
.stacks-tile{margin:6px 0 14px;padding:10px 12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg)}
.stacks-tile-h3{margin:0 0 8px;font-size:var(--font-size-xs);font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:var(--text-muted)}
.stacks-tile-row{display:flex;flex-wrap:wrap;gap:6px}
.stacks-tile-pill{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:var(--radius-sm);background:var(--bg);border:1px solid var(--border);color:var(--text);font-family:inherit;font-size:var(--font-size-md);font-weight:500;cursor:pointer;transition:border-color var(--duration-sm),background .12s}
.stacks-tile-pill:hover{border-color:var(--accent);background:color-mix(in srgb, var(--accent) 8%, var(--bg))}
.stacks-tile-pill--smart{border-color:var(--sky);background:color-mix(in srgb, var(--sky) 8%, var(--bg))}
.stacks-tile-pill--smart:hover{background:color-mix(in srgb, var(--sky) 14%, var(--bg))}
.stacks-tile-pill[data-color="peri"]{border-color:var(--peri);background:color-mix(in srgb, var(--peri) 8%, var(--bg))}
.stacks-tile-pill[data-color="sky"]{border-color:var(--sky);background:color-mix(in srgb, var(--sky) 8%, var(--bg))}
.stacks-tile-pill[data-color="sage"]{border-color:var(--sage-deep);background:color-mix(in srgb, var(--sage-deep) 8%, var(--bg))}
.stacks-tile-pill[data-color="honey"]{border-color:var(--honey,#e0a85a);background:color-mix(in srgb, var(--honey,#e0a85a) 8%, var(--bg))}
.stacks-tile-pill[data-color="coral"]{border-color:var(--coral);background:color-mix(in srgb, var(--coral) 8%, var(--bg))}
.stacks-tile-pill-name{max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.stacks-tile-pill-kind{font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:var(--sky-deep,var(--sky));background:color-mix(in srgb, var(--sky) 18%, transparent);padding:1px 6px;border-radius:var(--radius-sm)}
.stacks-tile-pill-count{font-size:var(--font-size-xs);color:var(--text-muted);font-family:ui-monospace,SFMono-Regular,monospace;background:var(--surface);padding:1px 6px;border-radius:var(--radius-sm)}

/* Search empty-state Stacks header — sub-label row with "+ New stack" button */
.search-zone-sub-label--row{display:flex;align-items:center;justify-content:space-between;gap:8px}
.search-stack-new{font-family:inherit;font-size:var(--font-size-xs);font-weight:600;color:var(--accent);background:none;border:none;cursor:pointer;padding:2px 6px;border-radius:var(--btn-radius);text-transform:none;letter-spacing:normal}
.search-stack-new:hover{background:var(--accent-soft)}
.search-stack-empty{padding:14px 12px;font-size:var(--font-size-sm);color:var(--text-muted);background:var(--surface);border:1px dashed var(--border);border-radius:var(--radius-sm);text-align:center;line-height:1.45}

/* Stack tile — smart variant + per-color tint + kind badge */
.search-zone-deck--smart{border-color:var(--sky);background:color-mix(in srgb, var(--sky) 8%, var(--bg))}
.search-zone-deck--smart:hover{border-color:var(--sky);background:color-mix(in srgb, var(--sky) 14%, var(--bg))}
.search-zone-deck[data-color="peri"]{border-color:var(--peri);background:color-mix(in srgb, var(--peri) 8%, var(--bg))}
.search-zone-deck[data-color="peri"]:hover{background:color-mix(in srgb, var(--peri) 14%, var(--bg))}
.search-zone-deck[data-color="sky"]{border-color:var(--sky);background:color-mix(in srgb, var(--sky) 8%, var(--bg))}
.search-zone-deck[data-color="sky"]:hover{background:color-mix(in srgb, var(--sky) 14%, var(--bg))}
.search-zone-deck[data-color="sage"]{border-color:var(--sage-deep);background:color-mix(in srgb, var(--sage-deep) 8%, var(--bg))}
.search-zone-deck[data-color="sage"]:hover{background:color-mix(in srgb, var(--sage-deep) 14%, var(--bg))}
.search-zone-deck[data-color="honey"]{border-color:var(--honey,#e0a85a);background:color-mix(in srgb, var(--honey,#e0a85a) 8%, var(--bg))}
.search-zone-deck[data-color="honey"]:hover{background:color-mix(in srgb, var(--honey,#e0a85a) 14%, var(--bg))}
.search-zone-deck[data-color="coral"]{border-color:var(--coral);background:color-mix(in srgb, var(--coral) 8%, var(--bg))}
.search-zone-deck[data-color="coral"]:hover{background:color-mix(in srgb, var(--coral) 14%, var(--bg))}
.search-zone-deck .szd-label-row{display:flex;align-items:center;gap:6px}
.search-zone-deck .szd-kind{font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:var(--sky-deep,var(--sky));background:color-mix(in srgb, var(--sky) 18%, transparent);padding:1px 6px;border-radius:var(--radius-sm)}

/* v60 — reduced-motion sweep. Animations that didn't have a
   prefers-reduced-motion fallback get one here as a catch-all.
   Falls back to fadeIn or no animation. */
@media(prefers-reduced-motion:reduce){
  .focus-trigger,
  .fc-card-inner,
  .ios-install-banner{animation:none;transition:none}
  .fc-card.swipe-out-left,
  .fc-card.swipe-out-right{animation:fadeIn .15s ease both}
  .lib-stats-strip,
  .recall-card,
  .saq-card{animation:none}
}

/* Pass pill contrast — ensure the text is legible on its band
   colour in BOTH light and dark mode. The mid (honey) variant
   was particularly weak; tighten the deep-token text against
   the fill so the pill always reads. */
.pill-low,.fc-saq-meta-pill.pill-low{background:var(--coral-fill);color:var(--coral-deep);font-weight:600}
.pill-mid,.fc-saq-meta-pill.pill-mid{background:var(--honey-fill);color:var(--honey-deep);font-weight:600}
.pill-high,.fc-saq-meta-pill.pill-high{background:var(--sage-fill);color:var(--sage-deep);font-weight:600}
html.dark .pill-low,html.dark .fc-saq-meta-pill.pill-low{background:color-mix(in srgb,var(--coral) 22%,transparent);color:var(--coral-lift)}
html.dark .pill-mid,html.dark .fc-saq-meta-pill.pill-mid{background:color-mix(in srgb,var(--honey) 22%,transparent);color:var(--honey)}
html.dark .pill-high,html.dark .fc-saq-meta-pill.pill-high{background:color-mix(in srgb,var(--mint) 22%,transparent);color:var(--mint)}


/* A4-fix: register --fc-glow so the browser can interpolate it.
   Without @property, `transition: --fc-glow .35s ease` is a no-op because
   custom properties default to <any> (no interpolation). initial-value must
   be a concrete color (not a var()) — use the literal hex of --mint. */
@property --fc-glow {
  syntax: '<color>';
  inherits: false;
  initial-value: #157570;
}

/* =====================================================
   FOCUS MODE — full-screen gamified card stack
   ===================================================== */
/* P1·5 — focus mode opens with a staggered sequence: takeover fades in
   over var(--duration-md), THEN the card flies in via fcCardIn at 280ms. Reads as
   discrete beats (room arrives → card arrives) instead of a single
   simultaneous event. The :not(.active) opacity:0 base lets the
   transition fire on .active.
   prefers-reduced-motion drops both transitions to instant flips. */
.focus-overlay{
  position:fixed;inset:0;z-index:200;
  /* Cinematic base: deep navy + type-colour radial halos via --fc-glow (set in JS). */
  background:
    radial-gradient(ellipse 80% 45% at 50% 0%,
      color-mix(in srgb, var(--fc-glow,var(--mint)) 18%, transparent) 0%,
      transparent 100%),
    radial-gradient(ellipse 60% 35% at 50% 100%,
      color-mix(in srgb, var(--fc-glow,var(--mint)) 8%, transparent) 0%,
      transparent 100%),
    var(--focus-overlay-bg);
  display:none;flex-direction:column;
  /* iOS-render: include left/right safe-area-inset so iPhone landscape
     (Dynamic Island shifted to the side) doesn't occlude card edges. */
  padding:env(safe-area-inset-top,0) env(safe-area-inset-right,0) env(safe-area-inset-bottom,16px) env(safe-area-inset-left,0);
  opacity:0;
  transition:opacity var(--duration-md) ease, --fc-glow .35s ease;
}
/* Per-type progress fill + header border colour */
.focus-overlay--type-recall     .fc-progress-fill{background:var(--sage,#79B9DD)}
.focus-overlay--type-saq        .fc-progress-fill{background:var(--rose,#E84870)}
.focus-overlay--type-pharmacopia .fc-progress-fill{background:var(--violet,#8B5CF6)}
.focus-overlay--type-axiom      .fc-progress-fill,.focus-overlay--type-fact .fc-progress-fill{background:var(--saltbush, #C4CAD0)}
.focus-overlay--type-recall     .fc-header{border-bottom-color:color-mix(in srgb,var(--sage) 30%,var(--border))}
.focus-overlay--type-saq        .fc-header{border-bottom-color:color-mix(in srgb,var(--rose) 30%,var(--border))}
.focus-overlay--type-pharmacopia .fc-header{border-bottom-color:color-mix(in srgb,var(--violet) 30%,var(--border))}
.focus-overlay--type-axiom      .fc-header{border-bottom-color:color-mix(in srgb,var(--saltbush) 30%,var(--border))}
/* Cinematic card lift — subtle type-colored shadow makes the card pop */
.focus-overlay .fc-card{
  box-shadow:
    0 12px 48px color-mix(in srgb, var(--fc-glow,var(--mint)) 22%, transparent),
    0 3px 10px rgba(0,0,0,.5);
}
.focus-overlay.active{display:flex;opacity:1}
.focus-overlay.active .fc-card--enter{animation-delay:.18s;animation-fill-mode:both}
/* iOS-render: status pill — fixed-positioned below the safe-area-inset-top
   so it hugs the bottom of the Dynamic Island on iPhone Pro. On non-island
   devices it reads as a thin status pill. Hidden by default; toggled via
   updateStatusPill() and gated on state.settings.statusPill !== false. */
.status-pill{
  position:absolute;top:calc(env(safe-area-inset-top, 0px) + 4px);
  left:50%;transform:translateX(-50%);
  z-index:210;
  display:inline-flex;align-items:center;gap:6px;
  padding:4px 12px;
  font-size:var(--font-size-xs);font-weight:500;line-height:1.2;
  color:var(--text);
  background:color-mix(in srgb, var(--surface-elevated) 92%, transparent);
  border:0.5px solid var(--border);
  border-radius:var(--radius-pill);
  backdrop-filter:saturate(180%) blur(12px);
  -webkit-backdrop-filter:saturate(180%) blur(12px);
  pointer-events:none;
  white-space:nowrap;
  max-width:min(200px, 60vw);
  overflow:hidden;text-overflow:ellipsis;
  animation:statusPillIn .25s ease-out;
}
.status-pill[hidden]{display:none}
.status-pill .sp-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0;background:var(--sage)}
.status-pill .sp-dot--saq      {background:var(--honey)}
.status-pill .sp-dot--nemesis  {background:var(--coral)}
.status-pill .sp-dot--axiom,
.status-pill .sp-dot--fact     {background:var(--sky)}
.status-pill .sp-dot--pharma   {background:var(--violet)}
@keyframes statusPillIn{from{opacity:0;transform:translateX(-50%) translateY(-4px)}to{opacity:1;transform:translateX(-50%) translateY(0)}}
@media(prefers-reduced-motion:reduce){.status-pill{animation:none}}
@media(prefers-reduced-motion:reduce){
  .focus-overlay{transition:none}
  .focus-overlay.active .fc-card{animation-delay:0s}
}

/* ── Loading state: overlay shown immediately on click while API is in-flight ─ */
@keyframes fcLoadingSpin{to{transform:rotate(360deg)}}
.focus-overlay--loading::before{
  content:'';
  position:absolute;top:50%;left:50%;
  width:36px;height:36px;margin:-18px 0 0 -18px;
  border:2.5px solid color-mix(in srgb,var(--text) 15%,transparent);
  border-top-color:var(--mint,#5ACBAD);
  border-radius:50%;
  animation:fcLoadingSpin .7s linear infinite;
}
@media(prefers-reduced-motion:reduce){.focus-overlay--loading::before{animation:none;opacity:.35}}

/* Nemesis session: coral override — the cinematic gradient already picks
   up --fc-glow:coral from _applyFcTypeTheme; this just amplifies it.     */
.focus-overlay--nemesis .fc-progress-fill{background:var(--coral)}
.focus-overlay--nemesis .fc-header{border-bottom-color:color-mix(in srgb,var(--coral) 30%,var(--border))}
.focus-overlay--nemesis .fc-close:hover{background:var(--coral-fill);color:var(--coral-deep)}
/* W5.1 — Recovery session chrome (softer coral than nemesis). */
.focus-overlay--recovery .fc-progress-fill{background:var(--coral)}
.focus-overlay--recovery .fc-header{border-bottom-color:color-mix(in srgb,var(--coral) 25%,var(--border))}
/* Recovery tag: "↺ Recovery · 2018.1 Paper 1" — set text via JS in bootFocusSession. */
.fc-recovery-tag{
  display:none;align-items:center;gap:5px;
  font-size:var(--font-size-xs);font-weight:700;letter-spacing:0.4px;text-transform:uppercase;
  color:var(--coral-deep);background:var(--coral-fill);
  padding:3px 8px;border-radius:var(--radius-pill);flex-shrink:0;max-width:180px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.focus-overlay--recovery .fc-recovery-tag{display:inline-flex}
/* Header gets a small "🔥 Nemesis run" tag in front of the progress bar. */
.fc-nemesis-tag{
  display:none;align-items:center;gap:5px;
  font-size:var(--font-size-xs);font-weight:700;letter-spacing:0.5px;text-transform:uppercase;
  color:var(--coral-deep);background:var(--coral-fill);
  padding:3px 8px;border-radius:var(--radius-pill);flex-shrink:0;
}
.focus-overlay--nemesis .fc-nemesis-tag{display:inline-flex}

/* Tamed celebration — fired when the user grades every nemesis card
   "Got it" in a single session. Full-screen veil with a glow-up icon
   + the line "Tamed". 'Tamed' here is intentionally restrained — no
   confetti, no loop. One fade-in, one held beat, one gentle pulse. */
.fc-tamed-veil{
  position:absolute;inset:0;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;
  background:radial-gradient(ellipse at center,
    color-mix(in srgb,var(--coral) 28%,var(--bg)) 0%,
    color-mix(in srgb,var(--coral) 6%,var(--bg)) 60%);
  z-index:10;
  animation:fcTamedVeilIn .42s var(--ease-spring) both;
}
.fc-tamed-icon{
  font-size:64px;line-height:1;
  animation:fcTamedIconPulse 1.6s ease-in-out infinite;
}
.fc-tamed-title{
  font-family:var(--font-display);
  font-size:32px;font-weight:400;
  color:var(--coral-deep);
  letter-spacing:1px;
  margin:0;
}
.fc-tamed-sub{
  font-size:var(--font-size-md);color:var(--text-muted);text-align:center;
  max-width:280px;line-height:1.5;
}
@keyframes fcTamedVeilIn{
  from{opacity:0;backdrop-filter:blur(0)}
  to  {opacity:1;backdrop-filter:blur(2px)}
}
@keyframes fcTamedIconPulse{
  0%,100%{transform:scale(1);filter:none}
  50%    {transform:scale(1.06);filter:drop-shadow(0 0 14px color-mix(in srgb,var(--coral) 50%,transparent))}
}
@media(prefers-reduced-motion:reduce){
  .fc-tamed-veil{animation:fadeIn var(--duration-md) ease both}
  .fc-tamed-icon{animation:none}
}
/* §5 FM3 — single-row header. align-items:center keeps everything on one
   vertical line so close, progress, counter, XP, and undo all share a
   baseline. */
/* v102 — header is now column flex: row-1 (chrome) + row-2 (queue strip) */
.fc-header{display:flex;flex-direction:column;align-items:stretch;gap:0;padding:0;border-bottom:1px solid var(--border);flex-shrink:0}
.fc-header-row{display:flex;align-items:center;gap:10px;padding:10px 16px 8px}
/* v170/172 — queue-strip: Apple Music queue style. Visible by default on
   tablet/desktop (≥600px); collapsed by default on phones (<600px), tap
   the counter to reveal. New visual design persists across both states.
   --queue-collapsed pref hides at any width. --queue-open opens on phone
   (auto-close 4s, set by toggleFcQueuePeek). */
.fc-queue-strip{
  display:flex;align-items:center;gap:6px;
  padding:6px 50% 10px;          /* 50% padding lets first/last tile snap to centre */
  overflow-x:auto;overflow-y:visible;scrollbar-width:none;
  overscroll-behavior-x:contain; /* iOS-render: contain horizontal rubber-band to the
                                    strip; stops the flick from bleeding into page scroll
                                    or reading as a swipe-to-grade. snap-x still works. */
  scroll-snap-type:x mandatory;
  scroll-behavior:smooth;
  position:relative;/* tooltip anchor */
  -webkit-mask-image:linear-gradient(to right, transparent 0, black 64px, black calc(100% - 64px), transparent 100%);
          mask-image:linear-gradient(to right, transparent 0, black 64px, black calc(100% - 64px), transparent 100%);
}
.fc-queue-strip::-webkit-scrollbar{display:none}
/* Phone (<600px): collapsed by default; counter-tap toggles --queue-open. */
@media(max-width:599px){
  .fc-queue-strip{display:none}
  .fc-header--queue-open .fc-queue-strip{display:flex}
}
/* Desktop (≥600px): visible by default; --queue-collapsed pref hides. */
.fc-header--queue-collapsed .fc-queue-strip{display:none}
/* Mobile: counter becomes tap target — subtle violet ring.
   F-P1-04: rgba literals promoted to --fc-counter-* cinema tokens. */
@media(max-width:599px){
  .focus-overlay .fc-card-counter{
    cursor:pointer;padding:3px 7px;border-radius:var(--radius-sm);
    border:1px solid var(--fc-counter-border);background:var(--fc-counter-bg);
    color:var(--fc-counter-fg);
    transition:background .15s,color .15s;
  }
  .focus-overlay .fc-card-counter:active,
  .focus-overlay .fc-header--queue-open .fc-card-counter{
    background:var(--fc-counter-bg-open);color:var(--fc-counter-fg-open);
  }
}
/* Queue strip chips — 3-state carousel (phase 7 + nav-return patch).
   Visual state is driven entirely by data-state="upcoming|active|graded"
   and data-type/data-grade attributes; see CAROUSEL V2 block below.
   The old v170 class-based rules (.fc-type-chip--past/--current using
   --chip-fill/--chip-fill-light) are retired — they had higher specificity
   (0,3,0) than the data-state rules (0,2,0) and applied wrong token colours
   to upcoming chips. Classes --past/--current are still emitted by JS for
   the animation-exclusion and pip-sizing rules that follow. */
.fc-type-chip{
  position:relative;flex-shrink:0;
  width:30px;height:30px;border-radius:var(--radius-sm);
  display:flex;align-items:center;justify-content:center;
  border:0;padding:0;background:transparent;color:inherit;
  cursor:pointer;font:inherit;
  scroll-snap-align:center;
  transition:transform .18s ease,box-shadow var(--duration-md) ease;
  -webkit-tap-highlight-color:transparent;
}
.fc-type-chip::before{
  /* invisible 44 × 44 hit region (HIG touch target) */
  content:'';position:absolute;inset:-7px;border-radius:var(--radius);
}
.fc-type-chip:hover{transform:translateY(-1px)} /* WS11: separated hover transform from focus-visible; universal :focus-visible ring now applies */
.fc-type-chip svg{width:13px;height:13px;flex-shrink:0;display:block;color:inherit}
/* Grade pip — bottom-right corner (legacy; not emitted by current renderQueuePreview). */
.fc-chip-pip{
  position:absolute;bottom:-3px;right:-3px;
  width:10px;height:10px;border-radius:50%;
  border:2px solid var(--focus-overlay-bg);box-sizing:border-box;
  pointer-events:none;
}
.fc-type-chip--current .fc-chip-pip{
  width:13px;height:13px;border-width:2.5px;bottom:-4px;right:-4px;
}
.fc-chip-pip[data-grade="1"]{background:var(--fc-badge-missed,#DC2626)}
.fc-chip-pip[data-grade="2"]{background:var(--fc-badge-hazy,#f59e0b)}
.fc-chip-pip[data-grade="3"]{background:var(--fc-badge-honed,#15803D)}
.fc-chip-pip[data-grade="4"]{background:var(--fc-badge-mastered)}

/* =====================================================
   CAROUSEL V2 — phase 7 (2026-05-05)
   3 states: upcoming / active / graded.
   Type and grade colour never co-occur — graded chips replace type
   colour with grade colour entirely (filled + inverted glyph).
   Spec: docs/CARD-REDESIGN-SPEC.md §10.
   ===================================================== */
.fc-type-chip[data-type="recall"]      {--type-colour:var(--sky-deep)}
.fc-type-chip[data-type="saq"]         {--type-colour:var(--rose-deep)}
.fc-type-chip[data-type="pharmacopia"] {--type-colour:var(--violet-deep)}
.fc-type-chip[data-type="axiom"]       {--type-colour:var(--saltbush-deep)}
.fc-type-chip[data-type="fact"]        {--type-colour:var(--saltbush-deep)}
.fc-type-chip[data-type="nemesis"]     {--type-colour:var(--coral-deep)}

/* Upcoming — transparent + type outline + glyph in type colour. */
.fc-type-chip[data-state="upcoming"]{
  background:transparent;
  border:1.5px solid var(--type-colour);
  color:var(--type-colour);
  font-weight:500;font-size:16px;
}
/* Active — 1.22× scale, solid type-colour fill + white glyph. */
.fc-type-chip[data-state="active"]{
  width:44px;height:44px;
  background:var(--type-colour);
  border:2px solid var(--type-colour);
  color:#fff;
  font-weight:500;font-size:20px;
  transform:translateY(-1px);
  box-shadow:none;
}
html.dark .fc-type-chip[data-state="active"]{color:#0b0b10}
/* Graded — filled with grade colour, inverted glyph. No outline. */
.fc-type-chip[data-state="graded"][data-grade="missed"]   {--grade-colour:var(--grade-missed)}
.fc-type-chip[data-state="graded"][data-grade="honed"]    {--grade-colour:var(--grade-honed)}
.fc-type-chip[data-state="graded"][data-grade="mastered"] {--grade-colour:var(--grade-mastered)}
.fc-type-chip[data-state="graded"]{
  background:var(--grade-colour,var(--grade-honed));
  border:0;
  color:#F4ECDA; /* warm cream ink — high contrast on coral / green / amethyst */
  font-weight:500;font-size:16px;
}
html.dark .fc-type-chip[data-state="graded"]{color:#0b0b10}

@keyframes fcChipSlideRight{from{transform:translateX(10px);opacity:0}to{transform:translateX(0);opacity:1}}
@keyframes fcChipSlideLeft {from{transform:translateX(-10px);opacity:0}to{transform:translateX(0);opacity:1}}
.fc-queue-strip--forward .fc-type-chip{animation:fcChipSlideRight .24s var(--ease-out) both}
.fc-queue-strip--back    .fc-type-chip{animation:fcChipSlideLeft  .24s var(--ease-out) both}
.fc-queue-strip--forward .fc-type-chip--current,
.fc-queue-strip--back    .fc-type-chip--current{animation:none}
@media(prefers-reduced-motion:reduce){
  .fc-queue-strip--forward .fc-type-chip,
  .fc-queue-strip--back    .fc-type-chip{animation:none}
}
.fc-close{width:36px;height:36px;border-radius:50%;border:none;background:var(--surface-alt);color:var(--text-muted);font-size:20px;cursor:pointer;line-height:1;flex-shrink:0;display:flex;align-items:center;justify-content:center;transition:background .12s}
.fc-close:hover{background:var(--border);color:var(--text)}
/* Progress wrap holds the bar + inline counter on one row. flex:1 means it
   eats the remaining space between the close button and the XP/undo cluster. */
.fc-progress-wrap{flex:1;display:flex;align-items:center;gap:8px;min-width:0}
.fc-progress-bar{flex:1;height:4px;background:var(--border);border-radius:var(--radius-2xs);overflow:hidden}
.fc-progress-fill{height:100%;background:var(--accent);border-radius:var(--radius-2xs);transition:width .3s ease}
.fc-card-counter{font-size:var(--font-size-xs);color:var(--text-muted);font-variant-numeric:tabular-nums;white-space:nowrap}
/* §5 FM5 — XP pill: hidden by default via [hidden]; first rateFocusCard
   removes the attribute, after which the pill stays visible. honey-tinted
   so it reads as a reward without competing with the brand sage/mint. */
.fc-xp-pill{display:inline-flex;align-items:center;gap:4px;font-size:var(--font-size-xs);font-weight:600;color:var(--honey-deep);background:var(--honey-fill);padding:3px 8px;border-radius:var(--radius-pill);flex-shrink:0;font-variant-numeric:tabular-nums}
html.dark .fc-xp-pill{color:var(--honey);background:var(--honey-soft)}
.fc-xp-pill[hidden]{display:none}
.fc-xp-val{font-weight:700}
.fc-undo-btn{padding:4px 10px;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--surface);color:var(--text-muted);font-size:var(--font-size-xs);cursor:pointer;display:flex;align-items:center;gap:4px;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);flex-shrink:0;font-family:inherit}
.fc-undo-btn:hover{border-color:var(--accent);color:var(--accent)}
.fc-undo-btn:disabled{opacity:0.3;cursor:not-allowed}
.fc-undo-count{background:var(--accent);color:var(--accent-on);border-radius:var(--radius-sm);font-size:var(--font-size-2xs);font-weight:700;padding:1px 5px;min-width:16px;text-align:center}
#fcVoiceToggle{transition:color var(--duration-md);color:var(--text-disabled)} /* WS11 v9.7-foundation: dropped opacity:0.4 + undefined --text-secondary; --text-disabled is a real ≥3:1 UI token for inactive state */
#fcVoiceToggle .icn{width:15px;height:15px}
#fcVoiceToggle.is-active{color:var(--sage)}
#fcVoiceToggle.fc-voice-toggle--heard{color:var(--mint)}
@keyframes fc-voice-heard{0%{transform:scale(1.35)}100%{transform:scale(1)}}
#fcVoiceToggle.fc-voice-toggle--heard .icn{animation:fc-voice-heard 0.5s ease-out}
@media(prefers-reduced-motion:reduce){#fcVoiceToggle.fc-voice-toggle--heard .icn{animation:none}}
/* §5 FM7 — week pips + exam countdown sit tight together. No
   margin-left:auto void on .fc-exam-countdown — the band stays
   compact, anchored left. */
.fc-week-band{display:flex;align-items:center;gap:8px;padding:6px 16px 0;flex-shrink:0;flex-wrap:wrap}
.fc-pip{width:8px;height:8px;border-radius:50%;background:var(--surface-alt);border:1px solid var(--border);transition:background var(--duration-md);flex-shrink:0}
.fc-pip.done{background:var(--amber);border-color:var(--amber)}
.fc-pip.today{background:var(--accent);border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-soft)}
.fc-pip.freeze{background:var(--text-faint);border-color:var(--text-faint)}
.fc-pip-label{font-size:9px;color:var(--text-faint);margin-right:2px}
.fc-exam-countdown{font-size:var(--font-size-xs);color:var(--text-muted);display:flex;align-items:center;gap:4px}
.fc-exam-countdown strong{color:var(--text);font-variant-numeric:tabular-nums}
/* Post-v9.1 audit — tighter stage padding so the card claims more of the
   available vertical and the queue preview sits closer to the action. */
/* v58 — added padding-bottom so cards aren't crashing into the
   viewport edge / focus-overlay safe-area inset. Gives the cards
   the 'central focus' feel the user asked for. overflow-y allows
   the done screen to scroll if its content (with a long badge
   haul) outgrows the stage. */
/* Top padding reduced 24→16px — the fc-week-band already adds visual separation.
   Bottom padding raised to 48px base so the action bar never jams the viewport edge. */
.fc-stage{flex:1;overflow-y:auto;overflow-x:hidden;position:relative;display:flex;align-items:stretch;justify-content:center;padding:16px 16px 48px;overscroll-behavior:contain}
@media(min-width:600px){.fc-stage{padding:24px 24px 64px}}
/* Cinema overscroll guard: the fixed overlay must never let the Today tab behind
   it scroll into view. overscroll-behavior:none on the overlay + locking the page
   behind it (page can't scroll/rubber-band while a session is active). */
.focus-overlay{overscroll-behavior:none}
html:has(.focus-overlay.active),
body:has(.focus-overlay.active){overflow:hidden;overscroll-behavior:none}
/* patch-007 — Depth-stack ghost cards (.fc-behind1, .fc-behind2) fully
   removed: DOM nodes deleted, JS toggles deleted, CSS deleted. */
/* §5 FM2 — card max-width 640, width calc(100% - 48px) per spec. The
   bg switches to --surface-elevated so the card reads as elevated above
   the page (warm cream → lighter cream in light, deep forest → mint-tinted
   surface in dark). Border-radius uses the token. */
/* Card-redesign IMPROVE: soften box-shadow from --shadow-md to --shadow-1.
   The medium shadow created a "ghost outline" silhouette below the card
   that read as a second card behind it. */
.fc-card{z-index:2;width:calc(100% - 48px);max-width:640px;max-height:100%;background:var(--surface-elevated);border:1px solid var(--border);border-radius:var(--radius-lg);display:flex;flex-direction:column;gap:0;overflow-y:auto;box-shadow:var(--shadow-1);position:relative;min-width:380px;min-height:280px;touch-action:none;will-change:transform;contain:layout style}
/* SMOOTHNESS PASS — while a card is in motion (dragged / exiting / promoting),
   make it a flat composited texture so ONLY transform/opacity animate and the
   browser never repaints mid-frame. Flatten the 48px coloured glow shadow to a
   cheap flat one, and freeze every infinite/decorative animation on the card
   (Pearl hue-rotate + sheen are the worst offenders). Everything restores the
   instant the card settles (class removed). This is what closes the gap to the
   lightweight mockup. The functional promotion (CSS transition) + WAAPI exit are
   unaffected (animation-play-state only touches @keyframes animations). */
.focus-overlay .fc-card.fc-card--motion{box-shadow:var(--shadow-1)!important}
.fc-card.fc-card--motion,
.fc-card.fc-card--motion *,
.fc-card.fc-card--motion::before,
.fc-card.fc-card--motion::after{animation-play-state:paused!important}
/* Tier D — ghost cards sit occluded behind the active card; their infinite
   decorative animations (pearl stripe-sheen, holo-rotate, logo breath) keep
   painting uselessly. Pause the same selector set as --motion above, scoped
   to ghost classes. Ghost classes are removed by _finalizePromotedCard() when
   the card is promoted to active, so animations resume automatically — no JS
   needed. Does NOT pause the transform/opacity promotion glide (that is a CSS
   transition, not a @keyframes animation). */
.fc-card.fc-ghost-1,
.fc-card.fc-ghost-1 *,
.fc-card.fc-ghost-1::before,
.fc-card.fc-ghost-1::after,
.fc-card.fc-ghost-2,
.fc-card.fc-ghost-2 *,
.fc-card.fc-ghost-2::before,
.fc-card.fc-ghost-2::after{animation-play-state:paused!important}
/* Entry animation is OPT-IN via .fc-card--enter (added by renderFocusCard for a
   freshly-built active card: boot / undo / done / PRM rebuilds). Pre-rendered
   ghost cards and promoted cards must NOT replay fcCardIn — the promotion is a
   transform glide, not an entry. (Was on base .fc-card → double up-animation.) */
.fc-card.fc-card--enter{animation:fcCardIn var(--duration-lg) var(--ease-spring)}
/* `to` intentionally omits transform: with animation-fill-mode:both (set on
   .focus-overlay.active .fc-card), a `transform:none` here would persist after
   the entry ends and override the inline drag transform (animations beat inline
   styles), killing the swipe pickup/lift. Omitting it frees transform post-entry. */
@keyframes fcCardIn{from{opacity:0;transform:translateY(18px) scale(0.97)}to{opacity:1}}
/* B10: @keyframes fcCardOut + .fc-card.exit removed — 'exit' class is never added
   in JS (confirmed by grep of app.js + swipe-engine.js); dead code removed. */
@media(min-width:600px){.fc-card{min-width:420px;min-height:320px}}
/* Short viewports (iOS landscape, on-screen keyboard) — drop min-height so
   the card never extends past the visible stage and clips the grade bar. */
@media(max-height:600px){.fc-card{min-height:auto}}

/* Today-fix v2 #5 — directional swipe-out animations on grade. Missed
   triggers swipe-left (translateX -120% + slight tilt); Got it triggers
   swipe-right. Reads as 'this card flew off in the direction I sent it'
   reinforcing the swipe metaphor + arrow-key shortcuts.
   Flip animation on Show Answer / Space toggles a 3D rotate via
   .fc-card.flipping: 180deg Y-axis rotate so the back of the card
   appears for a moment, then snap to revealed. For the recall + nemesis
   cards (which use class-driven .revealed reveal, not actual face
   flipping), the animation is a brief scale pulse to register the tap. */
@keyframes fcSwipeOutLeft{
  from{opacity:1;transform:none}
  to{opacity:0;transform:translateX(-120%) rotate(-12deg)}
}
@keyframes fcSwipeOutRight{
  from{opacity:1;transform:none}
  to{opacity:0;transform:translateX(120%) rotate(12deg)}
}
.fc-card.swipe-out-left {animation:fcSwipeOutLeft  .32s var(--ease-out) forwards}
.fc-card.swipe-out-right{animation:fcSwipeOutRight .32s var(--ease-out) forwards}

/* patch-007 — Reveal animation refactored. The previous fcRevealPulse
   (scale 0.97 → 1) combined with a hard cut on .fc-action-bar created a
   "flash in / flash out" sensation when cards flipped front → back. Now:
     · the show-button fades + slides up out of place
     · the answer slides in + fades from below the prompt
     · the action bar fades + slides up into the bottom border
   Single coordinated var(--duration-lg) cubic-bezier across all card types so recall,
   pharmacopia, nemesis and SAQ-fact reveal the same way. */
@keyframes fcRevealAnswerIn{
  0%  {opacity:0;transform:translateY(8px)}
  100%{opacity:1;transform:translateY(0)}
}
@keyframes fcRevealActionBarIn{
  0%  {opacity:0;transform:translateY(6px)}
  100%{opacity:1;transform:translateY(0)}
}
@keyframes fcRevealShowBtnOut{
  0%  {opacity:1;transform:translateY(0)}
  100%{opacity:0;transform:translateY(-4px)}
}
.fc-card.revealing .fc-show-btn{animation:fcRevealShowBtnOut .18s ease both}
@media(prefers-reduced-motion:reduce){
  /* F-P1-01: 5 focus keyframes now guarded. Bounce/spring → instant fade. */
  /* B10: .fc-card.exit{animation:none} removed — exit class is dead code. */
  .fc-card.fc-card--enter{animation:fadeIn var(--duration-sm) ease both}
  .fc-card.swipe-out-left,
  .fc-card.swipe-out-right{animation:fadeIn var(--duration-sm) ease both}
  .fc-card.revealed .fc-answer{animation:fadeIn var(--duration-sm) ease both}
  .fc-card.revealed .fc-action-bar{animation:fadeIn var(--duration-sm) ease both}
  .fc-card.revealing .fc-show-btn{animation:none}
}

/* ── C6–C8: Nemesis boss-battle cinematics ──────────────────────────────
   C6  boss-battle entry: charcoal+ember backdrop + weighted slide-in
   C7  taunt hold: 2s answer-hold on low grade for nemesis card
   C8  tumble exit: positive grade spins card off right edge
   C9  tamed toast: corner notification when nemesis card is tamed
   Settings: nemesisTheatrics=false in localStorage key iatro-nemesis-prefs-v1
             skips all animations below; colors still apply.
   Reduced motion: all transforms/animations suppressed; colors retained. */

/* --- Backdrop: charcoal+ember theme when nemesis card is active --- */
.nemesis-active {
  background: linear-gradient(135deg, #1a1a1a 0%, #2d1810 50%, #1a1a1a 100%) !important;
}

/* --- C6 card entry: weighted slide-in from right --- */
@keyframes nemesisSlideIn {
  from { opacity: 0; transform: translateX(60px); box-shadow: 0 2px 8px rgba(0,0,0,0.15); }
  to   { opacity: 1; transform: translateX(0);    box-shadow: 0 8px 32px rgba(0,0,0,0.3); }
}
.fc-card--nemesis.nemesis-entry {
  animation: nemesisSlideIn 420ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
  box-shadow: 0 8px 32px rgba(0,0,0,0.3);
}

/* --- C6 card ember stripe --- */
.fc-card--nemesis {
  border-left-color: var(--nemesis-ember) !important;
  box-shadow: inset 3px 0 8px rgba(232,93,38,0.3), 0 8px 32px rgba(0,0,0,0.3);
}

/* --- C7 taunt hold: keep card visible during 2s pause after low grade --- */
.fc-card--nemesis.nemesis-taunt {
  /* prevent the normal swipe-out from firing; JS adds this class, removes after 2s */
  animation: none !important;
}

/* --- C8 tumble exit: positive grade for nemesis card --- */
@keyframes nemesisTumbleOut {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateX(120%) rotate(12deg); }
}
.fc-card--nemesis.nemesis-tumble {
  animation: nemesisTumbleOut 400ms cubic-bezier(0.55, 0, 0.1, 1) forwards;
}

/* --- C9 tamed corner toast --- */
@keyframes tamedToastIn {
  from { opacity: 0; transform: translateY(-12px) scale(0.95); }
  to   { opacity: 1; transform: translateY(0)     scale(1);    }
}
@keyframes tamedToastOut {
  from { opacity: 1; transform: translateY(0)     scale(1);    }
  to   { opacity: 0; transform: translateY(-8px)  scale(0.96); }
}
.nemesis-tamed-toast {
  position: fixed;
  top: max(20px, env(safe-area-inset-top, 20px));
  right: max(16px, env(safe-area-inset-right, 16px));
  z-index: 10000;
  background: linear-gradient(135deg, #2d1810, #1a1a1a);
  color: #f5c87a;
  border: 1.5px solid var(--nemesis-ember);
  border-radius: var(--radius-md);
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  box-shadow: 0 4px 20px rgba(232,93,38,0.35);
  animation: tamedToastIn 220ms cubic-bezier(0.34,1.56,0.64,1) both;
  pointer-events: none;
  max-width: min(280px, 80vw);
}
.nemesis-tamed-toast.nemesis-tamed-toast--out {
  animation: tamedToastOut var(--duration-md) ease both;
}

/* --- Library "Tamed N×" chip --- */
.tamed-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: var(--font-size-2xs, 10px);
  font-weight: 600;
  padding: 2px 7px;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--nemesis-ember) 14%, transparent);
  color: var(--nemesis-ember);
  border: 0.5px solid color-mix(in srgb, var(--nemesis-ember) 30%, transparent);
  letter-spacing: 0.03em;
  white-space: nowrap;
}
html.dark .tamed-chip {
  background: color-mix(in srgb, var(--nemesis-ember) 20%, transparent);
  color: #f5c87a;
  border-color: color-mix(in srgb, var(--nemesis-ember) 40%, transparent);
}

/* --- Reduced motion overrides: suppress all nemesis transforms/animations --- */
@media (prefers-reduced-motion: reduce) {
  .fc-card--nemesis.nemesis-entry { animation: fadeIn var(--duration-sm) ease both; }
  .fc-card--nemesis.nemesis-tumble { animation: none; opacity: 0; }
  .nemesis-tamed-toast { animation: none; }
  .nemesis-tamed-toast.nemesis-tamed-toast--out { animation: none; opacity: 0; }
}
/* §5 Focus card types — token-driven mapping per v9.1.
   recall=sage/mint, nemesis=coral, saq=peri (pushed violet), fact=sky.
   Border + 5%-mixed surface tint share the family colour; type-label
   pill uses *-fill bg + *-deep text (alias resolves correctly in dark). */
/* Phase 7 (2026-05-02) — `--fc-card-surface` introduced so cinema-overlay
   cards can override the app `--surface` token. Cinema is always-dark by
   design (DESIGN.md §Cinema-overlay scoping rule), so cinema tokens carry no
   `html.dark` override. Cards inside cinema present as cream paper on the
   midnight stage in both themes.
   Stage 2 audit (2026-05-04, Run 2): the v229 cleanup left
   `--fc-card-surface: var(--surface)` which silently theme-leaked to
   `#182B26` forest-green in dark mode — broke the paper-on-stage metaphor
   (root cause of "focus mode is ugly"). Fixed cream literal restores the
   metaphor in both themes; literal hex is permitted inside cinema scope
   (consistent with `--focus-overlay-bg #08083B` and other cinema literals).
   Type tint bumped 5% → 8% to match the app-context level shipped in v229
   so type identity is readable on the cream cinema card. */
/* Light mode: cream surface for cinema cards. */
.focus-overlay { --fc-card-surface: #F5F1E6; }
/* Dark mode: identity-tinted dark surface. --fc-dm-card-tint controls the blend
   strength — update this single token to tune all dark-mode cinema card colours. */
html.dark .focus-overlay { --fc-card-surface: var(--surface); --fc-dm-card-tint: 18%; }
/* Light mode cinema cards lock to cream-surface text tokens so dark-mode --text
   (#F4ECDD) never resolves cream-on-cream inside the card body. */
html:not(.dark) .focus-overlay .fc-card {
  --text: #1F1D1A;
  --text-muted: #57524A;
  --text-faint: #6B6457;
  --border: rgba(0,0,0,0.10);
  color: var(--text);
  box-shadow: 0 4px 24px rgba(0,0,0,0.35);
  max-height: calc(100dvh - 170px);
  display: flex;
  flex-direction: column;
}
/* Dark mode cinema cards: use theme text tokens (light text on dark tinted surface). */
html.dark .focus-overlay .fc-card {
  --border: rgba(255,255,255,0.10);
  color: var(--text);
  box-shadow: 0 4px 32px rgba(0,0,0,0.55);
  max-height: calc(100dvh - 170px);
  display: flex;
  flex-direction: column;
}
/* Answer panel dark inset — restore cream text so answer reads on the elevated dark surface. */
html.dark .focus-overlay .fc-card .fc-answer {
  --text: #F4ECDD;
  --text-muted: #C2CCC5;
  color: var(--text);
}
/* Light mode: axiom/fact get a subtle lime tint on cream. */
html:not(.dark) .focus-overlay .fc-card[data-type="axiom"],
html:not(.dark) .focus-overlay .fc-card[data-type="fact"] {
  background: color-mix(in srgb, #8EA020 6%, #F5F1E6);
}
/* Card identity stripes — same in both themes; type backgrounds use --fc-card-surface token. */
.fc-card[data-type="recall"]      {border-left:6px solid var(--sky-deep);    background:var(--fc-card-surface)}
.fc-card[data-type="nemesis"]     {border-left:6px solid var(--coral-deep);  background:var(--fc-card-surface)}
.fc-card[data-type="saq"]         {border-left:6px solid var(--rose-deep);   background:var(--fc-card-surface)}
.fc-card[data-type="fact"]        {border-left:6px solid var(--saltbush-deep);   background:var(--fc-card-surface)}
.fc-card[data-type="axiom"]       {border-left:6px solid var(--saltbush-deep);   background:var(--fc-card-surface)}
/* patch-007 — Pharmacopia (drug field cards). */
.fc-card[data-type="pharmacopia"] {border-left:6px solid var(--violet-deep); background:var(--fc-card-surface)}
.fc-type-label{display:inline-flex;align-items:center;gap:5px;font-size:var(--font-size-2xs);font-weight:700;letter-spacing:0.06em;text-transform:uppercase;padding:4px 10px;border-radius:var(--radius-tiny);align-self:flex-start;flex-shrink:0}
.card-type-tag{position:absolute;top:8px;left:8px;z-index:1}
.study-card--recall .fc-type-label{background:var(--sky-fill);  color:var(--sky-deep)}
.study-card--saq    .fc-type-label{background:var(--rose-fill); color:var(--rose-deep)}
.study-card--axiom  .fc-type-label{background:var(--saltbush-fill); color:var(--saltbush-deep)}
.study-card--pharma .fc-type-label{background:var(--violet-fill);color:var(--violet-deep)}
html.dark .study-card--recall .fc-type-label{background:var(--sage-fill);color:var(--sage-deep)}
.fc-card[data-type="recall"]      .fc-type-label{background:var(--sky-fill);  color:var(--sky-deep)}
.fc-card[data-type="nemesis"]     .fc-type-label{background:var(--coral-fill);color:var(--coral-deep)}
.fc-card[data-type="saq"]         .fc-type-label{background:var(--rose-fill); color:var(--rose-deep)}
.fc-card[data-type="fact"]        .fc-type-label{background:var(--saltbush-fill); color:var(--saltbush-deep)}
.fc-card[data-type="axiom"]       .fc-type-label{background:var(--saltbush-fill); color:var(--saltbush-deep)}
.fc-card[data-type="pharmacopia"] .fc-type-label{background:var(--violet-fill); color:var(--violet-deep)}
/* Dark mode per-type backgrounds — identity colour mixed into dark surface at --fc-dm-card-tint.
   Recall uses --sage (sky-blue alias) instead of --sky (lime-gold in DM). Stripe colour also
   swapped for Recall so it reads sky-blue (sage) instead of lime-gold. */
html.dark .fc-card[data-type="recall"]         {border-left-color:var(--sage); background:color-mix(in srgb,var(--sage)   var(--fc-dm-card-tint,18%),var(--fc-card-surface))}
html.dark .fc-card[data-type="saq"]            {background:color-mix(in srgb,var(--rose)   var(--fc-dm-card-tint,18%),var(--fc-card-surface))}
html.dark .fc-card[data-type="pharmacopia"]    {background:color-mix(in srgb,var(--violet) var(--fc-dm-card-tint,18%),var(--fc-card-surface))}
html.dark .fc-card[data-type="axiom"]          {background:color-mix(in srgb,var(--saltbush)   var(--fc-dm-card-tint,18%),var(--fc-card-surface))}
html.dark .fc-card[data-type="fact"]           {background:color-mix(in srgb,var(--saltbush)   var(--fc-dm-card-tint,18%),var(--fc-card-surface))}
html.dark .fc-card[data-type="nemesis"]        {background:color-mix(in srgb,var(--coral)  var(--fc-dm-card-tint,18%),var(--fc-card-surface))}
html.dark .fc-card[data-type="image_occlusion"]{background:color-mix(in srgb,var(--sage)   var(--fc-dm-card-tint,18%),var(--fc-card-surface))}
html.dark .fc-card[data-type="recall"]      .fc-type-label{background:var(--sage-fill); color:var(--sage-deep)}
/* Pharmacopia meta header inside the card body — drug name + field key. */
.fc-pharma-meta{font-size:var(--font-size-sm);font-weight:500;color:var(--violet-deep);padding:14px 24px 0;letter-spacing:0.02em;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
/* patch-028 polish — direction badge for reverse pharma cards (drug→class etc) */
.fc-pharma-reverse-badge{font-size:var(--font-size-2xs);font-weight:600;padding:2px 8px;border-radius:var(--radius-pill);background:color-mix(in srgb,var(--violet) 14%,transparent);color:var(--violet-deep);border:0.5px solid color-mix(in srgb,var(--violet) 28%,transparent);letter-spacing:0.02em;white-space:nowrap}
/* patch-033 image-occlusion — image card with SVG mask overlay + per-region grade panel */
.fc-card--image-occlusion .fc-body--image{padding:12px 16px 16px;display:flex;flex-direction:column;gap:8px}
.fc-image-title{font-size:var(--font-size-lg);font-weight:600;color:var(--text);line-height:1.3}
.fc-image-source{font-size:var(--font-size-xs);color:var(--text-muted);font-style:italic}
.fc-image-stage{position:relative;width:100%;background:var(--surface-soft,var(--surface));border-radius:var(--radius-sm);overflow:hidden;border:1px solid var(--border)}
.fc-image{display:block;width:100%;height:auto}
.fc-image-overlay{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.fc-image-region{pointer-events:auto;transition:opacity .15s}
.fc-image-region-rect{fill:color-mix(in srgb,var(--accent,#0d6e6b) 78%,transparent);stroke:var(--accent,#0d6e6b);stroke-width:1.5;transition:fill .25s,opacity .25s}
.fc-image-region:hover .fc-image-region-rect{fill:color-mix(in srgb,var(--accent,#0d6e6b) 60%,transparent)}
.fc-image-region.open .fc-image-region-rect{fill:color-mix(in srgb,var(--accent,#0d6e6b) 14%,transparent);stroke:color-mix(in srgb,var(--accent,#0d6e6b) 40%,transparent);stroke-dasharray:4 3}
.fc-image-region-label{fill:white;font-weight:600;letter-spacing:0.01em;opacity:0;transition:opacity .25s;text-shadow:0 1px 2px rgba(0,0,0,0.5);pointer-events:none}
.fc-image-region.open .fc-image-region-label{opacity:1;fill:var(--text)}
.fc-image-region.graded[data-grade="1"] .fc-image-region-rect{stroke:var(--coral,#dc2626)}
.fc-image-region.graded[data-grade="3"] .fc-image-region-rect{stroke:var(--sage-deep,#15803D)}
.fc-image-region.graded[data-grade="4"] .fc-image-region-rect{stroke:var(--violet)}
.fc-image-grade-panel{margin-top:6px;padding:10px 12px;border-radius:var(--radius-sm);background:color-mix(in srgb,var(--accent,#0d6e6b) 6%,var(--surface));border:1px solid color-mix(in srgb,var(--accent,#0d6e6b) 18%,transparent)}
.fc-image-grade-head{font-size:var(--font-size-md);font-weight:600;color:var(--text);margin-bottom:4px}
.fc-image-grade-hint{font-size:var(--font-size-sm);color:var(--text-muted);margin-bottom:8px;font-style:italic}
.fc-image-grade-btns{display:flex;gap:6px}
.fc-image-grade-btns .fc-grade-btn{flex:1;padding:8px;font-size:var(--font-size-md)}
.fc-image-progress{font-size:var(--font-size-xs);color:var(--text-muted);text-align:center;letter-spacing:0.04em;text-transform:uppercase}
.fc-image-progress.complete{color:var(--accent,#0d6e6b);font-weight:600}
.fc-type-label--image{background:color-mix(in srgb,var(--accent,#0d6e6b) 18%,transparent);color:var(--accent,#0d6e6b)}
/* patch-028b — Daily morning briefing banner (Phase 1 ship #2). Sits below stage-hero on Today tab (WS10 reposition). */
.morning-briefing-banner{margin:6px 12px 10px;padding:12px 14px 12px 16px;border-radius:var(--radius);background:color-mix(in srgb,var(--accent,#0d6e6b) 6%,var(--surface));border:1px solid color-mix(in srgb,var(--accent,#0d6e6b) 18%,transparent);position:relative;font-size:var(--font-size-md);line-height:1.45;color:var(--text)}
.morning-briefing-banner .mb-title{display:block;font-size:var(--font-size-xs);font-weight:600;text-transform:uppercase;letter-spacing:0.06em;color:var(--accent,#0d6e6b);margin-bottom:6px}
.morning-briefing-banner ul.mb-lines{margin:0;padding:0;list-style:none;display:grid;gap:4px}
.morning-briefing-banner ul.mb-lines li{display:flex;align-items:baseline;gap:8px;color:var(--text)}
.morning-briefing-banner ul.mb-lines li .mb-key{font-weight:600;min-width:84px;color:var(--text-muted);font-size:var(--font-size-sm)}
.morning-briefing-banner ul.mb-lines li .mb-val{flex:1;font-size:var(--font-size-md)}
.morning-briefing-banner .mb-dismiss{position:absolute;top:6px;right:6px;width:28px;height:28px;border:0;background:transparent;color:var(--text-muted);font-size:18px;line-height:1;cursor:pointer;border-radius:var(--btn-radius)}
.morning-briefing-banner .mb-dismiss:hover{background:color-mix(in srgb,var(--text-muted) 12%,transparent);color:var(--text)}
/* §5 FM2 — body padding matches the card's prompt-led design. The prompt
   itself takes 28px 24px 18px per spec; answer/tags follow at 0 24px so
   they hang off the prompt's left edge with consistent gutters. */
.fc-body{padding:0;flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:8px;min-height:0}
/* Post-v9.1 audit — prompt size bumped from 17→19px in focus mode. The
   takeover has more room than the Today tab cards; using it makes the
   prompt the visual hero. The .fc-saq-q variant tracks the same size. */
/* v172 P3 — padding-right bumped 24→80px so the absolutely-positioned
   timer pill (.fc-timer-pomodoro at top:10/right:10, ~52px wide) never
   overlaps wrapped prompt text. Issue #7 was mechanically resolved by
   the min-height/flex layout but explicit clearance is more robust. */
.fc-prompt{font-size:clamp(16px,2.4vw,20px);font-weight:500;line-height:1.45;color:var(--text);padding:24px 80px 14px 24px;font-family:var(--font-sans)}
/* Cards without a timer (recall, fact, pharma) don't need the inset. */
.fc-card:not([data-type="saq"]) .fc-prompt{padding-right:24px}
.fc-saq-q{font-size:clamp(16px,2.4vw,20px);line-height:1.45}
/* v107 — saqPassRateBefore kicker: small muted text below the SAQ question, pre-reveal */
.saq-pass-rate-kicker{font-size:var(--font-size-xs);color:var(--text-muted);padding:0 24px 10px;font-style:italic}
.fc-card.revealed .saq-pass-rate-kicker{display:none}
.fc-tag{font-size:var(--font-size-xs);color:var(--text-muted);padding:0 24px}
.fc-tag a{color:var(--text-muted);text-decoration:none;border-bottom:1px dotted var(--text-faint)}
/* §5 FM1 (AP1) — answer hidden until .fc-card.revealed. Solid border +
   surface-elevated background; never dashed (dashed reserved for §5 pre-
   reveal placeholder zones we don't render). 180ms fadeIn matches §7. */
.fc-answer{
  display:none;
  margin:0 24px 16px;
  /* Card-redesign 2026-05-05 IMPROVE — solidity rule §21: no inner box-within-card
     chrome. Body sits flush on the card surface; padding alone gives breathing room. */
  background:transparent;
  border:0;
  border-radius:0;
  padding:0 0 4px;
  font-size:clamp(13px,1.8vw,16px);line-height:1.55;color:var(--text);
}
.fc-card.revealed .fc-answer{display:block;animation:fcRevealAnswerIn var(--duration-lg) var(--ease-out) both}
/* SAQ focus card (2026-05-26): the model answer fills the card to the bottom and
   uses near-full width; a wide diagram scrolls horizontally instead of clipping.
   Prompt sits high (less wasted space above the stem). The SAQ prompt lives
   OUTSIDE .fc-body, so .fc-body/.fc-answer are the flex:1 region below it. */
.fc-card[data-type="saq"] .fc-prompt{padding-top:12px;padding-bottom:10px}
.fc-card[data-type="saq"] .fc-body{padding-bottom:0;min-height:0}
.fc-card.revealed[data-type="saq"] .fc-answer{flex:1 1 auto;min-height:0;margin:0 14px 12px;overflow-y:auto;overflow-x:hidden}
.fc-card[data-type="saq"] .fc-answer pre,
.fc-card[data-type="saq"] .fc-answer table,
.fc-card[data-type="saq"] .fc-answer .fc-callout{max-width:100%;overflow-x:auto}
/* Card-unification sprint J — Today/Library grid cards (.study-card, not .fc-card) use
   the same .fc-answer reveal pattern. Covers axiom, recall, saq, pharma grid cards. */
.study-card.revealed .fc-answer{display:block;animation:fcRevealAnswerIn var(--duration-lg) var(--ease-out) both}
/* Nav-return: card was already graded and user navigated back to it.
   Skip the reveal animation so the card appears instantly in its graded
   state rather than replaying the unrevealed → revealed transition. */
.fc-card--nav-return .fc-answer,
.fc-card--nav-return .fc-action-bar{animation:none !important}

/* RICHCARDS v3 §3 — cloze body, Extra, Mnemonic. Shared classes used by both
   Focus mode (.fc-card.revealed) and the Today tab (.recall-card.revealed) so
   one set of rules covers both renderers. */
.fc-cloze-body{font-size:clamp(13px,1.8vw,16px);line-height:1.6;color:var(--text);padding:0 24px 4px;margin:0;font-family:var(--font-sans)}
.recall-card .fc-cloze-body{font-size:var(--font-size-lg);line-height:1.55;padding:6px 0 4px}
.fc-cloze-blank{display:inline;background:var(--honey-fill);color:var(--honey-deep);border-radius:var(--radius-tiny);padding:1px 6px;font-weight:500}
.fc-cloze-rev{display:none;background:var(--sage-fill);color:var(--sage-deep);border-radius:var(--radius-tiny);padding:1px 6px;font-weight:500}
.fc-card.revealed .fc-cloze-blank,.recall-card.revealed .fc-cloze-blank{display:none}
.fc-card.revealed .fc-cloze-rev,.recall-card.revealed .fc-cloze-rev{display:inline}
.fc-cloze-sibling{color:var(--text-muted-strong)} /* WS11 v9.7-foundation: dropped opacity:0.75 (~3:1 FAIL on dark surface); --text-muted-strong is pre-mixed ≥4.5:1 AA body */
.fc-cloze-hint{font-style:italic;font-size:0.85em;opacity:0.8}

.fc-extra,.fc-mnemonic{display:none;margin:0 24px 12px;padding:10px 12px;border-radius:var(--radius-sm);font-size:var(--font-size-md);line-height:1.55}
.recall-card .fc-extra,.recall-card .fc-mnemonic{margin:8px 0 0}
.fc-card.revealed .fc-extra,.fc-card.revealed .fc-mnemonic,.recall-card.revealed .fc-extra,.recall-card.revealed .fc-mnemonic{display:block;animation:fadeIn .2s}
.fc-extra{background:color-mix(in srgb,var(--text) 4%,var(--surface));border:0.5px solid var(--border)}
.fc-extra-label,.fc-mnemonic-label{font-size:var(--font-size-2xs);font-weight:700;letter-spacing:0.06em;text-transform:uppercase;color:var(--text-muted);margin-bottom:4px}
.fc-extra-body{color:var(--text)}
.fc-mnemonic{background:var(--violet-fill);border:0.5px solid color-mix(in srgb,var(--violet) 30%,transparent);color:var(--violet-deep)}
.fc-mnemonic-label{color:var(--violet-deep)}
.fc-mnemonic-body{font-style:italic}

/* F-P2-44: .fc-tap-hint rules removed (no JS creates this class). */
/* F-P2-44: orphaned patch-008 .fc-conf-* comment block removed. */
.fc-action-bar{display:none;gap:0;border-top:1px solid var(--border);flex-shrink:0;border-bottom-left-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg);overflow:hidden}
/* Card-redesign 2026-05-05 IMPROVE — kill the star-shape "central hole" caused
   by 3 rounded buttons meeting at the inverted-T cross. Buttons tile flush;
   outer corners come from .fc-action-bar's border-radius + overflow:hidden. */
.fc-action-bar .fc-grade-btn{border-radius:0}
.fc-card.revealed .fc-action-bar{display:flex;flex-wrap:wrap;animation:fcRevealActionBarIn var(--duration-lg) var(--ease-out) both;animation-delay:.06s}
/* Today-fix v3 — Focus mode Missed → reveals .miss-tag-overlay--focus
   in place of the binary action bar. Same takeover pattern as the
   Today recall card: hide the Got/Miss row, expand the overlay full-
   width along the bottom of the card. */
.fc-card.revealed.tag-open .fc-action-bar{display:none}
.fc-card .miss-tag-overlay--focus{display:none}
.fc-card.revealed.tag-open .miss-tag-overlay--focus{display:block;border-top:1px solid var(--coral)}
/* patch-008 — universal 3-button focus action bar. Equal-flex tiles split
   the action area; subtle vertical separators preserve the original
   borderless feel. Hover/active states tint per grade. */
/* v177 N10 — Grade button colour palette INVERTED.
   Was: rest = muted, active = vibrant.
   Now: rest = vibrant (so the user sees the strong intent of each option
   before they decide), active = muted (signals "you've made your call,
   tap again to reset"). The reset gesture is the inversion: muted means
   commit, vibrant means available-to-press. */
.fc-grade-btn{
  flex:1;padding:16px 12px;border:none;background:var(--surface);
  font-size:var(--font-size-lg);font-weight:700;cursor:pointer;
  display:flex;align-items:center;justify-content:center;gap:6px;
  transition:background var(--duration-sm),color var(--duration-sm),opacity var(--duration-sm);
}
.fc-grade-btn + .fc-grade-btn{border-left:0.5px solid var(--border)}
/* Inverted-T layout: Mastered full-width on top, Missed | Honed half-width below.
   DOM order Missed→Honed→Mastered; order:-1 hoists Mastered to top row via flex-wrap.
   Collapse: when .active (re-graded), others hide and active fills the full width. */
.fc-action-bar:has(.fc-grade-btn.active) .fc-grade-btn:not(.active){display:none}
.fc-action-bar:has(.fc-grade-btn.active) .fc-grade-btn.active{flex:1 1 100%;border:none}
/* Pre-grade state: solid fill + white text */
.fc-grade-btn--missed  {background:var(--coral-vivid);color:#fff}
.fc-grade-btn--hazy    {background:var(--fc-badge-hazy);color:var(--fc-badge-hazy-text)}
.fc-grade-btn--honed   {background:var(--fc-badge-honed);color:#fff}
.fc-grade-btn--mastered{background:var(--fc-badge-mastered);color:#fff;order:-1;flex:1 1 100%;border-left:none!important;border-bottom:0.5px solid rgba(255,255,255,.18)}
/* Hover = darken 15 % (mirrors .r-grade hover). */
.fc-grade-btn--missed:hover,
.fc-grade-btn--missed:active   {background:color-mix(in srgb,var(--coral-vivid) 85%,#000)}
.fc-grade-btn--honed:hover,
.fc-grade-btn--honed:active    {background:color-mix(in srgb,var(--fc-badge-honed) 85%,#000)}
.fc-grade-btn--mastered:hover,
.fc-grade-btn--mastered:active {background:color-mix(in srgb,var(--fc-badge-mastered) 85%,#000)}
/* Card-redesign 2026-05-05 IMPROVE — cinema scope override.
   .focus-overlay .btn--primary (0,2,0) and its :hover:not(:disabled) (0,4,0)
   were overriding the per-grade rules. Match the specificity with :not(:disabled)
   so each grade keeps its identity at rest AND on hover. */
.focus-overlay .fc-grade-btn--missed:not(:disabled)   {background:var(--coral-vivid);          color:#fff;border-color:var(--coral-vivid)}
.focus-overlay .fc-grade-btn--honed:not(:disabled)    {background:var(--fc-badge-honed);       color:#fff;border-color:var(--fc-badge-honed)}
.focus-overlay .fc-grade-btn--mastered:not(:disabled) {background:var(--fc-badge-mastered);    color:#fff;border-color:var(--fc-badge-mastered)}
/* AUDIT-2026-05-06 #2 (Sprint 2) — Night-mode comfort. Filled cinema palette
   reads as "painful at night" against the deep-midnight cinema bg. Override
   resting state to outlined-with-tint (12% fill + 1.5px border + colored text)
   so grade buttons feel calm at rest. Hover/active flips to filled for unmistakable
   tap feedback. The filled :active state still uses the WCAG-tuned palette. */
html.dark .focus-overlay .fc-grade-btn--missed:not(:disabled){
  background:color-mix(in srgb, var(--coral-vivid) 14%, transparent);
  color:var(--coral-vivid);
  border-color:color-mix(in srgb, var(--coral-vivid) 70%, transparent);
}
html.dark .focus-overlay .fc-grade-btn--honed:not(:disabled){
  background:color-mix(in srgb, var(--fc-badge-honed) 16%, transparent);
  color:color-mix(in srgb, var(--fc-badge-honed) 75%, #fff);
  border-color:color-mix(in srgb, var(--fc-badge-honed) 70%, transparent);
}
html.dark .focus-overlay .fc-grade-btn--mastered:not(:disabled){
  background:color-mix(in srgb, var(--fc-badge-mastered) 16%, transparent);
  color:color-mix(in srgb, var(--fc-badge-mastered) 80%, #fff);
  border-color:color-mix(in srgb, var(--fc-badge-mastered) 70%, transparent);
}
/* Hover/active in dark — fills back up to the saturated palette so the user
   gets clear tap feedback. Bigger contrast jump than light mode's darken. */
html.dark .focus-overlay .fc-grade-btn--missed:hover:not(:disabled),
html.dark .focus-overlay .fc-grade-btn--missed:active:not(:disabled){
  background:var(--coral-vivid); color:#fff; border-color:var(--coral-vivid);
}
html.dark .focus-overlay .fc-grade-btn--honed:hover:not(:disabled),
html.dark .focus-overlay .fc-grade-btn--honed:active:not(:disabled){
  background:var(--fc-badge-honed); color:#fff; border-color:var(--fc-badge-honed);
}
html.dark .focus-overlay .fc-grade-btn--mastered:hover:not(:disabled),
html.dark .focus-overlay .fc-grade-btn--mastered:active:not(:disabled){
  background:var(--fc-badge-mastered); color:#fff; border-color:var(--fc-badge-mastered);
}
.focus-overlay .fc-grade-btn--missed:hover:not(:disabled),
.focus-overlay .fc-grade-btn--missed:active:not(:disabled)   {background:color-mix(in srgb,var(--coral-vivid) 85%,#000)}
.focus-overlay .fc-grade-btn--honed:hover:not(:disabled),
.focus-overlay .fc-grade-btn--honed:active:not(:disabled)    {background:color-mix(in srgb,var(--fc-badge-honed) 85%,#000)}
.focus-overlay .fc-grade-btn--mastered:hover:not(:disabled),
.focus-overlay .fc-grade-btn--mastered:active:not(:disabled) {background:color-mix(in srgb,var(--fc-badge-mastered) 85%,#000)}

/* v177 N9 — Card reset animation (Option B · eraser wipe). Triggered by
   adding .fc-card--reset to the card; removed after 480ms by the JS reset
   handler. Violet pseudo-element sweeps L→R across the card surface,
   masking the answer; card content fades to 0. After the animation
   finishes the card is re-rendered fresh (unrevealed). */
.fc-card--reset{position:relative;overflow:hidden}
.fc-card--reset::after{
  content:'';position:absolute;inset:0;
  background:linear-gradient(90deg,
    transparent 0%,
    color-mix(in srgb,var(--violet,#7F77DD) 65%,transparent) 35%,
    color-mix(in srgb,var(--violet,#7F77DD) 90%,transparent) 50%,
    color-mix(in srgb,var(--violet,#7F77DD) 65%,transparent) 65%,
    transparent 100%);
  transform:translateX(-110%);
  animation:fcCardWipe .48s cubic-bezier(.5,0,.4,1) forwards;
  pointer-events:none;z-index:10;border-radius:inherit;
}
.fc-card--reset .fc-body,.fc-card--reset .fc-action-bar,.fc-card--reset .fc-card-back{
  animation:fcCardFade .32s ease forwards;
}
@keyframes fcCardWipe{
  0%{transform:translateX(-110%)}
  100%{transform:translateX(110%)}
}
@keyframes fcCardFade{
  0%{opacity:1}
  60%{opacity:.15}
  100%{opacity:0}
}
@media(prefers-reduced-motion:reduce){
  .fc-card--reset::after{animation-duration:.08s}
  .fc-card--reset .fc-body,.fc-card--reset .fc-action-bar,
  .fc-card--reset .fc-card-back{animation:none;opacity:0}
}

/* v177 N10 — Active (post-grade) state = MUTED. The user has committed.
   Tapping the muted button RESETS (per N9). Lower opacity + neutral bg
   signals "this is your selection, tap again to undo". */
.fc-grade-btn.active{
  background:var(--surface)!important;
  color:var(--text-muted)!important;
  opacity:.75;
}
.fc-grade-btn.active::after{
  content:'· tap to reset';
  font-size:var(--font-size-2xs);font-weight:500;opacity:.7;margin-left:6px;letter-spacing:0.02em;
}
/* v[next] — Focus overlay: filled = pre-grade, outline = selected.
   Mirrors the non-focus fill/outline swap so the visual language is consistent.
   .active = re-visit "already graded" state (tapping resets card).
   .graded = ephemeral selection flash during the 260ms swipe-out animation. */
.focus-overlay .fc-grade-btn.active{background:transparent!important;opacity:1}
.focus-overlay .fc-grade-btn--missed.active  {border:1.5px solid var(--coral-vivid)!important;color:var(--coral-vivid)!important}
.focus-overlay .fc-grade-btn--honed.active   {border:1.5px solid var(--fc-badge-honed)!important;color:var(--fc-badge-honed)!important}
.focus-overlay .fc-grade-btn--mastered.active{border:1.5px solid var(--fc-badge-mastered)!important;color:var(--fc-badge-mastered)!important}
/* Suppress "· tap to reset" label in focus overlay — card is animating, no space */
.focus-overlay .fc-grade-btn.active::after{display:none}
/* .graded — applied by JS the moment a grade is chosen; lives for 260ms while card exits */
.focus-overlay .fc-grade-btn.graded{background:transparent!important;opacity:1}
.focus-overlay .fc-grade-btn--missed.graded  {border:1.5px solid var(--coral-vivid)!important;color:var(--coral-vivid)!important}
.focus-overlay .fc-grade-btn--honed.graded   {border:1.5px solid var(--fc-badge-honed)!important;color:var(--fc-badge-honed)!important}
.focus-overlay .fc-grade-btn--mastered.graded{border:1.5px solid var(--fc-badge-mastered)!important;color:var(--fc-badge-mastered)!important}
/* Dim ungraded siblings while one is graded */
.focus-overlay .fc-action-bar:has(.fc-grade-btn.graded) .fc-grade-btn:not(.graded){opacity:0.3;transition:opacity .08s}
.fc-show-btn{display:block;width:calc(100% - 32px);margin:0 auto 16px;align-self:center;padding:14px;border:none;border-radius:var(--radius-md);background:var(--accent);color:white;font-size:var(--font-size-lg);font-weight:700;cursor:pointer;box-shadow:0 3px 0 var(--accent-pressed);transition:background .1s,color .1s,border-color .1s,box-shadow .1s,transform .1s,opacity .1s;flex-shrink:0;box-sizing:border-box}
.fc-show-btn:hover{transform:translateY(-1px);box-shadow:0 4px 0 var(--accent-pressed)}
.fc-show-btn:active{transform:translateY(2px);box-shadow:0 1px 0 var(--accent-pressed)}
.fc-card.revealed .fc-show-btn{display:none}
/* Focus-overlay Show Answer uses --accent so cinema chrome follows palette changes. */
.focus-overlay .fc-show-btn{background:var(--accent);box-shadow:0 3px 0 var(--accent-pressed)}
.focus-overlay .fc-show-btn:hover{box-shadow:0 4px 0 var(--accent-pressed)}
.focus-overlay .fc-show-btn:active{box-shadow:0 1px 0 var(--accent-pressed)}
/* v59 — SAQ identity row at top-left, position:absolute so it sits
   outside the rotating .fc-card-inner and doesn't mirror on flip. */
.fc-saq-header-row{
  position:absolute;top:8px;left:8px;
  display:flex;align-items:center;gap:8px;
  z-index:3;
  pointer-events:none;
}
.fc-saq-header-row .fc-type-label{pointer-events:auto}
/* v178 — fc-card-front/back are dead classes (old 3D-flip architecture).
   The question (fc-prompt) is now appended directly to fc-card in JS,
   outside the scrollable fc-body, so it can never scroll behind the
   absolute header row. padding-top clears the header (top:14px + ~20px
   label height = ~34px; 72px gives generous breathing room on all
   viewports including when the meta wraps). flex-shrink:0 prevents the
   card's flex layout from compressing the question. */
.fc-card[data-type="saq"] .fc-prompt{padding-top:72px;flex-shrink:0}
@media(max-width:600px){
  .fc-card[data-type="saq"] .fc-prompt{padding-top:84px}
}
.fc-saq-meta--inline{
  display:inline-flex;align-items:center;gap:6px;
  font-size:var(--font-size-xs);color:var(--text-muted);
  flex-wrap:wrap;
}
.fc-saq-meta-txt{font-weight:500;letter-spacing:0.02em}
.fc-saq-meta-sep{opacity:0.5}
.fc-saq-meta-pill{
  display:inline-flex;align-items:center;
  font-size:var(--font-size-xs);font-weight:600;
  padding:2px 7px;border-radius:var(--radius-pill);
  letter-spacing:0.02em;
}
.fc-saq-meta-pill.pill-low{background:var(--coral-fill);color:var(--coral-deep)}
.fc-saq-meta-pill.pill-mid{background:var(--honey-fill);color:var(--honey-deep)}
.fc-saq-meta-pill.pill-high{background:var(--sage-fill);color:var(--sage-deep)}

/* v58 — pomodoro timer in the top-right corner of the SAQ card.
   Single button — click toggles play/pause. The countdown text
   sits inside the ring so the time is always visible. Tooltip
   updates per-state via updateFmTimerHover() so the user knows
   what'll happen on click. */
.fc-timer-pomodoro{
  position:absolute;top:10px;right:10px;
  width:48px;height:48px;
  border:none;background:transparent;padding:0;
  cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;
  z-index:3;
  transition:transform var(--duration-sm);
}
.fc-timer-pomodoro:hover{transform:scale(1.06)}
.fc-timer-pomodoro:active{transform:scale(0.96)}
.fc-timer-ring{width:48px;height:48px;cursor:pointer}
.fc-timer-ring circle{fill:none;stroke-width:3;stroke-linecap:round}
.fc-timer-track{stroke:var(--border)}
/* patch-007 — Focus-mode SAQ timer ring stroke migrated peri → honey
   to match the SAQ identity colour. Was a leftover from the peri palette. */
.fc-timer-fill{stroke:var(--honey);stroke-dasharray:157;stroke-dashoffset:0;transition:stroke-dashoffset 1s linear,stroke .5s}
.fc-timer-text{
  font-size:9.5px;font-family:var(--font-mono);font-weight:600;
  fill:var(--text);
  dominant-baseline:middle;text-anchor:middle;
}
/* Idle state — show a play glyph instead of the time when paused. */
.fc-timer-pomodoro:not(.is-running) .fc-timer-text{fill:var(--peri-deep)}
.fc-timer-pomodoro.is-running .fc-timer-fill{stroke:var(--peri)}
.fc-timer-pomodoro.is-done .fc-timer-fill{stroke:var(--coral)}
.fc-timer-pomodoro.is-done .fc-timer-text{fill:var(--coral-deep)}

/* ── SAQ timer chip + settings drawer ──────────────────────────────────────
   Sprint B PR4 redesign — filled rose-deep chip with colour-state escalation
   (default → warn ≤3min → urgent ≤1min → zero) and a slide-down drawer for
   per-Q time, total questions, sound, vibrate. JS owns data-state.
   Tokens (light + dark) defined alongside the chip below. */
:root{
  --fc-saq-timer-bg:var(--rose-deep);
  --fc-saq-timer-fg:#FFFFFF;
  --fc-saq-timer-warn-bg:var(--honey-deep);
  --fc-saq-timer-warn-fg:#FFFFFF;
  --fc-saq-timer-urgent-bg:var(--coral-deep);
  --fc-saq-timer-urgent-fg:#FFFFFF;
  --fc-saq-timer-zero-bg:#A12015;
  --fc-saq-timer-zero-fg:#FFFFFF;
}
html.dark{
  /* dark-mode rose-deep is too pale for white text — drop to rose for AA */
  --fc-saq-timer-bg:var(--rose);
  --fc-saq-timer-fg:#FFFFFF;
  --fc-saq-timer-warn-bg:#D88A2A;
  --fc-saq-timer-warn-fg:#FFFFFF;
  --fc-saq-timer-urgent-bg:#D85042;
  --fc-saq-timer-urgent-fg:#FFFFFF;
  --fc-saq-timer-zero-bg:#B82A1E;
  --fc-saq-timer-zero-fg:#FFFFFF;
}

.fc-saq-timer-wrap{
  display:flex;flex-direction:column;align-items:center;gap:8px;margin:4px auto;
}
.fc-saq-timer-wrap:has(>.fc-saq-timer-chip[hidden]){display:none}

.fc-saq-timer-chip{
  display:inline-flex;align-items:stretch;gap:0;
  background:var(--fc-saq-timer-bg);color:var(--fc-saq-timer-fg);
  border-radius:var(--btn-radius-pill,999px);
  box-shadow:var(--shadow-md);
  font-family:var(--font-sans);
  transition:background-color var(--duration-md) var(--ease-out-quart,cubic-bezier(.165,.84,.44,1)),
             box-shadow var(--duration-md) var(--ease-out-quart,cubic-bezier(.165,.84,.44,1)),
             transform var(--duration-md) var(--ease-out-quart,cubic-bezier(.165,.84,.44,1));
  user-select:none;-webkit-user-select:none;
}
.fc-saq-timer-chip[hidden]{display:none}
.fc-saq-timer-chip[data-state="warn"]{background:var(--fc-saq-timer-warn-bg);color:var(--fc-saq-timer-warn-fg)}
.fc-saq-timer-chip[data-state="urgent"]{background:var(--fc-saq-timer-urgent-bg);color:var(--fc-saq-timer-urgent-fg)}
.fc-saq-timer-chip[data-state="zero"]{
  background:var(--fc-saq-timer-zero-bg);color:var(--fc-saq-timer-zero-fg);
}
.fc-saq-timer-chip[data-paused="true"]{
  background:color-mix(in srgb,var(--fc-saq-timer-bg) 65%,#000);opacity:.92;
}
.fc-saq-timer-chip[data-paused="true"][data-state="warn"]{background:color-mix(in srgb,var(--fc-saq-timer-warn-bg) 65%,#000)}
.fc-saq-timer-chip[data-paused="true"][data-state="urgent"]{background:color-mix(in srgb,var(--fc-saq-timer-urgent-bg) 65%,#000)}

@keyframes fcSaqTimerZeroPulse{0%,100%{transform:scale(1)}50%{transform:scale(1.04);box-shadow:var(--shadow-lg)}}
@keyframes fcSaqTimer2MinPulse{0%{transform:scale(1)}40%{transform:scale(1.06)}100%{transform:scale(1)}}
@keyframes fcSaqTimerMinFlash{0%{opacity:.7}100%{opacity:1}}
@media(prefers-reduced-motion:no-preference){
  .fc-saq-timer-chip[data-state="zero"]{animation:fcSaqTimerZeroPulse 1500ms ease-in-out infinite}
  .fc-saq-timer-chip.timer-2min-pulse{animation:fcSaqTimer2MinPulse 600ms var(--ease-out-quart,cubic-bezier(.165,.84,.44,1))}
  .fc-saq-timer-chip.timer-min-flash{animation:fcSaqTimerMinFlash var(--duration-md) ease-out}
}

.fc-saq-timer-icon{
  display:inline-flex;align-items:center;justify-content:center;
  padding:0 0 0 12px;color:currentColor;
}
.fc-saq-timer-icon svg{width:14px;height:14px;stroke:currentColor;fill:none}

.fc-saq-timer-digits{
  appearance:none;border:none;background:transparent;
  color:inherit;cursor:pointer;font-family:inherit;
  padding:8px 14px 8px 8px;
  font-size:18px;font-weight:700;letter-spacing:.02em;
  font-variant-numeric:tabular-nums;
  display:inline-flex;align-items:center;gap:7px;line-height:1;
  border-radius:var(--btn-radius-pill,999px);
  transition:background var(--duration-sm);
}
.fc-saq-timer-digits:hover{background:color-mix(in srgb,#fff 12%,transparent)}
.fc-saq-timer-digits:focus-visible{outline:2px solid #fff;outline-offset:2px}
.fc-saq-timer-chip[data-paused="true"] .fc-saq-timer-digits::after{
  content:"";display:inline-block;width:3px;height:14px;
  border-left:3px double currentColor;margin-left:2px;opacity:.85;
}
/* TIME UP label replaces digits at zero */
.fc-saq-timer-digits[data-zero="true"]{
  font-size:13px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;
}

.fc-saq-timer-divider{
  width:1px;background:color-mix(in srgb,#fff 22%,transparent);
  margin:8px 0;flex:0 0 auto;
}

.fc-saq-timer-gear{
  appearance:none;border:none;background:transparent;
  color:inherit;cursor:pointer;
  padding:0 12px 0 4px;
  display:inline-flex;align-items:center;justify-content:center;
  border-radius:0 var(--btn-radius-pill,999px) var(--btn-radius-pill,999px) 0;
  transition:background var(--duration-sm),transform .14s var(--ease-out-quart,cubic-bezier(.165,.84,.44,1));
}
.fc-saq-timer-gear:hover{background:color-mix(in srgb,#fff 12%,transparent)}
.fc-saq-timer-gear:focus-visible{outline:2px solid #fff;outline-offset:-2px}
.fc-saq-timer-gear svg{width:15px;height:15px;stroke:currentColor;fill:none}
.fc-saq-timer-chip[data-drawer-open="true"] .fc-saq-timer-gear{transform:rotate(28deg)}
@media(prefers-reduced-motion:reduce){
  .fc-saq-timer-gear{transition:none}
  .fc-saq-timer-chip[data-drawer-open="true"] .fc-saq-timer-gear{transform:none}
  .fc-saq-timer-chip{transition:background-color .1s linear}
}

/* Drawer (slide-down from below the chip) */
.fc-saq-timer-drawer{
  width:300px;max-width:calc(100vw - 48px);
  background:var(--surface-elevated);
  border:1px solid var(--border);
  border-radius:var(--radius);
  box-shadow:var(--shadow-lg);
  padding:14px 14px 12px;
  transform-origin:top center;
  opacity:0;transform:translateY(-6px) scale(.98);
  pointer-events:none;
  transition:opacity var(--duration-md) var(--ease-out-quart,cubic-bezier(.165,.84,.44,1)),
             transform var(--duration-md) var(--ease-out-quart,cubic-bezier(.165,.84,.44,1));
}
.fc-saq-timer-drawer[hidden]{display:none!important}
.fc-saq-timer-wrap[data-drawer-open="true"] .fc-saq-timer-drawer{
  opacity:1;transform:translateY(0) scale(1);pointer-events:auto;
}
@media(prefers-reduced-motion:reduce){
  .fc-saq-timer-drawer{transition:opacity .1s linear;transform:none!important}
}
.fc-saq-timer-drawer-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:12px}
.fc-saq-timer-drawer-title{margin:0;font-size:var(--font-size-md);font-weight:700;color:var(--text);letter-spacing:.005em}
.fc-saq-timer-drawer-sub{font-size:var(--font-size-xs);color:var(--text-faint);font-variant-numeric:tabular-nums}
.fc-saq-timer-drawer-section{margin-bottom:12px}
.fc-saq-timer-drawer-section:last-of-type{margin-bottom:8px}

.fc-saq-timer-slider-row{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:4px}
.fc-saq-timer-slider-lbl{font-size:var(--font-size-xs);font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em}
.fc-saq-timer-slider-val{font-size:var(--font-size-md);font-weight:700;color:var(--accent-pressed);font-variant-numeric:tabular-nums}
html.dark .fc-saq-timer-slider-val{color:var(--accent)}

.fc-saq-timer-slider{
  width:100%;-webkit-appearance:none;appearance:none;
  height:24px;background:transparent;cursor:pointer;margin:0;padding:0;
}
/* WS11: removed `.fc-saq-timer-slider:focus{outline:none}`; universal :focus-visible baseline now rings keyboard focus. */
.fc-saq-timer-slider::-webkit-slider-runnable-track{height:6px;border-radius:var(--radius-pill);background:var(--surface2)}
.fc-saq-timer-slider::-moz-range-track{height:6px;border-radius:var(--radius-pill);background:var(--surface2);border:none}
.fc-saq-timer-slider::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;
  width:16px;height:16px;border-radius:var(--radius-pill);
  background:var(--accent);border:2px solid var(--surface-bright);
  box-shadow:var(--shadow-sm);margin-top:-5px;cursor:pointer;
  transition:transform var(--duration-sm),box-shadow var(--duration-sm);
}
.fc-saq-timer-slider::-moz-range-thumb{
  width:14px;height:14px;border-radius:var(--radius-pill);
  background:var(--accent);border:2px solid var(--surface-bright);
  box-shadow:var(--shadow-sm);cursor:pointer;
}
.fc-saq-timer-slider:hover::-webkit-slider-thumb{transform:scale(1.1)}
.fc-saq-timer-slider:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 30%,transparent)}

.fc-saq-timer-computed{
  margin-top:8px;padding:8px 10px;
  background:var(--accent-soft);
  border:1px solid color-mix(in srgb,var(--accent) 25%,var(--border));
  border-radius:var(--btn-radius);
  font-size:var(--font-size-sm);color:var(--accent-pressed);
  font-variant-numeric:tabular-nums;
}
html.dark .fc-saq-timer-computed{color:var(--accent-pressed)}

.fc-saq-timer-presets{display:flex;gap:5px;margin-top:8px}
.fc-saq-timer-preset{
  flex:1;appearance:none;cursor:pointer;font-family:inherit;
  background:var(--surface);color:var(--text-muted);
  border:1px solid var(--border);border-radius:var(--btn-radius);
  padding:7px 4px;font-size:var(--font-size-xs);font-weight:500;
  display:flex;flex-direction:column;align-items:center;gap:1px;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm);line-height:1.2;
}
.fc-saq-timer-preset:hover{border-color:var(--accent);color:var(--text)}
.fc-saq-timer-preset[aria-pressed="true"]{background:var(--accent);color:var(--accent-on);border-color:var(--accent)}
.fc-saq-timer-preset:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.fc-saq-timer-preset-mins{font-size:var(--font-size-md);font-weight:700;font-variant-numeric:tabular-nums}
.fc-saq-timer-preset-name{font-size:var(--font-size-2xs);opacity:.85;text-transform:uppercase;letter-spacing:.04em}

.fc-saq-timer-toggle-row{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:8px 0;border-top:1px solid var(--border);
}
.fc-saq-timer-toggle-row:first-of-type{border-top:none}
.fc-saq-timer-toggle-text{flex:1;min-width:0}
.fc-saq-timer-toggle-title{font-size:var(--font-size-md);font-weight:600;color:var(--text);line-height:1.2}
.fc-saq-timer-toggle-sub{font-size:var(--font-size-xs);color:var(--text-faint);margin-top:1px;line-height:1.3}
.fc-saq-timer-toggle-switch{
  appearance:none;border:none;cursor:pointer;
  width:36px;height:20px;border-radius:var(--radius-pill);
  background:var(--surface2);position:relative;flex:0 0 auto;
  transition:background var(--duration-sm);
}
.fc-saq-timer-toggle-switch::after{
  content:"";position:absolute;top:2px;left:2px;
  width:16px;height:16px;border-radius:var(--radius-pill);
  background:var(--surface-bright);box-shadow:var(--shadow-sm);
  transition:transform .14s var(--ease-out-quart,cubic-bezier(.165,.84,.44,1));
}
.fc-saq-timer-toggle-switch[aria-checked="true"]{background:var(--accent)}
.fc-saq-timer-toggle-switch[aria-checked="true"]::after{transform:translateX(16px)}
.fc-saq-timer-toggle-switch:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media(prefers-reduced-motion:reduce){
  .fc-saq-timer-toggle-switch::after{transition:none}
}

.fc-saq-timer-drawer-actions{
  display:flex;gap:6px;margin-top:12px;padding-top:10px;border-top:1px solid var(--border);
}
.fc-saq-timer-drawer-btn{
  flex:1;appearance:none;cursor:pointer;font-family:inherit;
  font-size:var(--font-size-sm);font-weight:600;
  padding:8px 10px;border-radius:var(--btn-radius);
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm);
}
.fc-saq-timer-drawer-btn--ghost{background:transparent;color:var(--text-muted);border:1px solid var(--border)}
.fc-saq-timer-drawer-btn--ghost:hover{border-color:var(--border-strong);color:var(--text)}
.fc-saq-timer-drawer-btn--accent{background:var(--accent);color:var(--accent-on);border:1px solid var(--accent)}
.fc-saq-timer-drawer-btn--accent:hover{background:var(--accent-pressed);border-color:var(--accent-pressed)}
.fc-saq-timer-drawer-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* SAQ card needs position:relative so the absolute timer anchors. */
.fc-card[data-type="saq"]{position:relative}
.fc-callout{border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;background:var(--surface)}
.fc-callout summary{padding:10px 13px;cursor:pointer;list-style:none;font-size:var(--font-size-sm);font-weight:600;display:flex;align-items:center;gap:7px}
.fc-callout summary::-webkit-details-marker{display:none}
/* §9 Same SVG chevron pattern as the global details rule — Unicode ▸ retired. */
.fc-callout summary::before{
  content:"";display:inline-block;width:12px;height:12px;flex-shrink:0;
  background-color:var(--text-muted);
  -webkit-mask-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
          mask-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;
  transition:transform .15s;
}
.fc-callout[open] summary::before{transform:rotate(90deg)}
.fc-callout-examiner summary{color:var(--sage-deep)}
.fc-callout-examiner{border-color:color-mix(in srgb,var(--sage) 50%,var(--border))}
.fc-callout-ai summary{color:var(--peri-deep)}
.fc-callout-ai{border-color:color-mix(in srgb,var(--peri) 50%,var(--border))}
.fc-callout-body{padding:11px 13px;border-top:1px solid var(--border);font-size:var(--font-size-lg);line-height:1.55;color:var(--text)}
.fc-callout-body p{margin:6px 0}
.fc-callout-body ul{margin:6px 0;padding-left:18px}
.fc-callout-body{padding:10px 13px 13px;border-top:1px solid var(--border);font-size:var(--font-size-md);line-height:1.55;color:var(--text)}
.fc-notion-link{display:flex;align-items:center;gap:6px;font-size:var(--font-size-sm);color:var(--text-muted);text-decoration:none;padding:8px 0}
.fc-notion-link:hover{color:var(--accent)}
.fc-saq-action{display:grid;grid-template-columns:1fr 1fr 1fr;border-top:1px solid var(--border);flex-shrink:0}
.fc-saq-action button{padding:14px 8px;border:none;background:var(--surface);font-size:var(--font-size-sm);font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:4px;transition:background var(--duration-sm),color var(--duration-sm);color:var(--text-muted)}
.fc-saq-action button:not(:last-child){border-right:0.5px solid var(--border)}
.fc-saq-action .fc-critical:hover,.fc-saq-action .fc-critical:active{background:var(--red-bg);color:var(--red)}
.fc-saq-action .fc-partial:hover,.fc-saq-action .fc-partial:active{background:var(--amber-bg);color:var(--honey-deep)}
.fc-saq-action .fc-high:hover,.fc-saq-action .fc-high:active{background:var(--accent-soft);color:var(--accent)}
/* .fc-ack-btn (Submit) retired in the post-v9.1 audit pass — the four
   Critical/Low/Intermediate/High pills are now the direct grade. */
/* Directional swipe labels — preview style: bordered, corner-anchored, tilted. */
.fc-swipe-left,.fc-swipe-right{position:absolute;top:16px;padding:5px 11px;border-radius:9px;border:2px solid currentColor;font-size:var(--font-size-md);font-weight:800;letter-spacing:.04em;pointer-events:none;opacity:0;transition:opacity .1s;z-index:5}
.fc-swipe-left{left:14px;transform:rotate(-10deg);background:var(--red-bg);color:var(--red)}
.fc-swipe-right{right:14px;transform:rotate(10deg);background:var(--accent-soft);color:var(--accent)}

/* v101 + v115-phase7 — Focus overlay header/chrome on cinema bg `--focus-overlay-bg` (now #08083B midnight) */
/* F-P2-41/42: rgba literals replaced with --fc-chrome-* tokens.                       */
.focus-overlay .fc-header{border-bottom-color:var(--fc-chrome-border)}
.focus-overlay .fc-close{background:var(--fc-chrome-bg);color:var(--fc-chrome-fg)}
.focus-overlay .fc-close:hover{background:rgba(255,255,255,.16);color:white}
.focus-overlay .fc-card-counter{color:var(--fc-chrome-fg-muted)}
/* F-P2-45 / Phase 7: progress-bar track promoted to --fc-chrome-track at α 0.36
   (was literal .18 = 1.62:1, missed the ≥3:1 target). Now 3.19:1 on `#08083B`. */
.focus-overlay .fc-progress-bar{background:var(--fc-chrome-track)}
.focus-overlay .fc-xp-pill{background:rgba(200,134,30,.2);color:rgba(230,185,85,1)}
.focus-overlay .fc-exam-countdown{color:var(--fc-chrome-fg-muted)}
.focus-overlay .fc-exam-countdown strong{color:var(--fc-chrome-fg)}
.focus-overlay .fc-undo-btn{border-color:var(--fc-chrome-border);background:var(--fc-chrome-bg);color:var(--fc-chrome-fg-muted)}
.focus-overlay .fc-undo-btn:hover{border-color:var(--accent);color:var(--accent)}
.focus-overlay .fc-undo-count{background:var(--accent);color:var(--focus-overlay-bg)}
.focus-overlay .fc-week-band .fc-pip-label{color:var(--fc-chrome-fg-muted)}
.focus-overlay .fc-nemesis-tag{background:rgba(200,90,80,.2)}
.focus-overlay .fc-queue-dot{background:color-mix(in srgb,currentColor 10%,#1a1a1c)}
/* v102 — C1: fc-done text unreadable on cinema bg — override token colours */
.focus-overlay .fc-done{color:var(--fc-chrome-fg)}
.focus-overlay .fc-done-title{color:var(--fc-chrome-fg)}
.focus-overlay .fc-done-title-sm{color:var(--fc-chrome-fg)}
.focus-overlay .fc-done-xp-label{color:var(--fc-chrome-fg-muted)}
.focus-overlay .fc-done-stats{color:var(--fc-chrome-fg-muted)}
.focus-overlay .fc-done-pill--missed{background:rgba(240,90,80,.25);color:#ff8a82}
.focus-overlay .fc-done-pill--honed{background:rgba(21,117,112,.25);color:#4ecdc4}
.focus-overlay .fc-done-pill--mastered{background:rgba(139,92,246,.25);color:#c4b5fd}
.focus-overlay .fc-done-miss-nudge{background:rgba(240,90,80,.15)}
.focus-overlay .fc-done-miss-nudge-sub{color:var(--fc-chrome-fg-muted)}
.focus-overlay .fc-ribbon-toggle{color:var(--fc-chrome-fg-muted)}

/* v101 — Ghost card stack (depth illusion behind active card) ======================== */
/* Phase 1 swipe-engine — card stack with concurrent promotion ghost cards.
   Ghost fidelity: lightweight placeholder chrome (no rendered body content).
   JS drives transform/filter/opacity inline during drag + promotion transitions.

   .fc-card-stack    — flex item in #fcStage; contains ghosts + live card.
   .fc-ghost-1       — depth-1 ghost (closest, z-index 1). Default static state.
   .fc-ghost-2       — depth-2 ghost (farthest, z-index 0). Default static state.
   swipe-engine.js overrides transform/filter/opacity inline for animation.

   Ghost static defaults (overridden inline by JS when engine is active):
     depth-1: translateY(18px) scale(0.945) brightness(0.94) opacity(0.5)
     depth-2: translateY(36px) scale(0.89)  brightness(0.86) opacity(0.3)
   These match the applyGhostDepth() formula for progress=0. */
.fc-card-stack{
  position:relative;width:calc(100% - 48px);max-width:640px;
  flex:1;min-height:0;display:grid;align-self:center;
}
/* Grid-overlay stacking: the active card + ghost cards all share ONE grid cell,
   so the stack is always sized by the cards and NEVER collapses when the
   outgoing card is removed on promotion. (The old position:absolute+inset:0
   model collapsed the content-sized stack the instant the only in-flow child
   left → the promoted absolute card rendered from the collapsed centre
   downward = the "card pinned to the lower half, no ghosts" bug.) Depth is
   pure transform (translate/scale) which does not affect grid sizing. */
.fc-card-stack > .fc-card,
.fc-card-stack > .fc-ghost{ grid-area:1 / 1; }
.fc-ghost{
  /* Placeholder ghost — shares the stack's single grid cell (grid-area:1/1),
     so it stretches to the live card's geometry without position:absolute
     (which collapsed the content-sized stack on promotion). content hidden. */
  border:1px solid var(--border);
  border-radius:var(--radius-lg,18px);
  pointer-events:none;
  will-change:transform;
}
/* Static resting positions — JS overrides these inline during drag/promotion */
.fc-ghost-1{
  background:var(--surface);
  z-index:1;
  transform:translateY(18px) scale(0.945);
  transform-origin:bottom center;
  opacity:.5;
  filter:brightness(0.94);
}
.fc-ghost-2{
  background:color-mix(in srgb,var(--surface) 60%,var(--border));
  z-index:0;
  transform:translateY(36px) scale(0.89);
  transform-origin:bottom center;
  opacity:.3;
  filter:brightness(0.86);
}
/* Reduced-motion: ghosts stay static (no transition/rise) */
@media(prefers-reduced-motion:reduce){
  .fc-ghost-1,.fc-ghost-2{ transition:none!important; }
}
.fc-card-stack>.fc-card{position:relative;z-index:2;width:100%;max-width:100%;align-self:stretch}

/* Phase 2 — pre-rendered ghost-1 slot card.
   A real fully-content-rendered card sits in the ghost-1 position (absolute,
   depth-1 transform applied by JS). animation:none suppresses the fcCardIn
   entry keyframe that fires unconditionally on .fc-card — promoted cards
   never replay an entry animation; they glide from ghost-1 to active via a
   transform transition (JS-driven). Only a genuine top-of-session boot card
   should play fcCardIn. */
.fc-card--prerender{
  animation:none!important;
  /* Pointer-events off while in ghost slot — shouldn't receive swipe/tap
     until promoted to active. */
  pointer-events:none;
}
/* B11: .fc-card--promoted{animation:none!important} removed — fc-card--promoted
   is never added in JS (confirmed by grep of app.js + swipe-engine.js); dead code. */

/* Swipe colour wash — FULL-CARD flat fill (matches the Motion Lab preview), not
   the old edge-glow radial. Per-direction grade colour (Missed coral / Honed
   green / Mastered violet); the engine scales element opacity 0→.85 with drag,
   so these base alphas land ~.30 effective at commit — coloured but legible. */
.fc-swipe-wash{position:absolute;inset:0;border-radius:inherit;pointer-events:none;opacity:0;z-index:20;transition:opacity .04s}
.fc-swipe-wash--left {background:rgba(200,60,60,.36)}
.fc-swipe-wash--right{background:rgba(40,160,80,.34)}
.fc-swipe-wash--up   {background:rgba(100,80,200,.38)}
/* Miss-tag washes (honey = grade 2): Mixed + Hazy both read amber to match the
   miss-tag buttons; Blank reuses --left (coral). */
.fc-swipe-wash--mixed{background:rgba(245,158,11,.34)}
.fc-swipe-wash--hazy {background:rgba(245,158,11,.34)}

/* v101 — Upward swipe-out animation (Mastered via compass drag) ===================== */
@keyframes fcSwipeOutUp{from{opacity:1;transform:none}to{opacity:0;transform:translateY(-110%) scale(.9)}}
.fc-card.swipe-out-up{animation:fcSwipeOutUp var(--duration-xl) var(--ease-out) forwards}
@media(prefers-reduced-motion:reduce){.fc-card.swipe-out-up{animation:fadeIn var(--duration-sm) ease both}}

/* v101 — Swipe-up hint label (Mastered, visible when compass is armed) ============== */
.fc-swipe-up{
  position:absolute;top:16px;left:50%;transform:translateX(-50%);
  padding:5px 12px;border-radius:9px;border:2px solid currentColor;
  font-size:var(--font-size-md);font-weight:800;letter-spacing:.04em;
  pointer-events:none;opacity:0;transition:opacity var(--duration-sm);z-index:5;
  background:var(--peri-fill);color:var(--peri-deep);white-space:nowrap;
}
/* Miss-tag swipe hints (tag-open): Hazy (up) + Mixed (right) read AMBER to match
   the miss-tag buttons, instead of the grade colours (purple / green). Blank
   (left) keeps its coral — that's already correct. */
.fc-swipe-up.fc-swipe-hint--tag,
.fc-swipe-right.fc-swipe-hint--tag{
  background:color-mix(in srgb, var(--grade-hazy) 18%, var(--surface-elevated));
  color:var(--grade-hazy-label);
}

/* Compass dial removed 2026-05-26 (cinema-mode pass). Grade input is now the
   Pointer-Events card pickup (← Missed · → Honed) + scroll-protected up-swipe
   (↑ Mastered), with the on-card buttons always available as tap targets. */
.focus-overlay.active #streakBar{display:none!important}
.focus-overlay .fc-week-band{display:none}
/* The Show Answer + grade buttons now render on touch as well (no compass to
   replace them). touch-action:none on the card + body means the browser never
   scrolls or cancels the gesture (iOS was stealing it via the nested overflow
   scrollers); wireFcSwipe owns everything and scrolls the answer manually. */
.fc-body{touch-action:none}
body[data-input="touch"] .fc-body{padding-bottom:calc(env(safe-area-inset-bottom,0px) + 16px)}
body[data-input="touch"] .fc-card:not(.revealed) .fc-body{cursor:pointer}
/* Swipe-only mode (Settings → "Show grade buttons in focus mode" off). Hides the
   Show Answer + the inverted-T grade buttons (.post-reveal, the real grade row
   from _buildGradeRow). Scoped to .focus-overlay so Today cards keep their
   buttons. Swipes still grade — they route through the same buttons via .click(),
   which fires even on display:none. The miss-tag overlay stays visible — it only
   appears after a deliberate Missed swipe and is the cue for ← Blank ↑ Hazy → Mixed. */
body.fc-buttons-hidden .focus-overlay .fc-show-btn{display:none!important}
body.fc-buttons-hidden .focus-overlay .fc-card .post-reveal{display:none!important}

.fc-combo{position:fixed;top:calc(env(safe-area-inset-top,44px) + 20px);left:50%;transform:translateX(-50%);background:var(--honey-fill);color:var(--honey-deep);font-weight:700;font-size:var(--font-size-md);padding:6px 16px;border-radius:99px;box-shadow:0 2px 8px rgba(0,0,0,0.15);pointer-events:none;animation:comboPop .35s var(--ease-spring);z-index:210}
html.dark .fc-combo{background:var(--honey-soft);color:var(--honey)}
@keyframes comboPop{from{opacity:0;transform:translateX(-50%) scale(0.7)}to{opacity:1;transform:translateX(-50%) scale(1)}}
/* B8-fix: suppress combo pop animation under reduced motion. */
@media(prefers-reduced-motion:reduce){.fc-combo{animation:none}}
/* M2 — Mastered burst. --tx/--ty set as inline CSS vars per particle by fireMasteredBurst(). */
@keyframes fcMasteredBurst{0%{opacity:1;transform:translate(0,0) scale(1)}100%{opacity:0;transform:translate(var(--tx),var(--ty)) scale(.15)}}
/* F8 — 3D flip machinery removed (F0 migrated SAQ to .revealed pattern). */

/* Today-fix v2 — focus mode SAQ callouts: same continuous-outline pattern
   as the SAQ tab card. Active button + content body share a coloured
   border to read as a paired unit. */
/* v177 — Force pointer-events:auto on the callout row so any parent
   that accidentally inherits pointer-events:none doesn't kill button
   taps (Issue N8). */
/* AUDIT-2026-05-06 #3 (Sprint 2) — sticky tab strip. The .fc-card scrolls
   internally (overflow-y:auto on the card) so when long Model-Answer prose
   pushes content beyond the card height, the user scrolls the card body
   and the CICM/Model/Notes tab strip used to scroll out of view too. Now
   the strip sticks to the top of the visible card area with a solid
   surface backdrop so model-answer content reads cleanly under it. */
/* Focus-mode callout: same unified panel as library — row (top) + bodies (bottom).
   Sticky row remains for long content; the shared outer border creates one frame. */
.fc-callout-wrap{
  border:1.5px solid var(--border);
  border-radius:var(--radius-sm);
  overflow:clip;
  margin-bottom:8px;
}
.fc-callout-row{
  display:flex;
  border-bottom:1.5px solid var(--border);
  pointer-events:auto;position:sticky;top:0;z-index:4;
  background:var(--fc-card-surface);
}
/* AUDIT-2026-05-06 #5 (Sprint 2) — ribbon summary mount, visible by default
   between haul + actions. Individual ribbons stay collapsed behind the
   "Show full breakdown" toggle below the action row. */
.fc-ribbon-summary-mount{margin:0 0 12px}
.fc-ribbon-summary-mount:empty{display:none}
.fc-callout-btn{
  flex:1;padding:9px 8px 10px;
  border:none;border-right:1.5px solid var(--border);
  background:color-mix(in srgb,var(--surface-alt) 40%,var(--fc-card-surface));
  color:var(--text-muted);font-size:var(--font-size-md);font-weight:600;font-family:inherit;
  cursor:pointer;
  transition:background var(--duration-sm),color var(--duration-sm);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.fc-callout-btn:last-child{border-right:none}
.fc-callout-btn:hover{
  background:color-mix(in srgb,var(--surface-alt) 70%,var(--fc-card-surface));color:var(--text);
}
.fc-callout-btn:focus-visible{
  outline:none;box-shadow:inset 0 0 0 2px var(--accent);
}
.fc-callout-btn--sage.active {
  background:color-mix(in srgb,var(--sage)  12%,var(--fc-card-surface));color:var(--sage-deep);
}
.fc-callout-btn--peri.active {
  background:color-mix(in srgb,var(--peri)  12%,var(--fc-card-surface));color:var(--peri-deep);
}
.fc-callout-btn--honey.active{
  background:color-mix(in srgb,var(--honey) 12%,var(--fc-card-surface));color:var(--honey-deep);
}

.fc-callout-bodies{}
.fc-callout-body-inline{
  font-size:var(--font-size-md);line-height:1.55;color:var(--text);
  background:var(--fc-card-surface);
  padding:12px 14px;
  animation:fadeIn .18s ease both;
}
.fc-callout-body-inline[hidden]{display:none}
.fc-callout-body-inline--sage  {background:color-mix(in srgb,var(--sage)  12%,var(--fc-card-surface))}
.fc-callout-body-inline--peri  {background:color-mix(in srgb,var(--peri)  12%,var(--fc-card-surface))}
.fc-callout-body-inline--honey {background:color-mix(in srgb,var(--honey) 12%,var(--fc-card-surface))}
.fc-callout-body-inline p:first-child{margin-top:0}
.fc-callout-body-inline p{margin:6px 0}
.fc-callout-body-inline ul{margin:6px 0;padding-left:18px}

/* §5 v9.1 done screen — emoji, DM-Serif title, DM-Serif XP hero, stats.
   v58 — explicit max-width + auto margin so it stays centred without
   relying on flex:1 stretching it to the full stage width (which
   was creating a 'card-shaped' visual that misled the eye into
   thinking only the header row was inside). overflow-y:auto safety
   net so a long badge haul doesn't clip. */
.fc-done{
  display:flex;flex-direction:column;align-items:center;
  justify-content:center;padding:32px 16px 16px;gap:12px;text-align:center;
  opacity:1;
  width:100%;max-width:520px;margin:0 auto;
  align-self:center;
}
.fc-done-icon{font-size:52px;line-height:1;margin-bottom:2px}
.fc-done-title{
  font-family:var(--font-display);font-weight:400;font-size:var(--font-size-3xl);
  letter-spacing:-0.005em;color:var(--text);
  margin:0;border:none;padding:0;
}
.fc-done-xp{
  font-family:var(--font-display);font-weight:400;font-size:48px;
  color:var(--accent);line-height:1;
  font-variant-numeric:tabular-nums;letter-spacing:-0.01em;
  display:inline-flex;align-items:baseline;gap:6px;
}
.fc-done-xp-label{
  font-family:var(--font-sans);font-weight:500;font-size:var(--font-size-xl);
  color:var(--text-muted);letter-spacing:normal;
}
.fc-done-stats{
  display:flex;gap:20px;justify-content:center;flex-wrap:wrap;
  font-size:var(--font-size-md);color:var(--text-muted);font-weight:500;
  margin-top:4px;
}
.fc-done-stat .val{font-size:24px;font-weight:700;color:var(--text)}
.fc-done-stat .lbl{font-size:var(--font-size-xs);color:var(--text-muted);text-transform:uppercase;letter-spacing:0.06em}
.fc-done-btn{
  padding:14px 32px;background:var(--accent);color:var(--accent-on);
  border:none;border-radius:var(--radius);font-size:15px;font-weight:700;
  font-family:var(--font-sans);cursor:pointer;
  box-shadow:0 3px 0 var(--accent-pressed);margin-top:14px;transition:background .1s,color .1s,border-color .1s,box-shadow .1s,transform .1s,opacity .1s;
}
.fc-done-btn:hover{transform:translateY(-1px);box-shadow:0 4px 0 var(--accent-pressed)}
.fc-done-btn:active{transform:translateY(2px);box-shadow:0 1px 0 var(--accent-pressed)}

/* §5 Phase 1 done-screen revamp — misses block + mini-tagbar + dual CTA stack.
   Surfaces what was missed inline (tap a row → answer expands), shows the
   miss-tag distribution, and offers a context-aware primary action ("Drill
   misses (N)") above the demoted Save & exit. Mirrors the existing fc-haul
   surface treatment so the two blocks read as a cohesive end-of-run column. */
.fc-misses{
  width:100%;
  margin:14px 0 4px;
  padding:14px 14px 12px;
  background:var(--surface-alt);
  border:1px solid var(--border);
  border-radius:var(--radius-lg);
  text-align:left;
}
.fc-misses-head{
  display:flex;align-items:center;justify-content:space-between;
  gap:10px;flex-wrap:wrap;
  margin-bottom:10px;
}
.fc-misses-title{
  font-size:var(--font-size-xs);font-weight:700;color:var(--text-muted);
  text-transform:uppercase;letter-spacing:0.06em;
}
.fc-miss-tagbar{
  display:inline-flex;gap:6px;flex-wrap:wrap;
}
.fc-miss-tagbar-seg{
  display:inline-flex;align-items:center;
  padding:3px 9px;
  border-radius:var(--radius-pill);
  font-size:var(--font-size-xs);font-weight:600;letter-spacing:0.02em;
  background:color-mix(in srgb,var(--coral-vivid) 18%,transparent);
  color:var(--coral-vivid);
  border:1px solid color-mix(in srgb,var(--coral-vivid) 35%,transparent);
  white-space:nowrap;
}
/* Subtle differentiation: hazy nudges amber, mixed nudges neutral so the bar
   reads as a distribution at a glance, not a uniform coral wash. */
.fc-miss-tagbar-seg--hazy{
  background:color-mix(in srgb,var(--fc-badge-hazy) 18%,transparent);
  color:var(--fc-badge-hazy);
  border-color:color-mix(in srgb,var(--fc-badge-hazy) 40%,transparent);
}
.fc-miss-tagbar-seg--mixed{
  background:color-mix(in srgb,var(--text-muted) 14%,transparent);
  color:var(--text);
  border-color:color-mix(in srgb,var(--text-muted) 30%,transparent);
}
.fc-misses-list{
  display:flex;flex-direction:column;gap:6px;
}
.fc-miss-row{
  display:block;width:100%;
  padding:10px 12px;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--radius-md);
  font-family:var(--font-sans);
  text-align:left;cursor:pointer;
  color:var(--text);
  transition:background var(--duration-sm),border-color var(--duration-sm);
}
.fc-miss-row:hover{
  background:color-mix(in srgb,var(--surface) 80%,var(--accent) 20%);
  border-color:color-mix(in srgb,var(--border) 60%,var(--accent) 40%);
}
.fc-miss-row-head{
  display:flex;align-items:flex-start;justify-content:space-between;
  gap:10px;
}
.fc-miss-row-prompt{
  font-size:var(--font-size-lg);line-height:1.45;font-weight:500;
  color:var(--text);
  flex:1;min-width:0;
}
.fc-miss-row-tag{
  flex-shrink:0;
  padding:2px 8px;border-radius:var(--radius-pill);
  font-size:var(--font-size-xs);font-weight:700;letter-spacing:0.04em;
  text-transform:uppercase;
  background:color-mix(in srgb,var(--coral-vivid) 18%,transparent);
  color:var(--coral-vivid);
  border:1px solid color-mix(in srgb,var(--coral-vivid) 35%,transparent);
  align-self:center;
}
.fc-miss-row-tag--hazy{
  background:color-mix(in srgb,var(--fc-badge-hazy) 18%,transparent);
  color:var(--fc-badge-hazy);
  border-color:color-mix(in srgb,var(--fc-badge-hazy) 40%,transparent);
}
.fc-miss-row-tag--mixed{
  background:color-mix(in srgb,var(--text-muted) 14%,transparent);
  color:var(--text);
  border-color:color-mix(in srgb,var(--text-muted) 30%,transparent);
}
.fc-miss-row-tag--untagged{
  background:color-mix(in srgb,var(--text-muted) 12%,transparent);
  color:var(--text-muted);
  border-color:color-mix(in srgb,var(--text-muted) 25%,transparent);
}
/* Answer body collapsed by default; aria-expanded="true" reveals it.
   .card-body class is added in JS so renderRichTextIn upgrades raw markdown
   to proper <p>/<ul>/<strong> markup once marked.js lazy-loads. The shared
   .card-body p / ul / li rules upstream provide paragraph spacing — don't
   set white-space:pre-line here or it overrides <p> margins. */
.fc-miss-row-ans{
  display:none;
  margin-top:8px;padding-top:8px;
  border-top:1px dashed var(--border);
  font-size:var(--font-size-md);line-height:1.55;color:var(--text-muted);
}
.fc-miss-row[aria-expanded="true"] .fc-miss-row-ans{display:block}
.fc-miss-row-ans strong{color:var(--text);font-weight:600}
.fc-miss-row-ans em{color:var(--text)}

/* Action stack: primary CTA on top (drill misses), Save & exit demoted to a
   secondary ghost button so the recommended next step is visually first.
   When there's no primary (e.g. clean run), saveBtnClass falls back to the
   solid .fc-done-btn so Save & exit retains its prior emphasis. */
.fc-done-actions{
  display:flex;flex-direction:column;align-items:stretch;gap:8px;
  width:100%;max-width:280px;margin-top:14px;
}
.fc-done-btn--primary{margin-top:0}
.fc-done-btn--secondary{
  margin-top:0;
  background:transparent;color:var(--text-muted);
  box-shadow:none;
  border:1px solid var(--border);
  font-weight:600;
}
/* W5.2 — Recovery debrief panel. Appended to fc-done when session is a Recovery Stack. */
.fc-recovery-debrief{
  width:100%;max-width:320px;margin-top:18px;
  border:1px solid color-mix(in srgb,var(--coral) 30%,var(--border));
  border-radius:var(--radius);overflow:hidden;
  background:color-mix(in srgb,var(--coral) 8%,var(--surface-alt));
}
.fc-rdb-header{
  display:flex;align-items:center;gap:7px;
  padding:10px 14px 8px;
  font-size:var(--font-size-xs);font-weight:700;letter-spacing:0.5px;text-transform:uppercase;
  color:var(--coral-deep);border-bottom:1px solid color-mix(in srgb,var(--coral) 20%,var(--border));
}
.fc-rdb-section{padding:10px 14px;border-bottom:1px solid color-mix(in srgb,var(--coral) 15%,var(--border))}
.fc-rdb-section:last-child{border-bottom:0}
.fc-rdb-label{font-size:var(--font-size-xs);font-weight:700;color:var(--text-muted);letter-spacing:0.04em;margin-bottom:6px;text-transform:uppercase}
.fc-rdb-grade-row{display:flex;align-items:center;gap:8px;margin-bottom:3px;font-size:var(--font-size-sm)}
.fc-rdb-grade-bar{flex:1;height:5px;border-radius:3px;background:var(--border)}
.fc-rdb-grade-fill{height:5px;border-radius:3px;min-width:2px}
.fc-rdb-grade-fill--4{background:var(--sage)}
.fc-rdb-grade-fill--3{background:color-mix(in srgb,var(--sage) 60%,var(--honey))}
.fc-rdb-grade-fill--2{background:var(--honey)}
.fc-rdb-grade-fill--1{background:var(--coral)}
.fc-rdb-grade-lbl{width:70px;color:var(--text-muted)}
.fc-rdb-grade-cnt{width:28px;text-align:right;color:var(--text-muted);font-size:var(--font-size-xs)}
.fc-rdb-line{font-size:var(--font-size-md);color:var(--text-muted);line-height:1.5;margin-bottom:3px}
.fc-rdb-line strong{color:var(--text)}
.fc-rdb-actions{display:flex;gap:8px;padding:10px 14px 12px}
.fc-rdb-btn{
  flex:1;padding:7px 0;border-radius:var(--radius-sm);font-size:var(--font-size-sm);font-weight:600;
  border:1px solid var(--border);background:var(--surface-alt2);color:var(--text);cursor:pointer;
}
.fc-rdb-btn--primary{background:color-mix(in srgb,var(--coral) 15%,var(--surface-alt2));border-color:color-mix(in srgb,var(--coral) 40%,var(--border));color:var(--coral-deep)}
.fc-done-btn--secondary:hover{
  background:var(--surface-alt);color:var(--text);
  box-shadow:none;transform:none;
  border-color:color-mix(in srgb,var(--border) 60%,var(--text-muted) 40%);
}
.fc-done-btn--secondary:active{
  transform:none;box-shadow:none;
}
/* Option C+A — layered haul: compact header row + grade pills + miss nudge + collapsible ribbon */
.fc-done-header-row{display:flex;align-items:center;gap:8px;justify-content:center}
.fc-done-icon-sm{font-size:28px;line-height:1}
.fc-done-title-sm{font-family:var(--font-display);font-weight:400;font-size:var(--font-size-xl);color:var(--text)}
.fc-done-pills{display:flex;gap:7px;justify-content:center;flex-wrap:wrap;margin:2px 0 2px}
.fc-done-pill{border-radius:20px;padding:4px 10px;font-size:var(--font-size-xs);font-weight:500}
.fc-done-pill--missed{background:rgba(240,90,80,.15);color:var(--coral-vivid)}
.fc-done-pill--honed{background:rgba(21,117,112,.15);color:var(--mint)}
.fc-done-pill--mastered{background:rgba(139,92,246,.15);color:var(--violet)}
.fc-done-miss-nudge{width:100%;max-width:280px;background:rgba(240,90,80,.1);border-radius:var(--radius-md);padding:9px 12px;text-align:left}
.fc-done-miss-nudge-title{font-size:var(--font-size-xs);font-weight:500;color:var(--coral-vivid);margin-bottom:2px}
.fc-done-miss-nudge-sub{font-size:var(--font-size-xs);color:var(--text-muted);line-height:1.4}
.fc-ribbon-collapse{width:100%;display:flex;flex-direction:column;align-items:center;margin-top:4px}
.fc-ribbon-toggle{background:none;border:none;color:var(--violet);font-size:var(--font-size-xs);cursor:pointer;padding:6px 0;font-family:var(--font-sans)}
.fc-ribbon-toggle:hover{text-decoration:underline}

/* F8-B-06 — Haul analysis panel: health bar + meta + type chips */
.fc-done-analysis{width:100%;display:flex;flex-direction:column;gap:6px;margin:4px 0 2px}
.fc-done-analysis-row{display:flex;align-items:center;gap:8px}
.fc-health-bar{flex:1;height:6px;border-radius:3px;background:var(--border);overflow:hidden;display:flex}
.fc-health-seg{height:100%;transition:width .4s var(--ease-spring)}
.fc-health-seg--missed  {background:var(--coral-vivid)}
.fc-health-seg--honed   {background:var(--mint)}
.fc-health-seg--mastered{background:var(--violet)}
.fc-health-label{font-size:var(--font-size-xs);font-weight:600;white-space:nowrap;flex-shrink:0}
.fc-health--good{color:var(--mint)}
.fc-health--ok  {color:var(--honey)}
.fc-health--low {color:var(--coral-vivid)}
.fc-done-meta{font-size:var(--font-size-xs);color:var(--text-muted);text-align:center;line-height:1.4}
.fc-done-type-chips{display:flex;gap:6px;justify-content:center;flex-wrap:wrap}
.fc-done-type-chip{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:20px;font-size:var(--font-size-xs);font-weight:500;border:1px solid transparent}
.fc-done-type-glyph{font-size:11px;line-height:1}
.fc-done-type-chip--recall {background:rgba(56,189,248,.12);border-color:rgba(56,189,248,.35);color:var(--sky)}
.fc-done-type-chip--saq    {background:rgba(251,113,133,.12);border-color:rgba(251,113,133,.35);color:var(--rose)}
.fc-done-type-chip--pharma {background:rgba(167,139,250,.12);border-color:rgba(167,139,250,.35);color:var(--violet)}
.fc-done-type-chip--axiom  {background:rgba(163,230,53,.12);border-color:rgba(163,230,53,.35);color:var(--saltbush)}
.focus-overlay .fc-health--good{color:#4ecdc4}
.focus-overlay .fc-health--ok  {color:#fbbf24}
.focus-overlay .fc-health--low {color:#ff8a82}
.focus-overlay .fc-done-meta{color:var(--fc-chrome-fg-muted)}
.focus-overlay .fc-done-type-chip--recall {background:rgba(56,189,248,.18);border-color:rgba(56,189,248,.45);color:#7dd3fc}
.focus-overlay .fc-done-type-chip--saq    {background:rgba(251,113,133,.18);border-color:rgba(251,113,133,.45);color:#fda4af}
.focus-overlay .fc-done-type-chip--pharma {background:rgba(167,139,250,.18);border-color:rgba(167,139,250,.45);color:#c4b5fd}
.focus-overlay .fc-done-type-chip--axiom  {background:rgba(163,230,53,.18);border-color:rgba(163,230,53,.45);color:#bef264}

/* SAQ / Fact confidence rating section — now uses shared .fc-grade-btn system. */
/* F8-A-05 — SAQ focus-card rate section. Uses shared .fc-grade-btn system. */
/* F8 — .fc-saq-cf removed (class no longer emitted by F0/F1 buildSaqCard/buildFactCard). */
/* F1 — Fact card: hide Show Detail button after revealed. */
.fc-card[data-type="fact"].revealed .fc-show-btn{display:none}


/* =====================================================================
   card-v2.css — Cinema card v2 surface (strangler-fig Phase 2 scaffold)
   Flag-gated: only loaded when card_v2 flag is active.
   Token refs: tokens.css. Dark mode: html.dark (NOT [data-theme]).
   Safari 15 guards: color-mix() wrapped in @supports with solid fallback.
   ===================================================================== */

/* ─── TYPE-COLOR PER CARD TYPE ──────────────────────────────────────── */
/* Set --type-color so all color-mix() expressions resolve correctly.
   Real app tokens: --recall #2D6B95, --saq/#rose-deep #9D1E5E,
   --pharma/#violet-deep #6A1A80, --axiom/#saltbush-deep #5E6670.
   These are the LIGHT values; dark overrides come via html.dark below. */
.fc-card.type-recall  { --type-color:var(--recall); }
.fc-card.type-saq     { --type-color:var(--rose-deep); }
.fc-card.type-pharma  { --type-color:var(--violet-deep); }
.fc-card.type-axiom   { --type-color:var(--saltbush-deep); }
/* Nemesis: flame-ember identity drives the band/glyph/dots (ember reads on both
   light + dark per tokens.css:499). buildShell sets .type-nemesis for nemesis. */
.fc-card.type-nemesis { --type-color:var(--nemesis-ember); }

/* Dark mode: use the brighter card-type identity tokens (≥4.5:1 on dark surfaces) */
html.dark .fc-card.type-recall  { --type-color:var(--type-recall); }
html.dark .fc-card.type-saq     { --type-color:var(--type-saq); }
html.dark .fc-card.type-pharma  { --type-color:var(--type-pharma); }
html.dark .fc-card.type-axiom   { --type-color:var(--type-axiom); }
html.dark .fc-card.type-nemesis { --type-color:var(--nemesis-ember); }

/* The v2 nemesis identity is the ember BAND (above) — neutralise the v1
   .fc-card--nemesis ember left-stripe + inset shadow (focus-mode.css:497) which
   leaks onto v2 cards, restoring the standard v2 border + elevation shadow. */
.fc-card--v2.fc-card--nemesis {
  border-left-color: var(--border) !important;
  box-shadow: var(--shadow-lg) !important;
}

/* ─── CARD SHELL ─────────────────────────────────────────────────────── */
/* §2 verbatim contract values — do not drift. MUST be scoped to .fc-card--v2:
   a bare .fc-card here would override focus-mode.css for V1 cards too (this
   sheet loads after focus-mode.css) and silently restyle v1 when the flag is off. */
.fc-card--v2 {
  display:flex;flex-direction:column;overflow:hidden;position:relative;
  background:var(--surface-elevated);border-radius:var(--radius);
  border:1px solid var(--border);box-shadow:var(--shadow-lg);
  min-height:clamp(240px,40vh,320px);contain:layout;
  /* Fit the stack — drop v1's min-width:380px floor (focus-mode.css:374) which
     overflows ≤395px viewports. width:100% fills the stack edge-to-edge. */
  width:100%;min-width:0;max-width:100%;
  /* Allow native VERTICAL scroll (the answer zone) — v1's touch-action:none made
     the engine drive scrollTop manually, which fought the gesture. pan-y hands
     vertical to the browser (momentum, card stays still) and leaves horizontal to
     the swipe engine (Missed/Honed). 0,2,0 beats focus-mode.css .fc-card. */
}
.fc-card.fc-card--v2 { touch-action:pan-y; }
.fc-card--v2 .fc-answer-zone { touch-action:pan-y; }       /* native scroll */
.fc-card--v2 .fc-grade-zone  { touch-action:none; }        /* swipe-to-grade — engine owns it (up=Mastered, miss-tag swipes), no native pan */

/* Zero the v1 absolute-header padding reservation. app-shell-tail.css:4789 sets
   .fc-card{padding-top:calc(32px+12px)!important; padding:_ 18 18 22} to clear v1's
   ABSOLUTELY-positioned .card__header. The v2 band is IN-FLOW (its own child), so
   that 44px top pad just gaps the band and the L/R pad insets the full-bleed band.
   Needs .fc-card.fc-card--v2 (0,2,0) + !important to beat the v1 !important rule. */
.fc-card.fc-card--v2 { padding:0 !important; }

/* Very short viewports (small phones, iOS landscape, on-screen keyboard): the
   min-height floor (clamp 240–320) can exceed the stage and force overflow. The
   revealed max-height already caps at the stage via min(...,100%) below, so only
   the floor needs relaxing here. Mirrors focus-mode.css:418's v1 guard, which
   source-order can't reach v2. */
@media (max-height:600px) {
  .fc-card--v2 { min-height:0; }
}

/* Post-reveal: grows up to the cinema cap, three-zone scroll (.fc-answer-zone)
   absorbs anything beyond it. The cap is min()'d with a viewport-relative
   ceiling so the card NEVER outgrows the device — leaving room for the focus
   chrome that sits ABOVE the stage (header ~44 + queue carousel ~56 + SAQ
   pomodoro timer ~34) plus a top+bottom gutter (~80). The 215px budget covers
   the worst case (SAQ with the carousel open); when the carousel is closed the
   surplus just reads as a larger gutter. NB a percentage ceiling (100%) does
   NOT work here: the .fc-card-stack containing block is content-stretched =
   indefinite height, so a % max-height resolves to none and the cap is dropped.
   dvh tracks the dynamic viewport (iOS toolbars); vh line is the Safari‑15
   fallback. On a tall viewport the clamp wins (compact cinema card); on a short
   one the ceiling wins so nothing overlaps the timer/header or clips the grades. */
.fc-card--v2.revealed {
  /* --fc-stage-avail is the stage's REAL available height below the focus chrome
     (header + queue carousel + SAQ timer), written by _syncFcStageAvail() (rAF +
     ResizeObserver) — exact across devices (Dynamic Island / safe-area / timer).
     Cap to it so the card fills the stage (small gutter = the stage padding) and
     never overflows behind the timer; .fc-answer-zone becomes the real scroller
     (a vertical drag scrolls instead of firing Mastered). app.js also sets this
     INLINE per card (beats any device CSS quirk); the dvh value is the pre-JS
     fallback. No cinema clamp — clamping below the stage left a big top gap. */
  max-height:calc(100dvh - 240px);
  max-height:var(--fc-stage-avail, calc(100dvh - 240px));
}

/* Height morph — scoped to .morphing ONLY; never a global max-height transition
   (per-frame layout on iOS during gestures). */
@media (prefers-reduced-motion:no-preference) {
  .fc-card.morphing {
    transition:max-height 240ms var(--ease-out);
  }
}

/* Reduced-motion: neutralise morph + any unlock-cue transitions */
@media (prefers-reduced-motion:reduce) {
  .fc-card.morphing { transition:none !important; }
  .fc-reveal-btn { transition:none !important; }
  .fc-miss-back-btn { transition:none !important; }
}

/* ─── BAND ──────────────────────────────────────────────────────────── */
/* Safari 15 guard: solid type-colour fallback OUTSIDE @supports.
   Inside @supports, override with the color-mix tint. */
.fc-band {
  display:flex;align-items:center;gap:7px;padding:10px 14px 9px;
  background:var(--type-color, #2D6B95);  /* Safari 15 fallback: solid type colour */
  border-bottom:1px solid var(--type-color, #2D6B95);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-band {
    background:color-mix(in srgb, var(--type-color, #2D6B95) 26%, var(--surface-elevated));
    border-bottom:1px solid color-mix(in srgb, var(--type-color, #2D6B95) 22%, var(--border));
  }
}

/* Band children */
.fc-band-glyph {
  display:inline-flex;align-items:center;flex-shrink:0;
  width:17px;height:17px;
  color:color-mix(in srgb, var(--type-color, #2D6B95) 80%, var(--text));
}
.fc-band-kicker {
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:11px;font-weight:600;letter-spacing:.02em;
  color:color-mix(in srgb, var(--type-color, #2D6B95) 40%, var(--text));
}
.fc-band-meta {
  display:flex;align-items:center;gap:4px;flex-shrink:0;
}
.fc-band-dot {
  width:5px;height:5px;border-radius:50%;
  background:color-mix(in srgb, var(--type-color, #2D6B95) 35%, var(--border));
  opacity:.65;
}
.fc-band-dot.grade-honed    { background:var(--grade-honed);   opacity:1; }
.fc-band-dot.grade-missed   { background:var(--grade-missed);  opacity:1; }
.fc-band-dot.grade-mastered { background:var(--grade-mastered);opacity:1; }
.fc-band-dot.grade-hazy     { background:var(--grade-hazy);    opacity:1; }
.fc-band-dot.current        { background:var(--type-color, #2D6B95); opacity:1; }
.fc-band-more {
  appearance:none;border:0;background:transparent;cursor:pointer;
  color:color-mix(in srgb, var(--type-color, #2D6B95) 70%, var(--text-faint));
  font-size:14px;padding:0 2px;line-height:1;min-height:24px;min-width:24px;
}

/* ─── MARKED-STATE BAND FLIP ────────────────────────────────────────── */
/* JS toggles a class on .fc-card (never inline var(), which Safari 15 can't
   resolve inside color-mix). CSS does the mix here. Band background + border
   flip to the grade tint when the card enters the marked state.
   Classes: .fc-card--marked-mastered / -missed / -honed / -hazy */
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-card--marked-mastered .fc-band {
    background:color-mix(in srgb, var(--grade-mastered) 22%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--grade-mastered) 30%, var(--border));
  }
  .fc-card--marked-missed .fc-band {
    background:color-mix(in srgb, var(--grade-missed) 22%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border));
  }
  .fc-card--marked-honed .fc-band {
    background:color-mix(in srgb, var(--grade-honed) 22%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--grade-honed) 30%, var(--border));
  }
  .fc-card--marked-hazy .fc-band {
    background:color-mix(in srgb, var(--grade-hazy) 22%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--grade-hazy) 30%, var(--border));
  }
  /* NEUTRAL "graded today" — exact grade unknown (server flag only:
     cross-device / cleared-cache). Grey band so the card looks answered. */
  .fc-card--marked-graded .fc-band {
    background:color-mix(in srgb, var(--text-faint) 16%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--text-faint) 26%, var(--border));
  }
}

/* ─── HERO ZONE (pre-reveal) ─────────────────────────────────────────── */
/* Centred vertically; hidden once .revealed is on .fc-card */
.fc-hero {
  flex:1;display:flex;flex-direction:column;justify-content:center;
  padding:16px 16px 18px;
}
.fc-card.revealed .fc-hero { display:none; }

.fc-hero-prompt {
  font-size:18px;font-weight:560;line-height:1.5;
  color:var(--text);letter-spacing:-.01em;
}

/* ─── TOP ZONE (post-reveal) ─────────────────────────────────────────── */
/* flex:none, scroll-locked; hidden until .revealed */
.fc-top {
  flex:none;max-height:clamp(80px,32%,200px);overflow-y:auto;
  -webkit-overflow-scrolling:touch;overscroll-behavior-y:contain;
  overscroll-behavior-x:contain;
  display:none;
}
.fc-card.revealed .fc-top { display:block; }

/* Demoted prompt: full --text colour, wraps, never truncates. A light type tint
   sets the prompt row apart from the (plain-surface) answer below it. */
.fc-prompt-demoted {
  padding:10px 16px 9px;font-size:13px;font-weight:450;line-height:1.45;
  color:var(--text);letter-spacing:-.005em;border-bottom:1px solid var(--border);
  background:var(--surface-alt);   /* Safari-15 fallback */
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-prompt-demoted {
    background:color-mix(in srgb, var(--type-color, #2D6B95) 10%, var(--surface-elevated));
  }
}

/* SAQ tab bar — flat tabs with an active-tab underline (mockup card-refresh-v2),
   pinned (flex:none) between the demoted prompt and the scrolling answer zone so
   the content swaps beneath fixed tabs and wastes no vertical space on nested
   boxes. SAQ-only: only _buildSaqTabsV2 inserts a .fc-tab-bar. Hidden until the
   card is revealed (matches .fc-top / .fc-answer-zone). */
.fc-tab-bar {
  display:none;flex:none;gap:2px;padding:4px 14px 0;justify-content:flex-start;
  border-bottom:1px solid var(--border);
  background:color-mix(in srgb, var(--type-color, #2D6B95) 5%, var(--surface-elevated));
}
.fc-card.revealed .fc-tab-bar { display:flex; }
.fc-tab {
  appearance:none;border:none;background:transparent;font:inherit;
  font-size:12.5px;font-weight:600;color:var(--text-faint);
  padding:7px 11px 8px;cursor:pointer;border-bottom:2px solid transparent;
  margin-bottom:-1px;letter-spacing:.01em;
  transition:color .15s,border-color .15s;white-space:nowrap;min-height:36px;
}
.fc-tab:hover { color:var(--text-muted); }
.fc-tab.active {
  color:var(--type-color, #2D6B95);border-bottom-color:var(--type-color, #2D6B95);
}
/* Tab panels live plainly inside .fc-answer-body (no nested box). */
.fc-tab-panel[hidden] { display:none; }
.fc-tab-empty { color:var(--text-muted);font-style:italic;margin:0; }

/* ─── ANSWER ZONE (post-reveal) ──────────────────────────────────────── */
/* THE ONLY scroll region; hidden until .revealed */
.fc-answer-zone {
  flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
  overscroll-behavior-y:contain;
  display:none;
}
.fc-card.revealed .fc-answer-zone { display:block; }

/* Mask fade — added by JS when content overflows; removed at bottom */
.fc-answer-zone.mask-active {
  -webkit-mask-image:linear-gradient(to bottom,#000 88%,transparent);
  mask-image:linear-gradient(to bottom,#000 88%,transparent);
}
.fc-answer-zone.mask-bottom {
  -webkit-mask-image:none;
  mask-image:none;
}

/* Dark-mode answer zone = recessed well */
html.dark .fc-card.revealed .fc-answer-zone {
  background:var(--surface);
}

/* Answer body */
.fc-answer-body {
  padding:14px 16px 40px;/* extra bottom so last line clears mask fade + grade zone */
  font-size:14px;line-height:1.68;color:var(--text);
  background:var(--surface);/* recessed vs card surface-elevated */
}
html.dark .fc-answer-body { background:var(--surface); }
.fc-answer-body strong { font-weight:700;color:var(--text); }
.fc-answer-body p { margin:0 0 10px; }
.fc-answer-body p:last-child { margin-bottom:0; }
.fc-answer-body ul { padding-left:18px;margin:0 0 10px; }
.fc-answer-body li { margin:4px 0; }

/* Callout block */
.fc-callout {
  border-radius:var(--radius-sm);padding:10px 12px;margin:6px 0;
  background:var(--surface-elevated);
  border:1px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-callout {
    background:color-mix(in srgb, var(--type-color, #2D6B95) 10%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--type-color, #2D6B95) 20%, var(--border));
  }
}
.fc-callout-label {
  font-size:9px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--type-color, #2D6B95);margin-bottom:4px;
}
.fc-callout-text { font-size:13px;line-height:1.55;color:var(--text-muted); }

/* Axiom monospace answer body */
.fc-card.type-axiom .fc-answer-body {
  font-family:"SF Mono","Fira Code",Consolas,"Liberation Mono",monospace;
  font-size:13.5px;font-variant-numeric:tabular-nums;line-height:1.75;
}

/* Answer + grade zone reveal animation */
@media (prefers-reduced-motion:no-preference) {
  @keyframes fcRevealIn { from{opacity:0;transform:translateY(6px)} to{opacity:1;transform:none} }
  .fc-answer-zone.reveal-anim,.fc-grade-zone.reveal-anim {
    animation:fcRevealIn .22s var(--ease-spring) both;
  }
  .fc-grade-zone.reveal-anim { animation-delay:60ms; }
}

/* ─── GRADE ZONE (shared wrapper) ────────────────────────────────────── */
.fc-grade-zone {
  flex:none;border-top:1px solid var(--border);position:relative;
}

/* ─── GRADE ROW (post-reveal inverted-T) ─────────────────────────────── */
/* IDENTICAL grid contract as .fc-miss-tag-row — load-bearing for overlay alignment */
.fc-grade-row {
  display:grid;grid-template-columns:1fr 1fr;grid-template-rows:auto auto;
  gap:5px;padding:10px 10px 12px;
}
.fc-grade-btn {
  appearance:none;border:none;border-radius:var(--radius-md);min-height:44px;padding:0 10px;
  font:inherit;font-size:13px;font-weight:700;cursor:pointer;text-align:center;
  display:flex;align-items:center;justify-content:center;letter-spacing:.01em;
  transition:transform .1s var(--ease-out);
}
.fc-grade-btn:active { transform:scale(.96); }

/* Mastered: top-wide (grid-column:1/-1) */
.fc-grade-btn.mastered {
  grid-column:1/-1;
  color:var(--grade-mastered-label);
  background:var(--surface-elevated);
  border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-grade-btn.mastered {
    background:color-mix(in srgb, var(--grade-mastered) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-mastered) 30%, var(--border));
  }
}

/* Missed: row2 col1 */
.fc-grade-btn.missed {
  color:var(--grade-missed-label);
  background:var(--surface-elevated);
  border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-grade-btn.missed {
    background:color-mix(in srgb, var(--grade-missed) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border));
  }
}
html.dark .fc-grade-btn.missed {
  background:var(--surface-elevated);border-color:var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  html.dark .fc-grade-btn.missed {
    background:color-mix(in srgb, var(--grade-missed) 14%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-missed) 35%, var(--border));
  }
}

/* Honed: row2 col2 */
.fc-grade-btn.honed {
  color:var(--grade-honed-label);
  background:var(--surface-elevated);
  border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-grade-btn.honed {
    background:color-mix(in srgb, var(--grade-honed) 10%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-honed) 28%, var(--border));
  }
}
html.dark .fc-grade-btn.honed {
  color:var(--grade-honed-label);
  background:var(--surface-elevated);border-color:var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  html.dark .fc-grade-btn.honed {
    background:color-mix(in srgb, var(--grade-honed) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-honed) 30%, var(--border));
  }
}

/* ─── MISS-TAG OVERLAY ────────────────────────────────────────────────── */
/* Absolutely covers .fc-grade-zone (which is position:relative).
   display:none by default; .open shows it. */
.fc-miss-tag-overlay {
  position:absolute;inset:0;overflow:visible;
  background:var(--surface-elevated);border-top:1px solid var(--border);
  z-index:5;display:none;
}
.fc-miss-tag-overlay.open { display:block; }

/* Back button: floats ABOVE overlay (over answer zone), out of flow */
.fc-miss-back-btn {
  appearance:none;position:absolute;left:10px;right:10px;bottom:calc(100% + 6px);
  min-height:44px;border:1.5px solid var(--border-strong);border-radius:var(--radius-md);
  background:var(--surface-elevated);color:var(--text-muted);
  box-shadow:0 -4px 12px -6px rgba(0,0,0,.18);
  font:inherit;font-size:12.5px;font-weight:600;cursor:pointer;
  letter-spacing:.01em;text-align:center;
  transition:border-color .15s,color .15s;
}
.fc-miss-back-btn:hover { border-color:var(--text-faint);color:var(--text); }
.fc-miss-back-btn:active { transform:scale(.97); }

/* Miss-tag row: IDENTICAL grid+padding to .fc-grade-row (load-bearing alignment) */
.fc-miss-tag-row {
  display:grid;grid-template-columns:1fr 1fr;grid-template-rows:auto auto;
  gap:5px;padding:10px 10px 12px;
}
.fc-miss-tag-btn {
  appearance:none;border:none;border-radius:var(--radius-md);min-height:44px;padding:0 10px;
  font:inherit;font-size:13px;font-weight:700;cursor:pointer;text-align:center;
  display:flex;align-items:center;justify-content:center;letter-spacing:.01em;
  transition:transform .1s var(--ease-out),filter .1s;
}
.fc-miss-tag-btn:active { transform:scale(.96); }

/* Hazy: top-wide — mirrors Mastered */
.fc-miss-tag-btn.hazy {
  grid-column:1/-1;
  color:var(--grade-hazy-label);
  background:var(--surface);border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-miss-tag-btn.hazy {
    background:color-mix(in srgb, var(--grade-hazy) 12%, var(--surface));
    border-color:color-mix(in srgb, var(--grade-hazy) 30%, var(--border));
  }
}

/* Blank: mirrors Missed */
.fc-miss-tag-btn.blank {
  color:var(--grade-blank-label);
  background:var(--surface);border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-miss-tag-btn.blank {
    background:color-mix(in srgb, var(--grade-missed) 12%, var(--surface));
    border-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border));
  }
}

/* Mixed: mirrors Honed */
.fc-miss-tag-btn.mixed {
  color:var(--grade-hazy-label);
  background:var(--surface);border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-miss-tag-btn.mixed {
    background:color-mix(in srgb, var(--grade-hazy) 12%, var(--surface));
    border-color:color-mix(in srgb, var(--grade-hazy) 30%, var(--border));
  }
}

/* ─── MARKED CHIP ROW ─────────────────────────────────────────────────── */
/* Shown when .marked (graded); chip ≥44px, full-width */
.fc-marked-chip-row {
  padding:10px 10px 12px;display:flex;align-items:center;justify-content:center;
}
.fc-marked-chip-btn {
  appearance:none;border:none;border-radius:var(--radius-md);padding:9px 12px;
  width:100%;min-height:44px;
  font:inherit;font-size:12px;font-weight:700;cursor:pointer;letter-spacing:.01em;
  /* --marked-color set inline by JS; fallback = mastered */
  color:var(--marked-label-color, var(--grade-mastered-label));
  background:var(--surface-elevated);border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-marked-chip-btn {
    background:color-mix(in srgb, var(--marked-color, var(--grade-mastered)) 14%, var(--surface));
    border-color:color-mix(in srgb, var(--marked-color, var(--grade-mastered)) 35%, var(--border));
  }
}
/* Marked (nav-return graded): collapse the grade zone to JUST the chip — hide the
   grade row / reveal / confidence so nothing overflows the footer. */
.fc-card--v2.marked .fc-grade-zone .recall-actions,
.fc-card--v2.marked .fc-grade-zone .fc-confidence,
.fc-card--v2.marked .fc-grade-zone .fc-show-btn,
.fc-card--v2.marked .fc-grade-zone .fc-reveal-btn { display:none !important; }

/* ─── REVEAL BUTTON (pre-reveal) ──────────────────────────────────────── */
.fc-reveal-btn {
  display:block;width:100%;appearance:none;border-radius:var(--radius-md);min-height:44px;
  padding:0 10px;font:inherit;font-size:13px;font-weight:700;cursor:pointer;
  text-align:center;letter-spacing:.01em;margin:10px 10px 12px;
  width:calc(100% - 20px);
  color:var(--type-reveal-label, var(--recall-reveal-label));
  background:var(--surface-elevated);border:1.5px solid var(--border);
  transition:transform .1s var(--ease-out),filter .1s var(--ease-out);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-reveal-btn {
    background:color-mix(in srgb, var(--type-color, #2D6B95) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--type-color, #2D6B95) 30%, var(--border));
  }
}
/* .fc-reveal-btn:active — REMOVED, consolidated into the shared .mo-press
   utility (motion/motion.css) applied in card/reveal.js. */

/* --type-reveal-label per type (uses the new -reveal-label tokens from §7) */
.fc-card.type-recall  .fc-reveal-btn { color:var(--recall-reveal-label); }
.fc-card.type-saq     .fc-reveal-btn { color:var(--saq-reveal-label); }
.fc-card.type-pharma  .fc-reveal-btn { color:var(--pharma-reveal-label); }
.fc-card.type-axiom   .fc-reveal-btn { color:var(--axiom-reveal-label); }

/* ─── SWIPE WASH ─────────────────────────────────────────────────────────
   The bare .fc-swipe-wash shell rule was a duplicate of the authoritative
   definition (with gradient variants) in focus-mode.css:1393 — REMOVED. */

/* ═══════════════════════════════════════════════════════════════════════
   PHASE 3 — v2-scoped overrides for REUSED app.js grade components
   The grade row in Phase 3 comes from app.js reused helpers (_buildGradeRow /
   buildFcActionBar) which emit .recall-actions > .post-reveal > .r-grade--*.
   These rules restyle those existing elements to match the v2 design INSIDE
   .fc-card--v2 only. Existing v1 cards are unaffected.
   Phase 4 will replace these with native .fc-grade-btn rules (see buildGradeRowV2).
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── GRADE ZONE: recall-actions wrapper ────────────────────────────── */
/* In v2, the grade zone container is .fc-grade-zone (position:relative).
   .recall-actions fills it without extra chrome. */
.fc-card--v2 .fc-grade-zone .recall-actions {
  display:flex;flex-direction:column;width:100%;
}

/* ─── POST-REVEAL GRADE ROW (reused .post-reveal) ────────────────────── */
/* Override the v1 segmented-control grid (gap:0) with the v2 spec:
   inverted-T, 5px gap, 10px 10px 12px padding (FROZEN §2). */
.fc-card--v2 .fc-grade-zone .post-reveal {
  display:grid;
  grid-template-columns:1fr 1fr;
  grid-template-rows:auto auto;
  gap:5px;
  padding:10px 10px 12px;
  height:auto;  /* override v1 fixed height */
  width:100%;
  box-sizing:border-box;
}

/* Inverted-T placement: mastered = top wide, missed = BL, honed = BR */
.fc-card--v2 .fc-grade-zone .post-reveal .r-grade--mastered {
  grid-column:1/-1;
  grid-row:1;
  /* Reset v1 radius rules */
  border-top-left-radius:10px;
  border-top-right-radius:10px;
  border-bottom-left-radius:10px;
  border-bottom-right-radius:10px;
}
.fc-card--v2 .fc-grade-zone .post-reveal .r-grade--missed {
  grid-column:1;
  grid-row:2;
  border-radius:var(--radius-md);
}
.fc-card--v2 .fc-grade-zone .post-reveal .r-grade--honed {
  grid-column:2;
  grid-row:2;
  border-radius:var(--radius-md);
}

/* ─── GRADE BUTTONS: v2 uniform tint+outline+deep-label recipe ────────── */
/* Override the v1 solid-fill style with tint+outline+deep-label per FROZEN §2.
   The existing .recall-actions rules use solid colour fill (eye-catching).
   v2 uses the same visual recipe as .fc-grade-btn.* above. */
.fc-card--v2 .fc-grade-zone .r-grade {
  appearance:none;
  border-radius:var(--radius-md);
  min-height:44px;
  padding:0 10px;
  font:inherit;
  font-size:13px;
  font-weight:700;
  cursor:pointer;
  text-align:center;
  display:flex;
  align-items:center;
  justify-content:center;
  letter-spacing:.01em;
  transition:transform .1s var(--ease-out);
}
/* cinema .r-grade:active — REMOVED, consolidated into .mo-press-3d (motion/motion.css),
   applied per grade button in card/grade.js with a grade-tinted crush shadow. */

/* Mastered — tint+outline+deep violet label */
.fc-card--v2 .fc-grade-zone .r-grade--mastered {
  color:var(--grade-mastered-label);
  background:var(--surface-elevated);
  border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-card--v2 .fc-grade-zone .r-grade--mastered {
    background:color-mix(in srgb, var(--grade-mastered) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-mastered) 30%, var(--border));
  }
}

/* Missed — tint+outline+deep coral label */
.fc-card--v2 .fc-grade-zone .r-grade--missed {
  color:var(--grade-missed-label);
  background:var(--surface-elevated);
  border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-card--v2 .fc-grade-zone .r-grade--missed {
    background:color-mix(in srgb, var(--grade-missed) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border));
  }
}

/* Honed — tint+outline+deep green label */
.fc-card--v2 .fc-grade-zone .r-grade--honed {
  color:var(--grade-honed-label);
  background:var(--surface-elevated);
  border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-card--v2 .fc-grade-zone .r-grade--honed {
    background:color-mix(in srgb, var(--grade-honed) 10%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-honed) 28%, var(--border));
  }
}

/* ─── SHOW-ANSWER BUTTON in v2 grade zone ────────────────────────────── */
/* buildRecallCardV2 adds BOTH fc-show-btn (v1) and fc-reveal-btn (v2) classes.
   The existing .fc-reveal-btn rules in this file already handle the styling.
   Override the v1 .fc-show-btn btn--primary fill so the v2 look wins. */
.fc-card--v2 .fc-grade-zone .fc-show-btn {
  display:block;
  width:calc(100% - 20px);
  margin:10px 10px 0;
  /* v2 uniform tint+outline+deep label — this (0,3,0) selector must beat
     the v1 .btn--primary green fill (loaded after card-v2.css in the manifest). */
  min-height:44px;border-radius:var(--radius-md);font-weight:700;font-size:13px;letter-spacing:.01em;
  background:var(--surface-elevated);
  border:1.5px solid var(--border);
  color:var(--type-reveal-label, var(--recall-reveal-label));
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-card--v2 .fc-grade-zone .fc-show-btn {
    background:color-mix(in srgb, var(--type-color, #2D6B95) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--type-color, #2D6B95) 30%, var(--border));
  }
}
.fc-card--v2.type-recall .fc-grade-zone .fc-show-btn { color:var(--recall-reveal-label); }

/* v2 identity = the colour BAND, not a left stripe. Override the v1 per-type
   6px border-left (focus-mode.css:632/655) back to the neutral 1px card border.
   (0,3,0)/(0,4,1) specificity beats the v1 light/dark type-stripe rules. */
.fc-card.fc-card--v2[data-type] { border-left:1px solid var(--border); }
html.dark .fc-card.fc-card--v2[data-type] { border-left-color:var(--border); }

/* Hide the show-btn once revealed (v2 version, mirrors .fc-card.revealed .fc-reveal-btn) */
.fc-card--v2.revealed .fc-grade-zone .fc-show-btn,
.fc-card--v2.revealed .fc-grade-zone .fc-reveal-btn {
  display:none;
}

/* ─── CONFIDENCE BAR in v2 grade zone ────────────────────────────────── */
/* fc-confidence already hides on .revealed via:
   .fc-card.revealed .fc-confidence { display:none }  (app-shell-tail.css:1614)
   Position it at the top of the grade zone, above the show-btn. */
.fc-card--v2 .fc-grade-zone .fc-confidence {
  padding:10px 10px 0;
  flex-shrink:0;
}

/* ═══ NO HOVER tint/fill change on v2 controls ════════════════════════════════
   On touch, :hover sticks after a tap → the button stays in its hover state
   (e.g. Show Answer going solid green). The v2 controls must look identical at
   rest and on hover (interactivity comes later). CSS has no "revert to the
   non-hover value", so each :hover re-states the resting recipe, scoped to
   .fc-card--v2 at specificity ≥ the v1 hover rules that bleed in (focus-overlay
   btn--primary / fc-confidence-chip / miss-tag-btn :hover). */

/* Reveal / Show-Answer */
.fc-card--v2 .fc-grade-zone .fc-show-btn:hover,
.fc-card--v2 .fc-grade-zone .fc-reveal-btn:hover {
  background:var(--surface-elevated); border-color:var(--border);
  color:var(--type-reveal-label, var(--recall-reveal-label)); filter:none;
}
.fc-card--v2.type-recall .fc-grade-zone .fc-show-btn:hover,
.fc-card--v2.type-recall .fc-grade-zone .fc-reveal-btn:hover { color:var(--recall-reveal-label); }
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-card--v2 .fc-grade-zone .fc-show-btn:hover,
  .fc-card--v2 .fc-grade-zone .fc-reveal-btn:hover {
    background:color-mix(in srgb, var(--type-color, #2D6B95) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--type-color, #2D6B95) 30%, var(--border));
  }
}

/* Grade buttons */
.fc-card--v2 .fc-grade-zone .r-grade--mastered:hover { color:var(--grade-mastered-label); background:var(--surface-elevated); border-color:var(--border); }
.fc-card--v2 .fc-grade-zone .r-grade--missed:hover   { color:var(--grade-missed-label);   background:var(--surface-elevated); border-color:var(--border); }
.fc-card--v2 .fc-grade-zone .r-grade--honed:hover    { color:var(--grade-honed-label);    background:var(--surface-elevated); border-color:var(--border); }
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-card--v2 .fc-grade-zone .r-grade--mastered:hover { background:color-mix(in srgb, var(--grade-mastered) 12%, var(--surface-elevated)); border-color:color-mix(in srgb, var(--grade-mastered) 30%, var(--border)); }
  .fc-card--v2 .fc-grade-zone .r-grade--missed:hover   { background:color-mix(in srgb, var(--grade-missed) 12%, var(--surface-elevated));   border-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border)); }
  .fc-card--v2 .fc-grade-zone .r-grade--honed:hover    { background:color-mix(in srgb, var(--grade-honed) 10%, var(--surface-elevated));    border-color:color-mix(in srgb, var(--grade-honed) 28%, var(--border)); }
}

/* Confidence chips — re-state per-grade resting (beat focus-overlay …:hover muted) */
.fc-card--v2 .fc-grade-zone .fc-confidence-chip:hover { color:var(--text-muted); border-color:var(--border); background:var(--surface-alt); }
.fc-card--v2 .fc-grade-zone .fc-confidence-chip[data-grade="1"]:hover { color:var(--coral-deep); border-color:color-mix(in srgb,var(--coral-vivid) 40%,var(--border)); background:color-mix(in srgb,var(--coral-vivid) 10%,var(--surface-elevated)); }
.fc-card--v2 .fc-grade-zone .fc-confidence-chip[data-grade="2"]:hover { color:var(--honey-deep);  border-color:color-mix(in srgb,var(--honey) 40%,var(--border));       background:color-mix(in srgb,var(--honey) 10%,var(--surface-elevated)); }
.fc-card--v2 .fc-grade-zone .fc-confidence-chip[data-grade="4"]:hover { color:var(--violet-deep); border-color:color-mix(in srgb,var(--violet) 40%,var(--border));      background:color-mix(in srgb,var(--violet) 10%,var(--surface-elevated)); }

/* Miss-tag — re-state per-tag resting (beat the all-coral !important hover) */
.fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="hazy"]:hover,
.fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="mixed"]:hover {
  color:var(--grade-hazy-label) !important; border:1.5px solid var(--border) !important; background:var(--surface) !important;
}
.fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="blank"]:hover {
  color:var(--grade-blank-label) !important; border:1.5px solid var(--border) !important; background:var(--surface) !important;
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="hazy"]:hover,
  .fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="mixed"]:hover { background:color-mix(in srgb, var(--grade-hazy) 12%, var(--surface)) !important; border-color:color-mix(in srgb, var(--grade-hazy) 30%, var(--border)) !important; }
  .fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="blank"]:hover { background:color-mix(in srgb, var(--grade-missed) 12%, var(--surface)) !important; border-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border)) !important; }
}

/* ─── MISS-TAG OVERLAY in v2 context ─────────────────────────────────── */
/* The existing overlay structure from buildMissTagOverlay:
     .miss-tag-overlay.miss-tag-overlay--focus
       .miss-tag-header
       .miss-tag-grid
         .miss-tag-btn × N
   In v2, the overlay should sit OVER the grade zone (absolute, inset:0).
   The existing app-shell .fc-card.tag-open rules handle display:flex already.
   We override the height/sizing and absolute positioning here. */
/* Overlay covers the grade zone. Must beat app-shell-tail.css:5028
   (.fc-card .miss-tag-overlay{position:relative;overflow:hidden}) which is
   equal-specificity (0,3,0) but loaded LATER — so we use a 0,4,0 selector
   (+.tag-open) for the load-bearing position/overflow. */
/* 0,4,0 (.fc-card.fc-card--v2 …) so position:absolute + overflow:visible BEAT
   app-shell-tail.css:5028 `.fc-card .miss-tag-overlay{position:relative;overflow:
   hidden}` which loads later — without this the overlay falls into flow BELOW the
   grade row (both show stacked) instead of covering it. */
.fc-card.fc-card--v2 .fc-grade-zone .miss-tag-overlay {
  position:absolute;
  inset:0;
  background:var(--surface-elevated);
  border-top:1px solid var(--border);
  z-index:7;
  /* ALWAYS rendered + laid out (display:block), and shown/hidden via VISIBILITY,
     not display. iOS Safari defers painting a display:none→block flip until the
     next touch (the "miss-tags only appear after a tap" bug) — but it paints a
     visibility flip immediately because the element (incl. its buttons) is already
     laid out. !important beats app-shell-tail.css's .miss-tag-overlay{display:none}.
     Covering the grade zone (absolute, inset:0) is what HIDES the grade buttons
     when the miss-tags open — no separate teardown needed. */
  display:block !important;
  visibility:hidden;
  pointer-events:none;   /* let taps fall through to the grade buttons while hidden */
  height:auto;
  overflow:visible;      /* let the floated header sit above the grade zone */
  box-sizing:border-box;
}
.fc-card.fc-card--v2.tag-open .fc-grade-zone .miss-tag-overlay {
  visibility:visible;
  pointer-events:auto;
}

/* Swipe-only mode (Settings ▸ "Show grade buttons in focus mode" OFF →
   body.fc-buttons-hidden): the grade row (.post-reveal) + Show Answer are
   display:none, collapsing the grade zone to ~0 height. A swipe-to-Missed still
   opens the miss-tag overlay, but positioned absolute (inset:0) over a 0-height
   zone its tags collapse to nothing — the user has NO way to tag the miss and
   the card looks frozen. Fix: let the overlay flow IN-PLACE (it no longer has a
   grade row to cover), sized by its own content, so the inverted-T tags render
   full-size + tappable. Reveal + grade buttons stay hidden. */
body.fc-buttons-hidden .fc-card--v2.tag-open .fc-grade-zone .post-reveal {
  display:grid !important;  /* re-enable the grade-row LAYOUT (overrides fc-buttons-hidden's display:none) */
  visibility:hidden;        /* …but keep the grade buttons invisible + non-interactive */
}

/* Header → floats ABOVE the grade zone (over the answer zone), out of flow,
   mirroring the mockup's floating back-btn (.fc-miss-back-btn). */
.fc-card--v2 .fc-grade-zone .miss-tag-overlay .miss-tag-header {
  position:absolute;
  left:10px; right:10px; bottom:calc(100% + 6px);
  display:flex; align-items:center; justify-content:center; gap:6px;
  min-height:34px; margin:0; padding:0 12px;
  border:1.5px solid var(--border-strong); border-radius:var(--radius-md);
  background:var(--surface-elevated); color:var(--grade-missed-label);
  box-shadow:0 -4px 12px -6px rgba(0,0,0,.18);
  font-size:12.5px; font-weight:700; letter-spacing:.01em; white-space:nowrap;
}
.fc-card--v2 .fc-grade-zone .miss-tag-overlay .miss-tag-header-icon {
  width:14px; height:14px; flex-shrink:0;
}

/* Focus mode: the header is a "← Back to grading" control. "← Back" pinned left,
   the prompt centred in the remaining space; the whole pill is tappable (closes
   the miss-tag overlay → grade buttons return). */
.fc-card--v2 .fc-grade-zone .miss-tag-overlay .miss-tag-header--back {
  justify-content:flex-start; gap:8px; cursor:pointer;
}
.fc-card--v2 .miss-tag-header--back .miss-tag-back {
  flex-shrink:0; color:var(--text); font-weight:800;
}
.fc-card--v2 .miss-tag-header--back .miss-tag-header-label {
  flex:1; text-align:center; color:var(--grade-missed-label); font-weight:700;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* Tag grid → inverted-T, identical footprint to the grade row, fills the overlay.
   The selector includes .miss-tag-overlay (0,4,0) to BEAT app-shell-tail.css:5038
   (.fc-card .miss-tag-overlay .miss-tag-grid{padding:0}, 0,3,0 but loaded later) —
   without the padding the tags lose their 10px inset (too wide) AND the grid
   under-fills so align-content stretches them taller than the grade buttons. */
.fc-card--v2 .fc-grade-zone .miss-tag-overlay .miss-tag-grid {
  display:grid;
  grid-template-columns:1fr 1fr;
  grid-template-rows:auto auto;
  gap:5px;
  padding:10px 10px 12px;
  height:100%;
  align-content:start;   /* never stretch the rows → tags stay 44px like the grade buttons */
  box-sizing:border-box;
  flex:none;
}

/* Tag buttons: size EXACTLY like the grade buttons (.r-grade). Without an
   explicit min-height the v1 .miss-tag-btn over-stretches via the grid's
   align-content:stretch (~55px → reads "too large"); pinning 44px makes the
   content fill the zone with no stretch, so the inverted-T lands pixel-for-pixel
   on the Mastered/Missed/Honed footprint. */
.fc-card--v2 .fc-grade-zone .miss-tag-btn {
  min-height:44px; padding:0 10px; border-radius:var(--radius-md); box-sizing:border-box;
  display:flex; align-items:center; justify-content:center; gap:6px;
  font:inherit; font-size:13px; font-weight:700; letter-spacing:.01em;
}

/* Inverted-T placement mirroring the grade buttons: Hazy↔Mastered (top-wide),
   Blank↔Missed (col1 row2), Mixed↔Honed (col2 row2). Place by data-tag ONLY —
   MISS_TAGS order is [blank,hazy,mixed], so :first-child is Blank, not Hazy
   (using :first-child collided Blank onto Hazy's top cell → the overlap bug). */
.fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="hazy"]  { grid-column:1/-1; grid-row:1; border-radius:var(--radius-md); }
.fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="blank"] { grid-column:1;    grid-row:2; border-radius:var(--radius-md); }
.fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="mixed"] { grid-column:2;    grid-row:2; border-radius:var(--radius-md); }

/* Per-tag colour mirroring the swipe map (Hazy honey / Blank coral / Mixed honey).
   The focus-mode rule app-shell-tail.css:5058 forces ALL tags coral with
   !important (0,2,0); these 0,4,0 !important rules win it back per-tag. */
.fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="hazy"],
.fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="mixed"] {
  color:#7A5A00 !important;   /* yellower gold (was --grade-hazy-label #6E4509 brown) */
  border:1.5px solid var(--border) !important;
  background:var(--surface) !important;
}
html.dark .fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="hazy"],
html.dark .fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="mixed"] {
  color:#FBBF24 !important;   /* bright yellow on dark */
}
.fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="blank"] {
  color:var(--grade-blank-label) !important;
  border:1.5px solid var(--border) !important;
  background:var(--surface) !important;
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="hazy"],
  .fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="mixed"] {
    background:color-mix(in srgb, #F0B429 16%, var(--surface)) !important;   /* golden yellow, was amber #f59e0b */
    border-color:color-mix(in srgb, #F0B429 36%, var(--border)) !important;
  }
  .fc-card--v2 .fc-grade-zone .miss-tag-grid [data-tag="blank"] {
    background:color-mix(in srgb, var(--grade-missed) 12%, var(--surface)) !important;
    border-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border)) !important;
  }
}

/* ─── REVEAL TRANSITIONS: hero ↔ demoted prompt cross-fade ─────────────── */
/* Pre-reveal: hero zone is visible (already handled by .fc-hero / .fc-card.revealed .fc-hero).
   Post-reveal: demoted prompt + answer zone + grade zone become visible.
   These are handled by the zone CSS above (.fc-hero / .fc-top / .fc-answer-zone rules).
   Confidence bar hidden on reveal is handled by existing app-shell-tail.css:1614.
   Nothing additional needed here beyond the zone-level rules already in place. */

/* ─── MARKED-STATE: data-graded attribute → band flip ─────────────────── */
/* rateFocusCard sets data-graded="mastered|honed|missed" directly on .fc-card.
   tagMiss sets it to "missed". Use the existing .fc-card--marked-* class rules
   (already defined above in this file). Also wire data-graded as an alias so
   the band flips even if the class isn't set by the undo path. */
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .fc-card--v2[data-graded="mastered"] .fc-band {
    background:color-mix(in srgb, var(--grade-mastered) 22%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--grade-mastered) 30%, var(--border));
  }
  .fc-card--v2[data-graded="missed"] .fc-band {
    background:color-mix(in srgb, var(--grade-missed) 22%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border));
  }
  .fc-card--v2[data-graded="honed"] .fc-band {
    background:color-mix(in srgb, var(--grade-honed) 22%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--grade-honed) 30%, var(--border));
  }
}

/* ─── DOTS / RAIL from _buildDotRail inside .fc-band-meta ─────────────── */
/* _buildDotRail returns .card__rail containing .rr-dots with .rr-dot spans.
   In v2, this rail sits inside .fc-band-meta and should be compact/inline. */
.fc-card--v2 .fc-band-meta .card__rail {
  display:flex;align-items:center;gap:0;
}
.fc-card--v2 .fc-band-meta .rr-dots {
  display:flex;align-items:center;gap:3px;
}
.fc-card--v2 .fc-band-meta .rr-dot {
  width:6px;height:6px;border-radius:50%;
  background:color-mix(in srgb, var(--type-color, #2D6B95) 62%, var(--text-faint));
  opacity:.92;
}
.fc-card--v2 .fc-band-meta .rr-dot.missed   { background:var(--grade-missed);  opacity:1; }
.fc-card--v2 .fc-band-meta .rr-dot.honed    { background:var(--grade-honed);   opacity:1; }
.fc-card--v2 .fc-band-meta .rr-dot.mastered { background:var(--grade-mastered);opacity:1; }
/* Empty (no grade yet) dots: app-shell-tail.css:4566 makes them transparent+1px
   border (poor contrast on the tinted band). Beat it (0,4,0) with a solid muted
   fill so the rail is clearly visible. */
.fc-card--v2 .fc-band-meta .rr-dot.empty {
  background:var(--text-muted); border:none; opacity:.6;
}
/* Forecast chip: hide (not enough space in band meta) */
.fc-card--v2 .fc-band-meta .rr-chip { display:none; }
/* Nemesis text: compact in band */
.fc-card--v2 .fc-band-meta .rr-nemesis {
  font-size:9px;font-weight:800;letter-spacing:.06em;
  color:var(--grade-missed);opacity:.9;
}
.fc-card--v2 .fc-band-meta .nem-text { font-size:9px; }

/* ─── WHY BADGE from _buildWhyBadge inside .fc-band-meta ─────────────── */
/* Keep the badge small and inline with the band. */
.fc-card--v2 .fc-band-meta .recall-why-badge {
  font-size:9px;font-weight:700;padding:2px 5px;border-radius:var(--radius-tiny);
  white-space:nowrap;
}

/* ─── CARD OPTIONS BUTTON inside .fc-band-meta ────────────────────────── */
.fc-card--v2 .fc-band-meta .card-options-btn {
  /* reset the global .card-options-btn{position:absolute;top:8px;right:8px}
     (app-shell-tail.css:343) so the kebab sits INSIDE the band-meta flow,
     not floated to the card's top-right corner. */
  position:relative;top:auto;right:auto;opacity:1;width:auto;height:auto;z-index:5;
  flex:0 0 auto;   /* lift above overlapping meta content + never shrink below 24px */
  appearance:none;border:0;background:transparent;cursor:pointer;
  color:color-mix(in srgb, var(--type-color, #2D6B95) 70%, var(--text-faint));
  padding:0 2px;line-height:1;min-height:24px;min-width:24px;
  display:inline-flex;align-items:center;justify-content:center;
}

/* =====================================================================
   pwa/card/card.css — Grid surface (Today + Library) card system styles.

   Phase 1 scope: .card-proposed (today) + .card-browse (library).
   Cinema + preview styles remain in card-v2.css (coexist, not deleted yet).

   MIGRATE from card-v2.css:
     .card-proposed/.card-browse shells + padding-override
     .p-band/.b-band + glyphs/kicker/meta/dots
     .p-prompt hero + demoted + reveal row/btn + seam + answer
     .recall-actions grade row + miss-tag overlay (today context)
     .fc-tab-bar/.fc-tab/.fc-tab-panel (SAQ tabs in grid)
     .study-card__chip undo chip
     Reveal animation
   KEEP in shared files (cross-surface; do NOT re-declare here):
     .recall-actions base / .post-reveal / .r-grade / .r-grade--* (pre-planner CSS)
     .card__header / .card__rail / .card-options-btn (tail CSS)
     .fc-card SESSION-LAYOUT rules in focus-mode.css
     .miss-tag-overlay / .miss-tag-grid base (pre-planner CSS)

   TYPE_TOKENS: --type-color is set by .type-* on the card root (card-v2.css keeps
   those because .fc-card--v2 also uses them; we scope to .card-proposed/.card-browse).
   ===================================================================== */

/* ─── TYPE COLOR (grid scope only) ──────────────────────────────────── */
/* These are duplicated from card-v2.css but scoped to grid shells.
   card-v2.css sets them on .fc-card.type-*; our roots also carry .type-*
   so both rules fire. Order doesn't matter (same specificity). */
.card-proposed.type-recall,
.card-browse.type-recall  { --type-color:var(--recall); }
.card-proposed.type-saq,
.card-browse.type-saq     { --type-color:var(--rose-deep); }
.card-proposed.type-pharma,
.card-browse.type-pharma  { --type-color:var(--violet-deep); }
.card-proposed.type-axiom,
.card-browse.type-axiom   { --type-color:var(--saltbush-deep); }

html.dark .card-proposed.type-recall,
html.dark .card-browse.type-recall  { --type-color:var(--type-recall); }
html.dark .card-proposed.type-saq,
html.dark .card-browse.type-saq     { --type-color:var(--type-saq); }
html.dark .card-proposed.type-pharma,
html.dark .card-browse.type-pharma  { --type-color:var(--type-pharma); }
html.dark .card-proposed.type-axiom,
html.dark .card-browse.type-axiom   { --type-color:var(--type-axiom); }

/* ─── P1/P2: NEUTRALISE CINEMA .fc-card BLEED ────────────────────────── */
/* focus-mode.css sets:
     .fc-card { touch-action:none; will-change:transform; overflow-y:auto;
                min-height:280px; min-width:380px; position:relative;
                contain:layout style; }
     .fc-body { touch-action:none }
   Grid cards carry the .fc-card class (§11b contract) but are STATIC TILES
   in normal document flow. These overrides restore scroll-safe behaviour and
   content-driven height.  All !important beats the cinema specificity. */
.card-proposed.fc-card,
.card-browse.fc-card {
  touch-action:auto !important;     /* P1: never block or hijack scroll */
  will-change:auto !important;      /* P1: no compositor layer on static tiles */
  overflow-y:hidden !important;     /* P1: restore shell's overflow:hidden; neutralizes cinema overflow-y:auto scroll container */
  min-height:0 !important;          /* P2: content-driven height, no 280px floor */
  contain:none !important;          /* P1: remove layout containment (can trap stacking) */
}
/* .fc-body is the cinema scroll region; if grid cards have it, ensure no touch-action block */
.card-proposed .fc-body,
.card-browse .fc-body {
  touch-action:auto !important;
}

/* ─── CARD SHELLS ────────────────────────────────────────────────────── */
.card-proposed,
.card-browse {
  background:var(--surface-elevated);
  border-radius:var(--radius);
  border:1px solid var(--border);
  overflow:hidden;
  box-shadow:var(--shadow-md);
  display:flex;
  flex-direction:column;
  position:relative;
  /* BUG-C: fix min-width:380px from focus-mode.css .fc-card leaking onto grid cards */
  min-width:0 !important;
  max-width:100% !important;
  width:100% !important;
  box-sizing:border-box !important;
}
.card-browse {
  cursor:pointer;
  transition:box-shadow .15s var(--ease-out), border-color .15s;
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-browse:hover {
    box-shadow:0 6px 20px rgba(0,0,0,.12);
    border-color:color-mix(in srgb, var(--type-color, #2D6B95) 30%, var(--border));
  }
}
.card-browse:active { transform:scale(.985); }
@media (prefers-reduced-motion:reduce) { .card-browse:active { transform:none; } }

/* Neutralise legacy padding + stripe that bleeds onto the new shells.
   Specificity strategy: must beat app-shell-tail.css's 0,1,0 and 0,2,0 !important rules.
   Two-class (0,2,0) beats 0,1,0; three-class (0,3,0) beats 0,2,0 attribute rule. */
.card-proposed.recall-card,
.card-proposed.saq-card-face,
.card-proposed.axiom,
.card-browse.recall-card,
.card-browse.saq-card-face,
.card-browse.axiom {
  padding:0 !important;
  padding-top:0 !important;
  padding-right:0 !important;
  padding-bottom:0 !important;
  padding-left:0 !important;
  border-left:1px solid var(--border) !important;
}
/* pharma needs 0,3,0 to beat `.pharma-card[data-mode="library"]{padding-top:40px !important}` */
.card-proposed.recall-card.pharma-card,
.card-browse.recall-card.pharma-card {
  padding:0 !important;
  padding-top:0 !important;
  padding-right:0 !important;
  padding-bottom:0 !important;
  padding-left:0 !important;
  border-left:1px solid var(--border) !important;
}
html.dark .card-proposed.recall-card,
html.dark .card-proposed.saq-card-face,
html.dark .card-proposed.axiom,
html.dark .card-browse.recall-card,
html.dark .card-browse.saq-card-face,
html.dark .card-browse.axiom,
html.dark .card-proposed.recall-card.pharma-card,
html.dark .card-browse.recall-card.pharma-card {
  border-left-color:var(--border) !important;
}

/* ─── BANDS (Today .p-band / Library .b-band) ────────────────────────── */
.card-proposed .p-band,
.card-browse .b-band {
  display:flex;align-items:center;gap:7px;
  flex-shrink:0;
  background:var(--type-color, #2D6B95);
  border-bottom:1px solid var(--type-color, #2D6B95);
}
.card-proposed .p-band { padding:9px 12px 8px; }
.card-browse   .b-band { padding:8px 11px 7px; }
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed .p-band,
  .card-browse .b-band {
    background:color-mix(in srgb, var(--type-color, #2D6B95) 16%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--type-color, #2D6B95) 22%, var(--border));
  }
}

/* Glyph */
.p-band-glyph,
.b-band-glyph {
  display:inline-flex;align-items:center;flex-shrink:0;
  color:color-mix(in srgb, var(--type-color, #2D6B95) 80%, var(--text));
}
.p-band-glyph { width:17px;height:17px; }
.b-band-glyph { width:15px;height:15px; }

/* Kicker — quiet metadata, no underline at rest */
.p-band-kicker,
.b-band-kicker {
  font-size:10px;font-weight:420;letter-spacing:.015em;
  color:color-mix(in srgb, var(--type-color, #2D6B95) 30%, var(--text-muted));
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.p-band-kicker .kicker-meta,
.b-band-kicker .kicker-meta {
  color:color-mix(in srgb, var(--type-color, #2D6B95) 22%, var(--text-muted));
  font-weight:400;
}
.p-band-kicker .kicker-link,
.b-band-kicker .kicker-link {
  color:inherit;
  /* FIX-3: Lock font-size so legacy .card__breadcrumb{font-size:13px} (0,1,0) can't
     inflate the kicker from 10px → 13px. The kicker is a quiet 10px metadata line;
     rendering at 13px makes the link too wide and forces premature ellipsis. */
  font-size:10px;
  text-decoration:none;cursor:pointer;border-bottom:none;
  transition:color .12s;
}
.p-band-kicker .kicker-link:hover,
.b-band-kicker .kicker-link:hover {
  color:color-mix(in srgb, var(--type-color, #2D6B95) 60%, var(--text));
}
html.dark .p-band-kicker .kicker-link,
html.dark .b-band-kicker .kicker-link { color:inherit; }
html.dark .p-band-kicker .kicker-link:hover,
html.dark .b-band-kicker .kicker-link:hover {
  color:color-mix(in srgb, var(--type-color, #79B9DD) 70%, var(--text));
}

/* SAQ kicker truncation fix (Step 4).
   The SAQ kicker has the structure:
     <span class="kicker-meta kicker-meta--saq">2021.1·Q18 · 57% · </span>
     <a class="kicker-link">D10 · Renal Failure</a>
   Without flex, the whole kicker is one line truncated from the right, cutting off
   the node name entirely.  Flex layout gives the link the remaining space with its
   own ellipsis, while the meta prefix can flex-shrink when space is tight.
   Only applies to SAQ type (kicker-meta--saq selector) — recall/pharma/axiom kickers
   are unaffected (they don't have kicker-meta--saq).
   Note: we scope to .type-saq so the specificity is 0,2,0 — same as other kicker rules. */
.card-proposed.type-saq .p-band-kicker,
.card-browse.type-saq   .b-band-kicker {
  display:flex;align-items:center;gap:0;
}
.card-proposed.type-saq .p-band-kicker .kicker-meta--saq,
.card-browse.type-saq   .b-band-kicker .kicker-meta--saq {
  flex-shrink:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  /* Leave some minimum so the year·Q meta is always shown when space allows */
  max-width:60%;
}
.card-proposed.type-saq .p-band-kicker .kicker-link,
.card-browse.type-saq   .b-band-kicker .kicker-link {
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* Band-meta: compact 5px dots + kebab */
.p-band-meta,
.b-band-meta {
  display:flex;align-items:center;gap:4px;flex-shrink:0;
}
.card-proposed .p-band-meta .card__rail,
.card-browse   .b-band-meta .card__rail {
  width:auto;min-width:0;height:22px;
  display:flex;align-items:center;justify-content:flex-end;flex-shrink:0;position:relative;
}
/* Compact dots — match the 5px buildDots() style */
.p-band-dot,
.b-band-dot {
  width:5px;height:5px;border-radius:50%;flex-shrink:0;
  background:color-mix(in srgb, var(--type-color, #2D6B95) 35%, var(--border));
  opacity:.65;
}
.p-band-dot.grade-honed,    .b-band-dot.grade-honed    { background:var(--grade-honed);    opacity:1; }
.p-band-dot.grade-missed,   .b-band-dot.grade-missed   { background:var(--grade-missed);   opacity:1; }
.p-band-dot.grade-mastered, .b-band-dot.grade-mastered { background:var(--grade-mastered); opacity:1; }
.p-band-dot.grade-hazy,     .b-band-dot.grade-hazy     { background:var(--grade-hazy);     opacity:1; }
.p-band-dot.current,        .b-band-dot.current        { background:var(--type-color, #2D6B95); opacity:1; }

/* Compact kebab button */
.card-proposed .p-band-meta .card-options-btn,
.card-browse   .b-band-meta .card-options-btn {
  /* position:relative + z-index lifts the kebab above the adjacent meta content
     that otherwise overlaps ~4.5px of its right edge — without this the effective
     hit area is ~19.5px wide and axe target-size (WCAG 2.5.8) flags it as
     "partially obscured". flex:0 0 auto stops it shrinking below the 24px min. */
  position:relative;top:auto;right:auto;opacity:1;width:auto;height:auto;z-index:5;
  flex:0 0 auto;
  appearance:none;border:0;background:transparent;cursor:pointer;
  color:color-mix(in srgb, var(--type-color, #2D6B95) 70%, var(--text-faint));
  padding:0 2px;line-height:1;min-height:24px;min-width:24px;
  display:inline-flex;align-items:center;justify-content:center;
}

/* ─── HERO PROMPT (Today pre-reveal) ─────────────────────────────────── */
/* BUG-fix: no header↔prompt gap — hero prompt is direct child of flex column */
.card-proposed .p-prompt {
  padding:10px 14px 14px;
  font-size:17px;font-weight:560;line-height:1.45;
  color:var(--text);letter-spacing:-.01em;flex:1;
}

/* ─── REVEAL ROW + BUTTON ─────────────────────────────────────────────── */
.card-proposed .p-reveal-row {
  padding:10px 10px 12px;
  margin-top:auto;
}
.card-proposed .p-reveal-btn {
  appearance:none;display:block;width:100%;border-radius:10px;min-height:40px;
  padding:0 10px;font:inherit;font-size:13px;font-weight:700;cursor:pointer;
  text-align:center;letter-spacing:.01em;
  color:var(--type-reveal-label, var(--recall-reveal-label));
  background:var(--surface-elevated);
  border:1.5px solid var(--border);
  transition:transform .1s var(--ease-out), filter .1s;
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed .p-reveal-btn {
    background:color-mix(in srgb, var(--type-color, #2D6B95) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--type-color, #2D6B95) 30%, var(--border));
  }
}
/* .card-proposed .p-reveal-btn:active — REMOVED, consolidated into .mo-press
   (motion/motion.css) applied in card/reveal.js (today surface). */

/* ─── DEMOTED PROMPT (Today post-reveal / Library always-shown) ─────── */
.card-proposed .p-prompt-collapsed,
.card-proposed .p-prompt-saq-revealed,
.card-browse   .b-prompt {
  padding:8px 14px;
  font-size:12.5px;font-weight:450;line-height:1.45;
  color:var(--text);letter-spacing:-.005em;
  border-bottom:1px solid var(--border);
}
/* BUG-B: very subtle tint — hairline border provides the seam */
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed .p-prompt-collapsed,
  .card-proposed .p-prompt-saq-revealed,
  .card-browse   .b-prompt {
    background:color-mix(in srgb, var(--surface-elevated) 92%, var(--bg, #EFEBE0));
  }
}

/* ─── HAIRLINE SEAM ───────────────────────────────────────────────────── */
.card-proposed .p-seam,
.card-browse   .b-seam {
  display:flex;align-items:center;padding:0 14px;margin:0;
}
.card-browse .b-seam { padding:0 12px; }
.p-seam-rule,
.b-seam-rule { flex:1;height:1px;background:var(--border); }

/* ─── ANSWER PANELS ───────────────────────────────────────────────────── */
/* BUG-B fix: answer inherits card surface — no separate fill */
.card-proposed .p-answer { padding:10px 14px 12px; }
.card-browse   .b-answer { padding:7px 12px 9px; }
.card-proposed .p-answer-text { font-size:14px;line-height:1.6;color:var(--text); }
.card-proposed .p-answer-text strong { font-weight:700;color:var(--text); }
.card-browse   .b-answer-text { font-size:13.5px;line-height:1.55;color:var(--text); }
.card-browse   .b-answer-text strong { font-weight:700;color:var(--text); }

/* Axiom monospace */
.card-proposed.type-axiom .p-answer-text,
.card-browse.type-axiom   .b-answer-text {
  font-family:"SF Mono","Fira Code",Consolas,"Liberation Mono",monospace;
  font-size:13px;font-variant-numeric:tabular-nums;line-height:1.75;
}

/* ─── ENRICHMENT CALLOUTS ─────────────────────────────────────────────── */
.card-proposed .p-enrichment {
  margin:4px 10px 8px;border-radius:var(--radius-sm);padding:10px 12px;
  background:var(--surface-elevated);border:1px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed .p-enrichment {
    background:color-mix(in srgb, var(--type-color, #2D6B95) 14%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--type-color, #2D6B95) 20%, var(--border));
  }
}
.card-browse .b-enrichment {
  margin:2px 9px 6px;border-radius:var(--radius-sm);padding:7px 10px;
  background:var(--surface-elevated);border:1px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-browse .b-enrichment {
    background:color-mix(in srgb, var(--type-color, #2D6B95) 10%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--type-color, #2D6B95) 18%, var(--border));
  }
}
.p-enrichment-label,
.b-enrichment-label {
  font-size:9px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--type-deep, #2D6B95);margin-bottom:5px;
}
.p-enrichment-text,
.b-enrichment-text { font-size:13px;line-height:1.55;color:var(--text-muted); }
.b-enrichment-text { font-size:12px;line-height:1.5; }

/* ─── SAQ TABS ────────────────────────────────────────────────────────── */
.card-proposed .fc-tab-bar,
.card-browse   .fc-tab-bar {
  display:flex;gap:2px;padding:7px 10px 0;justify-content:center;
  border-bottom:1px solid var(--border);
  background:var(--surface, #F5F1E6);
  flex-shrink:0;
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed .fc-tab-bar,
  .card-browse   .fc-tab-bar {
    background:color-mix(in srgb, var(--type-saq, #C44484) 4%, var(--surface));
  }
}
.card-browse .fc-tab-bar { padding:5px 10px 0; }
.card-proposed .fc-tab,
.card-browse   .fc-tab {
  appearance:none;border:none;background:transparent;font:inherit;
  font-size:10.5px;font-weight:700;color:var(--text-faint);
  padding:5px 10px 7px;cursor:pointer;border-bottom:2px solid transparent;
  margin-bottom:-1px;letter-spacing:.02em;
  transition:color .15s, border-color .15s;white-space:nowrap;
}
.card-browse .fc-tab { font-size:10px;padding:4px 9px 6px; }
.card-proposed .fc-tab.active,
.card-browse   .fc-tab.active {
  color:var(--type-saq, #C44484);
  border-bottom-color:var(--type-saq, #C44484);
}
html.dark .card-proposed .fc-tab.active,
html.dark .card-browse   .fc-tab.active {
  color:var(--type-saq, #DD4490);
  border-bottom-color:var(--type-saq, #DD4490);
}
.card-proposed .fc-tab-panel,
.card-browse   .fc-tab-panel {
  padding:10px 12px 12px;font-size:13px;line-height:1.6;color:var(--text);
  overflow:visible;max-height:none;
}
.card-browse .fc-tab-panel { padding:8px 12px 10px;font-size:12.5px;line-height:1.55; }
.card-proposed .fc-tab-panel strong,
.card-browse   .fc-tab-panel strong { font-weight:700;color:var(--text); }
.card-proposed .fc-tab-panel p,
.card-browse   .fc-tab-panel p { margin:0 0 8px; }
.card-proposed .fc-tab-panel p:last-child,
.card-browse   .fc-tab-panel p:last-child { margin-bottom:0; }

/* SAQ fc-callout inside grid card */
.card-proposed .fc-callout,
.card-browse   .fc-callout {
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-sm);padding:9px 11px;margin:5px 0;
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed .fc-callout,
  .card-browse   .fc-callout {
    background:color-mix(in srgb, var(--type-saq, #C44484) 10%, var(--surface));
    border-color:color-mix(in srgb, var(--type-saq, #C44484) 20%, var(--border));
  }
}

/* SAQ grade row hidden in library/browse */
.card-browse .recall-actions,
.card-browse .saq-card-cf-footer { display:none !important; }

/* ─── GRADE ZONE (Today only) ─────────────────────────────────────────── */
/* .recall-actions is position:relative wrapper for miss-tag inset:0 */
.card-proposed .recall-actions { position:relative; }

/* Inverted-T grade row */
.card-proposed .recall-actions .post-reveal {
  display:grid;
  grid-template-columns:1fr 1fr;
  grid-template-rows:auto auto;
  gap:5px;
  padding:10px 10px 12px;
  height:auto;width:100%;box-sizing:border-box;
}
.card-proposed .recall-actions .r-grade--mastered { grid-column:1/-1;grid-row:1;border-radius:10px; }
.card-proposed .recall-actions .r-grade--missed   { grid-column:1;   grid-row:2;border-radius:10px; }
.card-proposed .recall-actions .r-grade--honed    { grid-column:2;   grid-row:2;border-radius:10px; }

/* Grade button recipe (tint+outline+deep-label) */
.card-proposed .recall-actions .r-grade {
  appearance:none;border-radius:10px;min-height:40px;padding:0 10px;
  font:inherit;font-size:12.5px;font-weight:700;cursor:pointer;text-align:center;
  display:flex;align-items:center;justify-content:center;letter-spacing:.01em;
  transition:transform .1s var(--ease-out), filter .1s;
}
/* today .r-grade:active — REMOVED, consolidated into .mo-press (motion/motion.css)
   applied per grade button in card/grade.js (today surface = base press). */
.card-proposed .recall-actions .r-grade--mastered {
  color:var(--grade-mastered-label);
  background:var(--surface-elevated);border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed .recall-actions .r-grade--mastered {
    background:color-mix(in srgb, var(--grade-mastered) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-mastered) 30%, var(--border));
  }
}
.card-proposed .recall-actions .r-grade--missed {
  color:var(--grade-missed-label);
  background:var(--surface-elevated);border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed .recall-actions .r-grade--missed {
    background:color-mix(in srgb, var(--grade-missed) 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border));
  }
}
html.dark .card-proposed .recall-actions .r-grade--missed {
  background:var(--surface-elevated);border-color:var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  html.dark .card-proposed .recall-actions .r-grade--missed {
    background:color-mix(in srgb, var(--grade-missed) 14%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-missed) 35%, var(--border));
  }
}
.card-proposed .recall-actions .r-grade--honed {
  color:var(--grade-honed-label);
  background:var(--surface-elevated);border:1.5px solid var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed .recall-actions .r-grade--honed {
    background:color-mix(in srgb, var(--grade-honed) 10%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-honed) 28%, var(--border));
  }
}
html.dark .card-proposed .recall-actions .r-grade--honed {
  background:var(--surface-elevated);border-color:var(--border);
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  html.dark .card-proposed .recall-actions .r-grade--honed {
    background:color-mix(in srgb, #22c55e 12%, var(--surface-elevated));
    border-color:color-mix(in srgb, #22c55e 30%, var(--border));
  }
}

/* ─── MISS-TAG OVERLAY (card-proposed context) ────────────────────────── */
/* In-flow replacement pattern: overlay lives in the normal block flow of
   .recall-actions alongside .post-reveal. When .tag-open:
     • .post-reveal is hidden (display:none !important beats all legacy rules)
     • overlay is shown as a block (display:block !important)
   This avoids the absolute-inset / height-collapse problem when .post-reveal
   disappears, AND beats the legacy .recall-card.tag-open/.fc-card.tag-open
   rules (both 0,2,0) via 0,3,0 specificity + !important.

   Default state: hidden (display:none wins over legacy display:flex from
   .miss-tag-overlay base rule at 0,1,0). */
.card-proposed .recall-actions .miss-tag-overlay {
  display:none !important;
  pointer-events:none;
  /* NOT position:absolute — in-flow so it occupies the grade-zone footprint */
  position:static !important;
  background:var(--surface-elevated);
  border-top:1px solid var(--border);
  z-index:auto;
  height:auto !important;
  width:100%;
  box-sizing:border-box;
  overflow:visible;
}
/* tag-open: show overlay, hide grade buttons — both !important to beat legacy rules */
.card-proposed.tag-open .recall-actions .miss-tag-overlay {
  display:block !important;
  pointer-events:auto;
}
/* FIX-1a: hide .post-reveal when miss-tag open — beats:
     legacy .recall-card.tag-open .post-reveal{display:none} (0,2,0)
     legacy .fc-card.tag-open .post-reveal{display:none} (0,2,0)
     card.css .card-proposed.revealed:not([data-graded]) .recall-actions .post-reveal{display:grid} (0,4,0)
   We use 0,3,0 + !important which wins over all. */
.card-proposed.tag-open .recall-actions .post-reveal { display:none !important; }

/* Miss-tag header: in-flow, appears above the miss-tag grid inside the overlay.
   Since the overlay is now in-flow (not absolute), the header renders as the
   first block inside the overlay — no floats-above-overlay pattern needed. */
.card-proposed .recall-actions .miss-tag-overlay .miss-tag-header {
  position:static;
  display:flex;align-items:center;justify-content:center;gap:5px;
  min-height:30px;margin:8px 10px 4px;padding:4px 10px;
  border:1px solid var(--border);border-radius:8px;
  background:var(--surface-elevated);
  font-size:var(--font-size-sm,12px);font-weight:700;color:var(--grade-missed-label);
  white-space:nowrap;
}
.card-proposed .recall-actions .miss-tag-overlay .miss-tag-header--back {
  position:static;
  display:flex;align-items:center;justify-content:flex-start;gap:8px;
  min-height:34px;margin:8px 10px 0;padding:0 12px;
  border:1.5px solid var(--border-strong);border-radius:10px;
  background:var(--surface-elevated);color:var(--grade-missed-label);
  font-size:12.5px;font-weight:700;letter-spacing:.01em;white-space:nowrap;
  cursor:pointer;
}
.card-proposed .recall-actions .miss-tag-overlay .miss-tag-header--back .miss-tag-back {
  flex-shrink:0;color:var(--text);font-weight:800;
}
.card-proposed .recall-actions .miss-tag-overlay .miss-tag-header--back .miss-tag-header-label {
  flex:1;text-align:center;color:var(--grade-missed-label);font-weight:700;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* Miss-tag grid: inverted-T footprint matching .post-reveal */
.card-proposed .recall-actions .miss-tag-overlay .miss-tag-grid {
  display:grid !important;
  grid-template-columns:1fr 1fr;
  grid-template-rows:auto auto;
  gap:5px;
  padding:10px 10px 12px;
  height:auto;  /* in-flow: no fixed height, let buttons size naturally */
  align-content:start;
  box-sizing:border-box;flex:none;
}
/* Tag placement — Hazy top (= Mastered), Blank BL (= Missed), Mixed BR (= Honed) */
.card-proposed .recall-actions .miss-tag-overlay .miss-tag-grid [data-tag="hazy"]  { grid-column:1/-1;grid-row:1;border-radius:10px; }
.card-proposed .recall-actions .miss-tag-overlay .miss-tag-grid [data-tag="blank"] { grid-column:1;   grid-row:2;border-radius:10px; }
.card-proposed .recall-actions .miss-tag-overlay .miss-tag-grid [data-tag="mixed"] { grid-column:2;   grid-row:2;border-radius:10px; }

/* Button base */
.card-proposed .recall-actions .miss-tag-btn {
  min-height:40px;padding:0 10px;border-radius:10px;box-sizing:border-box;
  display:flex;align-items:center;justify-content:center;gap:6px;
  font:inherit;font-size:13px;font-weight:700;letter-spacing:.01em;
}
/* Per-tag colours (0,3,0 specificity beats legacy 0,2,0) */
.card-proposed .recall-actions .miss-tag-grid [data-tag="hazy"],
.card-proposed .recall-actions .miss-tag-grid [data-tag="mixed"] {
  color:#7A5A00 !important;
  border:1.5px solid var(--border) !important;
  background:var(--surface) !important;
}
html.dark .card-proposed .recall-actions .miss-tag-grid [data-tag="hazy"],
html.dark .card-proposed .recall-actions .miss-tag-grid [data-tag="mixed"] {
  color:#FBBF24 !important;
}
.card-proposed .recall-actions .miss-tag-grid [data-tag="blank"] {
  color:var(--grade-blank-label) !important;
  border:1.5px solid var(--border) !important;
  background:var(--surface) !important;
}
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed .recall-actions .miss-tag-grid [data-tag="hazy"],
  .card-proposed .recall-actions .miss-tag-grid [data-tag="mixed"] {
    background:color-mix(in srgb, #F0B429 16%, var(--surface)) !important;
    border-color:color-mix(in srgb, #F0B429 36%, var(--border)) !important;
  }
  .card-proposed .recall-actions .miss-tag-grid [data-tag="blank"] {
    background:color-mix(in srgb, var(--grade-missed) 12%, var(--surface)) !important;
    border-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border)) !important;
  }
}

/* Band flip on grade — mirrors cinema .fc-card--marked-* */
@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed[data-graded="mastered"] .p-band {
    background:color-mix(in srgb, var(--grade-mastered) 22%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--grade-mastered) 30%, var(--border));
  }
  .card-proposed[data-graded="honed"] .p-band {
    background:color-mix(in srgb, var(--grade-honed) 22%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--grade-honed) 30%, var(--border));
  }
  .card-proposed[data-graded="missed"] .p-band,
  .card-proposed[data-graded="hazy"]   .p-band {
    background:color-mix(in srgb, var(--grade-missed) 22%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--grade-missed) 30%, var(--border));
  }
  /* NEUTRAL "graded today" — exact grade unknown (server flag only). */
  .card-proposed[data-graded="graded"] .p-band {
    background:color-mix(in srgb, var(--text-faint) 16%, var(--surface-elevated));
    border-bottom-color:color-mix(in srgb, var(--text-faint) 26%, var(--border));
  }
}

/* ─── UNDO CHIP (study-card__chip) ────────────────────────────────────── */
/* Double-grade fix: chip REPLACES grade row via [data-graded] → hide .post-reveal.
   CSS drives the show/hide; grade.js sets data-graded. */
.card-proposed .study-card__chip { display:none; }
.card-proposed[data-graded] .study-card__chip {
  display:flex;align-items:center;justify-content:center;
  margin:0 10px 12px;padding:9px 12px;width:calc(100% - 20px);
  appearance:none;border-radius:10px;min-height:40px;
  font:inherit;font-size:12px;font-weight:700;cursor:pointer;letter-spacing:.01em;
  background:var(--surface-elevated);
  border:1.5px solid var(--border);
  color:var(--text-muted);gap:6px;
}
/* Hide post-reveal grade buttons when graded (undo chip takes their place) */
.card-proposed[data-graded] .recall-actions .post-reveal { display:none !important; }
.card-proposed[data-graded] .recall-actions .miss-tag-overlay { display:none !important; }

@supports (background:color-mix(in srgb,red 10%,blue)) {
  .card-proposed[data-graded="mastered"] .study-card__chip {
    background:color-mix(in srgb, var(--grade-mastered) 14%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-mastered) 35%, var(--border));
    color:var(--grade-mastered-label);
  }
  .card-proposed[data-graded="honed"] .study-card__chip {
    background:color-mix(in srgb, var(--grade-honed) 10%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-honed) 28%, var(--border));
    color:var(--grade-honed-label);
  }
  .card-proposed[data-graded="missed"] .study-card__chip,
  .card-proposed[data-graded="hazy"]   .study-card__chip {
    background:color-mix(in srgb, var(--grade-missed) 14%, var(--surface-elevated));
    border-color:color-mix(in srgb, var(--grade-missed) 35%, var(--border));
    color:var(--grade-missed-label);
  }
}

/* ─── REVEAL VISIBILITY RULES ─────────────────────────────────────────── */
/* Pre-reveal: hide post-reveal sections */
.card-proposed .p-prompt-collapsed,
.card-proposed .p-prompt-saq-revealed,
.card-proposed .p-seam,
.card-proposed .p-answer,
.card-proposed .p-enrichment,
.card-proposed .fc-tab-bar,
.card-proposed .fc-tab-panel,
.card-proposed .recall-actions .post-reveal { display:none; }

/* Revealed (non-SAQ): show post-reveal sections, hide hero + reveal row */
.card-proposed.revealed .p-prompt-collapsed,
.card-proposed.revealed .p-seam,
.card-proposed.revealed .p-answer,
.card-proposed.revealed .p-enrichment { display:block; }
.card-proposed.revealed:not([data-graded]) .recall-actions .post-reveal { display:grid; }
.card-proposed.revealed .p-prompt { display:none; }
.card-proposed.revealed .p-reveal-row { display:none; }

/* SAQ revealed: show tabs + panels (but not the non-SAQ collapsed prompt) */
.card-proposed.type-saq.revealed .p-prompt-saq-revealed { display:block; }
.card-proposed.type-saq.revealed .fc-tab-bar { display:flex; }
/* P4-FIX: SAQ tab panels ONLY shown post-reveal. JS uses hidden attribute for active tab.
   The pre-reveal hide rule above (.card-proposed .fc-tab-panel { display:none }) is
   correct — this revealed override restores them; [hidden] hides inactive tabs. */
.card-proposed.type-saq.revealed .fc-tab-panel { display:block; }
.card-proposed.type-saq.revealed .fc-tab-panel[hidden] { display:none; }

/* Library (browse): answer sections always visible */
.card-browse .b-answer,
.card-browse .b-enrichment,
.card-browse .b-seam { display:block; }
.card-browse .fc-tab-bar { display:flex; }
.card-browse .fc-tab-panel { display:block; }
.card-browse .fc-tab-panel[hidden] { display:none; }

/* ─── REVEAL ANIMATION ────────────────────────────────────────────────── */
@keyframes gridRevealIn { from{opacity:0;transform:translateY(5px)} to{opacity:1;transform:none} }
@media (prefers-reduced-motion:no-preference) {
  .card-proposed.revealed .p-prompt-collapsed,
  .card-proposed.revealed .p-prompt-saq-revealed,
  .card-proposed.revealed .p-seam,
  .card-proposed.revealed .p-answer,
  .card-proposed.revealed .p-enrichment,
  .card-proposed.revealed .fc-tab-bar,
  .card-proposed.revealed .recall-actions {
    animation:gridRevealIn .2s var(--ease-spring) both;
  }
}

/* ─── P5: CALLOUT STYLING IN GRID CARD ANSWER/TAB CONTAINERS ─────────── */
/* app-shell-head-pre-planner.css scopes callout blockquote rules to
   .recall-answer/.fc-answer/.card-body etc — but NOT to .fc-tab-panel,
   .p-answer-text, or .b-answer-text (the grid card answer containers).
   Mirror the base chrome + typed variants here so classifyCallouts()
   output renders correctly inside grid cards. */
.card-proposed .fc-tab-panel blockquote.callout,
.card-browse   .fc-tab-panel blockquote.callout,
.card-proposed .p-answer-text blockquote.callout,
.card-browse   .b-answer-text blockquote.callout {
  position:relative;
  margin:.5em 0;padding:7px 11px 7px 36px;
  border-left:4px solid var(--accent);
  background:color-mix(in srgb,var(--accent) 5%,transparent);
  color:var(--text);font-style:normal;
  border-radius:0 4px 4px 0;
}
.card-proposed .fc-tab-panel blockquote.callout::before,
.card-browse   .fc-tab-panel blockquote.callout::before,
.card-proposed .p-answer-text blockquote.callout::before,
.card-browse   .b-answer-text blockquote.callout::before {
  content:'';position:absolute;left:10px;top:9px;width:16px;height:16px;
  background-position:center;background-repeat:no-repeat;background-size:contain;
}
.card-proposed .fc-tab-panel blockquote.callout > *:first-child,
.card-browse   .fc-tab-panel blockquote.callout > *:first-child,
.card-proposed .p-answer-text blockquote.callout > *:first-child,
.card-browse   .b-answer-text blockquote.callout > *:first-child { margin-top:0; }
.card-proposed .fc-tab-panel blockquote.callout > *:last-child,
.card-browse   .fc-tab-panel blockquote.callout > *:last-child,
.card-proposed .p-answer-text blockquote.callout > *:last-child,
.card-browse   .b-answer-text blockquote.callout > *:last-child { margin-bottom:0; }

/* callout-examiner — peri left-bar, no icon, reduced left-padding */
.card-proposed .fc-tab-panel blockquote.callout-examiner,
.card-browse   .fc-tab-panel blockquote.callout-examiner,
.card-proposed .p-answer-text blockquote.callout-examiner,
.card-browse   .b-answer-text blockquote.callout-examiner {
  border-left-color:var(--peri,#7c5cb8);
  background:color-mix(in srgb,var(--peri,#7c5cb8) 6%,transparent);
  padding-left:13px;
}
.card-proposed .fc-tab-panel blockquote.callout-examiner::before,
.card-browse   .fc-tab-panel blockquote.callout-examiner::before,
.card-proposed .p-answer-text blockquote.callout-examiner::before,
.card-browse   .b-answer-text blockquote.callout-examiner::before { content:none; }

/* callout-key — honey left-bar, lightbulb icon */
.card-proposed .fc-tab-panel blockquote.callout-key,
.card-browse   .fc-tab-panel blockquote.callout-key,
.card-proposed .p-answer-text blockquote.callout-key,
.card-browse   .b-answer-text blockquote.callout-key {
  border-left-color:var(--honey,#d4922b);
  background:color-mix(in srgb,var(--honey,#d4922b) 7%,transparent);
}
.card-proposed .fc-tab-panel blockquote.callout-key::before,
.card-browse   .fc-tab-panel blockquote.callout-key::before,
.card-proposed .p-answer-text blockquote.callout-key::before,
.card-browse   .b-answer-text blockquote.callout-key::before {
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23d4922b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5'/><path d='M9 18h6'/><path d='M10 22h4'/></svg>");
}

/* callout-safety / callout-definition — sage left-bar, book icon */
.card-proposed .fc-tab-panel blockquote.callout-safety,
.card-browse   .fc-tab-panel blockquote.callout-safety,
.card-proposed .p-answer-text blockquote.callout-safety,
.card-browse   .b-answer-text blockquote.callout-safety,
.card-proposed .fc-tab-panel blockquote.callout-definition,
.card-browse   .fc-tab-panel blockquote.callout-definition,
.card-proposed .p-answer-text blockquote.callout-definition,
.card-browse   .b-answer-text blockquote.callout-definition {
  border-left-color:var(--sage,#5e8b6c);
  background:color-mix(in srgb,var(--sage,#5e8b6c) 6%,transparent);
}

/* callout-pitfall — coral left-bar, warning icon */
.card-proposed .fc-tab-panel blockquote.callout-pitfall,
.card-browse   .fc-tab-panel blockquote.callout-pitfall,
.card-proposed .p-answer-text blockquote.callout-pitfall,
.card-browse   .b-answer-text blockquote.callout-pitfall {
  border-left-color:var(--coral,#e05a4b);
  background:color-mix(in srgb,var(--coral,#e05a4b) 6%,transparent);
}

/* callout-mnemonic / callout-pearl — violet left-bar */
.card-proposed .fc-tab-panel blockquote.callout-mnemonic,
.card-browse   .fc-tab-panel blockquote.callout-mnemonic,
.card-proposed .p-answer-text blockquote.callout-mnemonic,
.card-browse   .b-answer-text blockquote.callout-mnemonic,
.card-proposed .fc-tab-panel blockquote.callout-pearl,
.card-browse   .fc-tab-panel blockquote.callout-pearl,
.card-proposed .p-answer-text blockquote.callout-pearl,
.card-browse   .b-answer-text blockquote.callout-pearl {
  border-left-color:var(--violet,#8B5CF6);
  background:color-mix(in srgb,var(--violet,#8B5CF6) 6%,transparent);
}

/* callout-equation — recall/blue left-bar */
.card-proposed .fc-tab-panel blockquote.callout-equation,
.card-browse   .fc-tab-panel blockquote.callout-equation,
.card-proposed .p-answer-text blockquote.callout-equation,
.card-browse   .b-answer-text blockquote.callout-equation {
  border-left-color:var(--recall,#2D6B95);
  background:color-mix(in srgb,var(--recall,#2D6B95) 6%,transparent);
}

/* callout-mechanism / callout-heuristic — saltbush left-bar */
.card-proposed .fc-tab-panel blockquote.callout-mechanism,
.card-browse   .fc-tab-panel blockquote.callout-mechanism,
.card-proposed .p-answer-text blockquote.callout-mechanism,
.card-browse   .b-answer-text blockquote.callout-mechanism,
.card-proposed .fc-tab-panel blockquote.callout-heuristic,
.card-browse   .fc-tab-panel blockquote.callout-heuristic,
.card-proposed .p-answer-text blockquote.callout-heuristic,
.card-browse   .b-answer-text blockquote.callout-heuristic {
  border-left-color:var(--saltbush,#C4CAD0);
  background:color-mix(in srgb,var(--saltbush,#C4CAD0) 8%,transparent);
}

/* pwa/ribbon/ribbon.css — ribbon widget styles (2-row band ribbon, v2).
   The LOCKED design from MOCKUPS/card-refresh-v2.html (.rbn-* section):
     ROW 1 .rbn-band  = tinted header band — glyph + kicker + 5-dot rail + kebab.
                        Tint = card TYPE colour (browse) OR last-GRADE colour (graded).
     ROW 2 .rbn-body  = card-surface body — stem + body-right (last-grade pill + due).
   No left vertical identity stripe (removed — antipattern).
   Shared CSS that is NOT ribbon-specific (haul modal, ribbon-section/head,
   ribbon-kebab, study-ribbon-summary) stays in app-shell-head-pre-planner.css. */

/* =====================================================
   Legacy-stripe reset
   The wrap carries a `ribbon-card` co-class (for curriculum.js / select
   helper compat). Neutralise the old left-stripe / single-row rules so they
   do not bleed into the v2 band layout.
   ===================================================== */
.ribbon-wrap.ribbon-card{
  border:1px solid var(--border);
  border-left:1px solid var(--border);
  flex-direction:column;
  padding:0;
}
.ribbon-wrap.ribbon-card[data-is-pearl]::before{content:none}

/* =====================================================
   Wrapper (outer card shell)
   ===================================================== */
.ribbon-wrap{
  position:relative;
  border-radius:8px;border:1px solid var(--border);
  overflow:hidden;
  background:var(--surface-elevated);
  font-family:inherit;
  box-shadow:0 1px 4px rgba(0,0,0,.06);
  cursor:pointer;
  transition:border-color .14s,box-shadow .14s;
  width:100%;text-align:left;
  -webkit-touch-callout:none;
}
.ribbon-wrap:hover{
  border-color:color-mix(in srgb, var(--rbn-tint-color, var(--border-strong)) 40%, var(--border));
  box-shadow:0 3px 10px rgba(0,0,0,.10);
}
.ribbon-wrap:active{transform:scale(.993)}
@media (prefers-reduced-motion:reduce){.ribbon-wrap:active{transform:none}}
.reduced-motion .ribbon-wrap:active{transform:none!important}
.ribbon-wrap.expanded{
  border-color:color-mix(in srgb, var(--rbn-tint-color, var(--border-strong)) 55%, var(--border));
  box-shadow:0 4px 14px rgba(0,0,0,.12);
}

/* Primary-action trigger — keyboard/AT entry point covering band+body. */
/* z-index:0 keeps it below the kebab + kicker link (promoted to z-index:1). */
.ribbon-card__trigger{
  position:absolute;inset:0;
  background:transparent;border:0;padding:0;margin:0;
  cursor:pointer;z-index:0;border-radius:8px;
}
.ribbon-card__trigger:focus-visible{outline:none}
.ribbon-wrap:has(.ribbon-card__trigger:focus-visible){outline:2px solid var(--sage);outline-offset:1px}
.ribbon-wrap:focus-visible{outline:2px solid var(--sage);outline-offset:1px}
.rbn-more{position:relative;z-index:1}

/* =====================================================
   ROW 1: tinted header band
   ===================================================== */
.rbn-band{
  display:flex;align-items:center;gap:6px;
  min-height:28px;padding:5px 8px 5px 9px;
  position:relative;
  background:color-mix(in srgb, var(--rbn-tint-color, var(--border-strong)) 16%, var(--surface-elevated));
  border-bottom:1px solid color-mix(in srgb, var(--rbn-tint-color, var(--border-strong)) 22%, var(--border));
}

/* Bare type icon (18px) — tint-coloured. Pearl → sparkle (saltbush). */
.rbn-band-glyph{
  display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;
  color:color-mix(in srgb, var(--rbn-tint-color, var(--border-strong)) 80%, var(--text));
  width:18px;height:18px;
}
.rbn-band-glyph svg{width:18px;height:18px;display:block}
.rbn-band-glyph.is-pearl{color:var(--saltbush-deep,var(--saltbush))}

/* Kicker: [metadata ·] node code · node name — one line, EXTRA-SMALL 8px. */
/* The link is the only right-growing element so the node NAME truncates. */
.rbn-band-kicker{
  display:flex;align-items:center;min-width:0;flex:1;
  font-size:8px;font-weight:600;letter-spacing:.02em;
  color:color-mix(in srgb, var(--rbn-tint-color, var(--border-strong)) 45%, var(--text));
  overflow:hidden;white-space:nowrap;
}
.ribbon-wrap.rbn-new .rbn-band-kicker{color:var(--text-muted)}
.rbn-kicker-meta{flex:0 0 auto;white-space:nowrap}
/* Plain-text node code · name (req #4 — NOT a link; no hover/underline). */
.rbn-kicker-link{
  display:inline-flex;align-items:center;min-width:0;flex:1;
  color:inherit;text-decoration:none;overflow:hidden;
}
.rbn-kicker-code{flex:0 0 auto;white-space:nowrap}
.rbn-kicker-name{
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* Right side of band: dots + kebab */
.rbn-band-right{display:flex;align-items:center;gap:4px;flex-shrink:0}

/* 5-dot grade rail (from identity.buildDots, re-skinned) */
.rbn-dots{display:flex;align-items:center;gap:3px;flex-shrink:0}
.rbn-dot{
  width:5px;height:5px;border-radius:50%;flex-shrink:0;
  background:color-mix(in srgb, var(--rbn-tint-color, var(--border-strong)) 35%, var(--border));
  opacity:.55;
}
.rbn-dot.grade-honed   {background:var(--grade-honed);opacity:1}
.rbn-dot.grade-missed  {background:var(--grade-missed);opacity:1}
.rbn-dot.grade-mastered{background:var(--grade-mastered);opacity:1}
.rbn-dot.grade-hazy    {background:var(--grade-hazy);opacity:1}

/* Kebab — 44×44 hit area via padding + negative margin; div[role=button]. */
.rbn-more{
  appearance:none;border:0;background:transparent;
  color:color-mix(in srgb, var(--rbn-tint-color, var(--border-strong)) 70%, var(--text-faint));
  cursor:pointer;line-height:1;
  padding:10px 12px;margin:-10px -6px -10px 0;
  min-height:44px;min-width:44px;
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
  transition:color .12s;border-radius:4px;
}
.rbn-more:hover{color:var(--text-muted)}
.rbn-more svg{display:block}

/* =====================================================
   ROW 2: body (NOT tinted — card surface)
   ===================================================== */
.rbn-body{
  display:flex;align-items:flex-start;gap:8px;
  min-height:26px;padding:5px 8px 7px 9px;
  position:relative;
  background:var(--surface);
}

/* Stem — 1–2 line clamp, left */
.rbn-stem{
  font-size:12px;font-weight:500;line-height:1.4;
  color:var(--text);letter-spacing:-.005em;
  flex:1;min-width:0;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.ribbon-wrap.expanded .rbn-stem{-webkit-line-clamp:unset;overflow:visible}

/* Right side of body: [last-grade pill] over due, hung under the dots/kebab */
.rbn-body-right{
  display:flex;flex-direction:column;align-items:flex-end;
  gap:2px;flex-shrink:0;
}

/* Last-grade word (graded cards) — soft tinted pill */
.rbn-last-grade{
  font-size:9.5px;font-weight:700;letter-spacing:.04em;
  color:var(--rbn-grade-label-color, var(--text-faint));
  white-space:nowrap;line-height:1;
  background:color-mix(in srgb, var(--rbn-grade-bg-color, var(--border)) 15%, var(--surface-elevated));
  border:1px solid color-mix(in srgb, var(--rbn-grade-bg-color, var(--border)) 30%, var(--border));
  border-radius:4px;padding:2px 5px;
}

/* Due string */
.rbn-due{
  font-size:9.5px;font-weight:600;letter-spacing:.03em;
  color:var(--text-muted);white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
.rbn-due.overdue {color:var(--grade-missed-label)}
.rbn-due.new-card{color:var(--text-muted)}
.rbn-due.due-soon{color:var(--grade-honed-label)}

/* Haul next-due forecast slot (filled post-session) — sits in body-right */
.haul-ribbon-due{
  font-size:9.5px;font-weight:600;color:var(--text-muted);
  font-variant-numeric:tabular-nums;white-space:nowrap;
}

/* =====================================================
   Expand panel — answer shown below Row 2
   ===================================================== */
.ribbon-expand{
  max-height:0;overflow:hidden;
  border-top:0 solid var(--border);
  background:var(--surface);
  padding:0 12px;
  font-size:12.5px;line-height:1.6;color:var(--text);
  /* Sit ABOVE the absolute .ribbon-card__trigger (inset:0, z-index:0) so the
     expand's interactive children — the SAQ 3-tab bar, ref chips — receive
     clicks instead of the trigger swallowing them (which also toggled the
     expand shut). The wrap click handler already ignores .ribbon-expand. */
  position:relative;z-index:1;
}
.ribbon-expand.open{
  max-height:none;
  border-top-width:1px;
  padding:10px 12px 11px;
}
@media (prefers-reduced-motion:no-preference){
  .ribbon-expand{transition:padding 200ms cubic-bezier(.4,.05,.2,1)}
}
.ribbon-expand strong{font-weight:700}
.ribbon-expand p{margin:0 0 7px}
.ribbon-expand p:last-child{margin-bottom:0}

/* Axiom expand: reuse content.js axiom layout (clinical context + formula +
   variables + named-after). content.js paints .fc-context/.axiom-formula/etc. */
.ribbon-expand--axiom .axiom-formula{font-size:15px;margin:8px 0}
.ribbon-expand--axiom .fc-context{
  font-style:italic;font-size:12.5px;color:var(--text-muted);margin:0 0 10px;
}

/* SAQ expand: reuse content.js 3-tab (CICM/Model/Notes) bar + panels.
   The shared .fc-tab-bar (card-v2.css) defaults to display:none and is only
   revealed by a .fc-card.revealed ancestor — which the ribbon expand does NOT
   have. Force it visible here so the SAQ ribbon expand shows the working tab bar
   (req #3), not just the active panel. */
.ribbon-expand--saq{
  /* .fc-tab active colour reads --type-color (set by .fc-card.type-saq on the
     card). The ribbon has no .fc-card ancestor, so alias it to the ribbon's
     resolved type colour (SAQ rose) for the active-tab underline/label. */
  --type-color:var(--rbn-type-color, var(--rose-deep));
}
.ribbon-expand--saq .fc-tab-bar{
  display:flex;margin:-2px -12px 8px;padding:4px 12px 0;
}
.ribbon-expand--saq .b-prompt{
  font-size:12.5px;font-weight:600;color:var(--text);margin:0 0 8px;
}

.ribbon-card__answer{color:var(--text);font-weight:400}

/* Drug 5-column expand layout */
.drug-expand-cols{display:flex;gap:10px;overflow-x:auto;align-items:flex-start}
.drug-expand-col{flex:1 1 0;min-width:90px}
.drug-expand-col__label{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);margin-bottom:5px}
@media(max-width:680px){.drug-expand-cols{flex-direction:column;gap:8px}}

/* =====================================================
   Compact mode (More-cards ghost rows)
   Tighter band + single-line stem (the promotable title stays visible).
   ===================================================== */
.ribbon-wrap--compact .rbn-band{min-height:24px;padding:3px 6px 3px 8px}
.ribbon-wrap--compact .rbn-body{min-height:0;padding:3px 8px 5px 9px}
.ribbon-wrap--compact .rbn-stem{-webkit-line-clamp:1;font-size:11px}

/* =====================================================
   Curriculum mode (topic ribbons)
   ===================================================== */
.ribbon-wrap--curriculum.ribbon-wrap--leaf-card{margin-left:20px}

/* =====================================================
   Multi-select state
   ===================================================== */
.ribbon-wrap.is-selected{
  background:color-mix(in srgb,var(--grade-honed) 8%,var(--surface));
  box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--grade-honed) 40%,var(--border));
}
.ribbon-wrap.is-selected::after{
  content:'✓';
  position:absolute;left:-14px;top:50%;transform:translateY(-50%);
  width:18px;height:18px;border-radius:50%;
  background:var(--grade-honed);color:#fff;
  font-size:10px;font-weight:700;
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 1px 3px rgba(0,0,0,0.15);z-index:2;
}
.ribbon-wrap.is-pressing{transform:scale(0.98);transition:transform 0.3s}

/* =====================================================
   Vertical list container
   ===================================================== */
.ribbon-list{display:flex;flex-direction:column;gap:4px;transition:padding-left 0.2s}
.ribbon-list.is-selecting{padding-left:20px}

/* =====================================================
   Summary header
   ===================================================== */
.ribbon-summary{
  display:flex;justify-content:space-between;align-items:center;
  padding:9px 12px;border-radius:8px;font-size:11px;
  background:color-mix(in srgb,var(--text) 4%,var(--surface));
  border:0.5px solid var(--border);margin-bottom:8px;
}
.ribbon-summary__title{font-weight:600}
.ribbon-summary__stats{display:flex;gap:10px;align-items:center;font-variant-numeric:tabular-nums}
.ribbon-summary__stat{display:flex;align-items:center;gap:4px}
.ribbon-summary__pip{width:8px;height:8px;border-radius:50%;display:inline-block}
.ribbon-summary__pip--missed  {background:var(--grade-missed)}
.ribbon-summary__pip--honed   {background:var(--grade-honed)}
.ribbon-summary__pip--mastered{background:var(--grade-mastered)}

/* =====================================================
   Selection toolbar
   ===================================================== */
.ribbon-select-bar{
  display:none;position:sticky;bottom:0;
  background:var(--surface-elevated);border:1px solid var(--border);
  border-radius:var(--radius-sm);padding:10px 14px;margin-top:8px;
  align-items:center;justify-content:space-between;gap:8px;
  box-shadow:0 -2px 12px rgba(0,0,0,0.08);z-index:10;
}
.ribbon-select-bar.is-active{display:flex}
.ribbon-select-bar__count{font-size:12px;font-weight:600;color:var(--text)}
.ribbon-select-bar__actions{display:flex;gap:6px}
.ribbon-select-bar__btn{
  padding:6px 12px;border-radius:6px;border:1px solid var(--border);
  background:var(--surface);color:var(--text);font-size:11px;cursor:pointer;
  font-family:inherit;font-weight:500;
}
.ribbon-select-bar__btn--primary{background:var(--sage);color:#fff;border-color:var(--sage)}
.ribbon-select-bar__btn--cancel{background:transparent;border-color:transparent;color:var(--text-muted)}

/* =====================================================
   Dark mode
   ===================================================== */
html[data-theme="dark"] .ribbon-wrap{background:var(--surface-elevated)}
html[data-theme="dark"] .rbn-body{background:var(--surface)}
html[data-theme="dark"] .ribbon-expand{background:var(--surface)}
html[data-theme="dark"] .ribbon-summary{background:color-mix(in srgb,var(--text) 5%,var(--surface))}
html[data-theme="dark"] .ribbon-select-bar{background:var(--surface-elevated)}

/* pwa/css/activity-surface.css
 * Activity Surface v3 — Lore tab redesign (Cupcake C1).
 *
 * Ported from _mockups/activity-surface-v1.html with three conflict resolutions:
 *   1. Sheet infrastructure uses as-* namespace (existing .sheet-backdrop at z:9998
 *      uses display:flex layout; our sheets use display:none + sibling slide pattern).
 *   2. .ribbon-list scoped under .activity-surface (existing .ribbon-list is flex-column).
 *   3. .sheet-handle conflict avoided (existing width:40px; ours is 36px).
 *
 * Class prefix convention: as-* for sheet infra; all other selectors are new.
 */

/* ── Shared helpers ─────────────────────────────────────────────────────── */
.section-eyebrow{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text-faint);font-weight:600;margin:0 0 8px}
.sect-header{display:flex;flex-direction:column;align-items:center;gap:2px;margin-bottom:12px;text-align:center;position:relative}
.sect-header h2{margin:0;font-family:var(--font-display);font-size:18px;font-weight:400;color:var(--text);line-height:1.1}
.sect-header .subhead{font-size:12px;color:var(--text-muted);font-weight:400}
.sect-header .info-tap{position:absolute;right:0;top:2px}

/* ── Hero strip (7-cell, kept + improved) ───────────────────────────────── */
.hero-strip-inner{display:flex;gap:6px;align-items:stretch;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:10px 12px}
.hero-strip-meta{display:flex;flex-direction:column;justify-content:center;gap:2px;padding-right:8px;border-right:1px solid var(--border);min-width:88px}
.hero-strip-meta-label{font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);font-weight:600}
.hero-strip-meta-streak{font-size:18px;line-height:1;color:var(--accent);display:flex;align-items:baseline;gap:4px;font-family:var(--font-sans);font-weight:700;font-variant-numeric:tabular-nums}
.hero-strip-meta-streak small{font-size:11px;color:var(--text-muted);font-weight:400}
.hero-strip-cells{display:grid;grid-template-columns:repeat(7,1fr);gap:6px;flex:1;align-items:stretch}
.hero-cell{position:relative;aspect-ratio:1;border-radius:var(--btn-radius);display:flex;align-items:center;justify-content:center;background:var(--surface-elevated);cursor:pointer;min-height:38px;border:1px solid transparent;transition:transform var(--duration-sm) var(--ease-out)}
.hero-cell::after{content:"";position:absolute;inset:-6px}
.hero-cell[data-today=true]{background:var(--coral)!important;transform:scale(1.18);z-index:2;box-shadow:0 4px 10px rgba(200,98,90,.35);border-color:var(--coral-deep)}
.hero-cell-day{font-size:13px;color:var(--text);font-weight:700;line-height:1;letter-spacing:.02em}
.hero-cell[data-lv="3"] .hero-cell-day,.hero-cell[data-lv="4"] .hero-cell-day{color:var(--accent-on)}
.hero-cell[data-future=true][data-lv="3"] .hero-cell-day,.hero-cell[data-future=true][data-lv="4"] .hero-cell-day{color:var(--text-muted-strong)}
.hero-cell[data-today=true] .hero-cell-day{color:var(--bg);font-size:14px}
.hero-cell-new{position:absolute;top:3px;left:5px;font-size:10px;line-height:1;font-weight:700;color:var(--sky-deep);font-variant-numeric:tabular-nums;pointer-events:none}
.hero-cell-due{position:absolute;bottom:3px;right:5px;font-size:10px;line-height:1;font-weight:700;color:var(--coral-deep);font-variant-numeric:tabular-nums;pointer-events:none}
.hero-cell[data-lv="1"]{background:color-mix(in srgb,var(--accent) 22%,var(--surface-elevated))}
.hero-cell[data-lv="2"]{background:color-mix(in srgb,var(--accent) 45%,var(--surface-elevated))}
.hero-cell[data-lv="3"]{background:color-mix(in srgb,var(--accent) 70%,var(--surface-elevated));color:var(--accent-on)}
.hero-cell[data-lv="4"]{background:var(--accent);color:var(--accent-on)}
.hero-cell[data-lv="3"] .hero-cell-day,.hero-cell[data-lv="4"] .hero-cell-day{color:color-mix(in srgb,var(--accent-on) 80%,transparent)}
.hero-cell[data-future=true][data-lv="1"]{background:color-mix(in srgb,var(--honey) 22%,var(--surface-elevated))}
.hero-cell[data-future=true][data-lv="2"]{background:color-mix(in srgb,var(--honey) 45%,var(--surface-elevated))}
.hero-cell[data-future=true][data-lv="3"]{background:color-mix(in srgb,var(--honey) 70%,var(--surface-elevated));color:var(--text-muted-strong)}
.hero-cell[data-future=true][data-lv="4"]{background:var(--honey);color:var(--text-muted-strong)}

/* ── Surface shell ─────────────────────────────────────────────────────── */
.activity-surface{max-width:1400px;margin:0 auto;padding:14px 14px 80px;display:flex;flex-direction:column;gap:14px;--page-pad:14px}
@media (min-width:768px){.activity-surface{padding:24px 20px 100px;gap:18px;--page-pad:20px}}
@media (min-width:1200px){.activity-surface{padding:28px 32px 100px;gap:20px;--page-pad:32px}}

/* ── §1 Heatmap rail ───────────────────────────────────────────────────── */
/* Negative inline-margin bleeds the rail to viewport edges; padding-inline
   restores the gutter so actions-row content aligns with the rest of the surface. */
.heatmap-rail{padding:6px 0 2px;background:transparent;margin-inline:calc(-1 * var(--page-pad,14px));padding-inline:var(--page-pad,14px)}
.heatmap-actions-row{display:flex;justify-content:center;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.heatmap-streak-inline{display:inline-flex;align-items:center;gap:6px;padding:3px 9px;background:var(--accent-soft);color:var(--accent);border-radius:var(--radius-pill);font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;min-height:24px;position:relative}
.heatmap-streak-inline .info-tap{width:18px;height:18px;border-radius:50%;background:rgba(255,255,255,.4);display:inline-flex;align-items:center;justify-content:center;font-size:10px;color:var(--accent);position:relative;cursor:pointer}
.heatmap-streak-inline .info-tap::after{content:"";position:absolute;inset:-6px}
.heatmap-streak-inline .longest{color:var(--text-muted);font-weight:500}
.heatmap-smooth-action{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;background:var(--coral-fill);color:var(--coral-deep);border:1px solid color-mix(in srgb,var(--coral-deep) 30%,transparent);border-radius:var(--radius-pill);font-size:11px;font-weight:600;cursor:pointer;min-height:28px;position:relative}
.heatmap-smooth-action::after{content:"";position:absolute;inset:-6px}
.heatmap-resume-action{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;background:var(--accent);color:var(--accent-on);border:0;border-radius:var(--radius-pill);font-size:11px;font-weight:600;cursor:pointer;min-height:28px;position:relative;box-shadow:0 1px 3px rgba(45,71,48,.18)}
.heatmap-resume-action::after{content:"";position:absolute;inset:-6px}
.heatmap-resume-action .pulse{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--coral);animation:as-pulse 1.8s ease-in-out infinite}
.heatmap-grid-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;padding:2px 2px 4px;scrollbar-width:thin}
.heatmap-grid{display:grid;grid-auto-flow:column;grid-template-rows:repeat(7,27px);gap:4px;width:max-content}
@media (min-width:768px){.heatmap-grid{grid-template-rows:repeat(7,30px);gap:4px}}
.hm-cell{width:27px;height:27px;border-radius:var(--radius-tiny);background:var(--surface-elevated);position:relative;cursor:pointer;transition:transform var(--duration-sm) var(--ease-out)}
@media (min-width:768px){.hm-cell{width:30px;height:30px;border-radius:5px}}
.hm-cell::after{content:"";position:absolute;inset:-4px}
.hm-cell-new{position:absolute;top:2px;left:3px;font-size:10px;line-height:1;font-weight:700;color:var(--sky-deep);font-variant-numeric:tabular-nums;pointer-events:none}
.hm-cell-due{position:absolute;bottom:2px;right:3px;font-size:10px;line-height:1;font-weight:700;color:var(--coral-deep);font-variant-numeric:tabular-nums;pointer-events:none}
.hm-cell[data-future=true]{background:var(--surface-elevated);border:1px solid color-mix(in srgb,var(--border) 50%,transparent)}
.hm-cell[data-future=true][data-burden=high]{background:color-mix(in srgb,var(--coral) 8%,var(--surface-elevated));border-color:color-mix(in srgb,var(--coral) 30%,transparent)}
.hm-cell[data-future=true][data-burden=heavy]{background:color-mix(in srgb,var(--coral) 15%,var(--surface-elevated));border-color:var(--coral)}
.hm-cell[data-future=true][data-burden=heavy]{outline:1px solid var(--coral);outline-offset:-1px}
.hm-cell[data-today=true]{background:var(--coral)!important;outline:2px solid var(--coral-deep);outline-offset:1px;z-index:1;border-color:transparent!important}
.hm-cell[data-rest=true]::before{content:"❄";position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:8px;color:var(--sky-deep);pointer-events:none}
.hm-cell[data-active=true]{box-shadow:0 0 0 2px var(--accent);transform:scale(1.2);z-index:2}
.hm-cell[data-empty=true]{background:transparent;border:1px dashed color-mix(in srgb,var(--border) 50%,transparent)}
.hm-cell[data-lv="0"]{background:var(--surface-elevated);border:1px solid color-mix(in srgb,var(--border) 60%,transparent)}
.hm-cell[data-lv="1"]{background:color-mix(in srgb,var(--accent) 22%,var(--surface-elevated))}
.hm-cell[data-lv="2"]{background:color-mix(in srgb,var(--accent) 45%,var(--surface-elevated))}
.hm-cell[data-lv="3"]{background:color-mix(in srgb,var(--accent) 70%,var(--surface-elevated))}
.hm-cell[data-lv="4"]{background:var(--accent)}
.hm-cell[data-future=true][data-lv="1"]{background:color-mix(in srgb,var(--honey) 22%,var(--surface-elevated))}
.hm-cell[data-future=true][data-lv="2"]{background:color-mix(in srgb,var(--honey) 45%,var(--surface-elevated))}
.hm-cell[data-future=true][data-lv="3"]{background:color-mix(in srgb,var(--honey) 70%,var(--surface-elevated))}
.hm-cell[data-future=true][data-lv="4"]{background:var(--honey)}

/* Past vs future tint on empty (lv=0) cells — past stays neutral grey, future
   gets a subtle honey wash so users see the horizon at a glance. */
.hm-cell[data-past=true][data-lv="0"]{background:color-mix(in srgb,var(--ink,#1a2211) 5%,var(--surface-elevated));border-color:color-mix(in srgb,var(--border) 50%,transparent)}
.hm-cell[data-future=true][data-lv="0"]{background:color-mix(in srgb,var(--honey) 6%,var(--surface-elevated));border-color:color-mix(in srgb,var(--honey) 18%,var(--border))}
.hm-cell[data-when=past][data-empty=true]{border-style:solid;border-color:color-mix(in srgb,var(--border) 30%,transparent)}
.hm-cell[data-when=future][data-empty=true]{border-style:dashed;border-color:color-mix(in srgb,var(--honey) 25%,var(--border))}
.hm-cell[data-iso]{cursor:pointer;transition:transform var(--duration-sm) var(--ease-out)}
.hm-cell[data-iso]:hover{transform:scale(1.15);z-index:1}

/* ── §2 Readiness anchor ───────────────────────────────────────────────── */
.readiness-anchor{background:var(--surface-elevated);border:0;border-radius:var(--radius-lg);padding:18px 18px 16px;box-shadow:var(--shadow-md);position:relative}
.readiness-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:14px;gap:8px}
.readiness-head h2{font-family:var(--font-display);font-size:18px;font-weight:400}
.readiness-head .info-tap{width:28px;height:28px;border-radius:50%;border:1px solid var(--border);display:inline-flex;align-items:center;justify-content:center;font-size:12px;color:var(--text-muted);position:relative;cursor:pointer}
.readiness-head .info-tap::after{content:"";position:absolute;inset:-8px}
.readiness-hero{display:flex;flex-direction:column;align-items:center;gap:14px;margin-bottom:14px;text-align:center}
.readiness-big{display:flex;flex-direction:column;align-items:center;gap:2px}
.readiness-num{font-family:var(--font-sans);font-weight:700;font-size:56px;line-height:.95;color:var(--text);font-variant-numeric:tabular-nums;display:flex;align-items:baseline;gap:2px;justify-content:center}
.readiness-num small{font-size:22px;color:var(--text-muted);font-weight:500;margin-left:2px}
.readiness-ci{font-size:11px;color:var(--text-faint);font-variant-numeric:tabular-nums}
.readiness-target-wrap{display:flex;flex-direction:column;gap:6px;min-width:0;width:100%;max-width:420px}
.readiness-target-bar{position:relative;height:10px;background:var(--surface);border-radius:5px;overflow:visible;border:1px solid var(--border)}
.readiness-target-fill{position:absolute;left:0;top:0;bottom:0;background:linear-gradient(90deg,var(--coral) 0%,var(--honey) 50%,var(--accent) 100%);border-radius:5px;opacity:.85}
.readiness-target-ci{position:absolute;top:-3px;bottom:-3px;background:color-mix(in srgb,var(--text) 22%,transparent);border-radius:3px;pointer-events:none}
.readiness-target-marker{position:absolute;top:-6px;bottom:-6px;width:2px;background:var(--coral-deep);border-radius:1px}
.readiness-target-marker::after{content:"target 80%";position:absolute;bottom:-16px;left:50%;transform:translateX(-50%);font-size:10px;color:var(--coral-deep);white-space:nowrap;font-variant-numeric:tabular-nums}
.readiness-delta{font-size:12px;color:var(--text-muted);display:flex;align-items:center;gap:8px;margin-top:12px}
.delta-chip{display:inline-flex;align-items:center;gap:3px;padding:3px 8px;border-radius:var(--radius-pill);font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;min-height:22px;position:relative}
.delta-chip::after{content:"";position:absolute;inset:-8px}
.delta-chip[data-dir=up]{background:var(--sage-fill);color:var(--sage-deep)}
.delta-chip[data-dir=down]{background:var(--coral-fill);color:var(--coral-deep)}
.delta-chip[data-dir=flat]{background:var(--surface);color:var(--text-muted);border:1px solid var(--border)}
.readiness-sub{display:grid;grid-template-columns:1fr;gap:10px;padding-top:14px;border-top:1px solid var(--border)}
@media (min-width:560px){.readiness-sub{grid-template-columns:1fr 1fr}}
.readiness-sub-row{display:grid;grid-template-columns:1fr auto;gap:8px;align-items:baseline;padding:6px 0;cursor:pointer;border-radius:var(--btn-radius);position:relative}
.readiness-sub-row:hover{background:var(--surface)}
.readiness-sub-row::after{content:"";position:absolute;inset:-4px -8px;border-radius:var(--radius-sm)}
.readiness-sub-row .label{font-size:12px;color:var(--text-muted)}
.readiness-sub-row .value{font-size:14px;font-weight:600;color:var(--text);font-variant-numeric:tabular-nums}
.readiness-sub-row .meta-row{grid-column:1/-1;font-size:10px;color:var(--text-faint)}
.readiness-sub-row .drill-arrow{color:var(--text-faint);font-size:11px;margin-left:6px;opacity:0;transition:opacity var(--duration-sm)}
.readiness-sub-row:hover .drill-arrow{opacity:1}

/* ── §3 FSRS cohorts ──────────────────────────────────────────────────── */
.cohorts-section{padding:0 4px}
.cohorts-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}
@media (min-width:560px){.cohorts-grid{grid-template-columns:repeat(3,1fr)}}
@media (min-width:768px){.cohorts-grid{grid-template-columns:repeat(6,1fr)}}
.cohort-tile{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:10px;display:flex;flex-direction:column;gap:3px;cursor:pointer;position:relative;min-height:80px;border-left:3px solid var(--c-new);transition:transform var(--duration-sm) var(--ease-out),box-shadow var(--duration-sm) var(--ease-out)}
.cohort-tile::after{content:"";position:absolute;inset:-2px;border-radius:14px}
.cohort-tile:hover{transform:translateY(-1px);box-shadow:var(--shadow-md)}
.cohort-tile[data-cohort=new]{border-left-color:var(--c-new)}
.cohort-tile[data-cohort=learning]{border-left-color:var(--c-learning)}
.cohort-tile[data-cohort=mature]{border-left-color:var(--c-mature)}
.cohort-tile[data-cohort=atrisk]{border-left-color:var(--c-atrisk);background:linear-gradient(180deg,color-mix(in srgb,var(--c-atrisk) 6%,var(--surface)) 0%,var(--surface) 100%)}
.cohort-tile[data-cohort=leech]{border-left-color:var(--c-leech);background:linear-gradient(180deg,color-mix(in srgb,var(--c-leech) 6%,var(--surface)) 0%,var(--surface) 100%)}
.cohort-tile[data-cohort=overdue]{border-left-color:var(--c-overdue);background:linear-gradient(180deg,color-mix(in srgb,var(--c-overdue) 8%,var(--surface)) 0%,var(--surface) 100%)}
.cohort-label{font-size:10px;letter-spacing:.04em;text-transform:uppercase;color:var(--text-muted);font-weight:600}
.cohort-num{font-size:22px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1}
.cohort-sub{font-size:10px;color:var(--text-faint);font-variant-numeric:tabular-nums}
.cohort-tile[data-cohort=overdue] .cohort-num,.cohort-tile[data-cohort=atrisk] .cohort-num,.cohort-tile[data-cohort=leech] .cohort-num{color:var(--coral-deep)}

/* ── §4 Curriculum cockpit ────────────────────────────────────────────── */
.curriculum-section{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px}
.curr-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;flex-wrap:wrap;gap:8px}
.curr-head h2{font-size:14px;font-weight:600}
.curr-head .meta{font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums}
.curr-summary-bar{display:flex;height:14px;border-radius:7px;overflow:hidden;background:var(--surface-elevated);border:1px solid var(--border);margin-bottom:8px}
.curr-summary-bar .seg{position:relative;display:flex;align-items:center;justify-content:center;font-size:9px;color:#fff;font-weight:600;min-width:6px}
.curr-summary-bar .seg[data-tone=mastered]{background:var(--grade-mastered)}
.curr-summary-bar .seg[data-tone=honed]{background:var(--grade-honed)}
.curr-summary-bar .seg[data-tone=hazy]{background:var(--grade-hazy);color:#111}
.curr-summary-bar .seg[data-tone=missed]{background:var(--grade-missed)}
.curr-summary-bar .seg[data-tone=untouched]{background:var(--surface-elevated);color:var(--text-faint);border-left:1px dashed var(--border)}
.curr-summary-legend{display:flex;flex-wrap:wrap;gap:10px;font-size:10px;color:var(--text-muted);margin-bottom:12px}
.curr-summary-legend span{display:inline-flex;align-items:center;gap:4px}
.curr-summary-legend i{width:10px;height:10px;border-radius:var(--radius-2xs);display:inline-block}
.curr-kpis{display:grid;grid-template-columns:repeat(2,1fr);gap:6px;margin-bottom:12px}
@media (min-width:560px){.curr-kpis{grid-template-columns:repeat(4,1fr)}}
.curr-kpi{background:var(--surface-elevated);border-radius:var(--radius-sm);padding:8px 10px;display:flex;flex-direction:column;gap:1px}
.curr-kpi-label{font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);font-weight:600}
.curr-kpi-value{font-size:18px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1}
.curr-kpi-sub{font-size:10px;color:var(--text-muted);font-variant-numeric:tabular-nums}
.curr-kpi[data-tone=alert] .curr-kpi-value{color:var(--coral-deep)}
.curr-toolbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;margin-bottom:8px}
.curr-toolbar-left{display:flex;gap:4px;flex-wrap:wrap}
.curr-toolbar-left button{padding:4px 9px;border:1px solid var(--border);background:var(--surface-elevated);border-radius:var(--radius-pill);color:var(--text-muted);font-size:11px;font-weight:500;cursor:pointer;min-height:26px;position:relative}
.curr-toolbar-left button::after{content:"";position:absolute;inset:-4px}
.curr-toolbar-left button[aria-pressed=true]{background:var(--accent);color:var(--accent-on);border-color:transparent}
.curr-toolbar-right{display:flex;gap:6px;align-items:center;font-size:11px;color:var(--text-muted);flex-wrap:wrap}
.curr-toolbar-right label{display:inline-flex;align-items:center;gap:4px;cursor:pointer;user-select:none}
.curr-sort{display:inline-flex;gap:3px;background:var(--surface-elevated);border:1px solid var(--border);border-radius:var(--radius-pill);padding:2px}
.curr-sort button{padding:3px 8px;border-radius:var(--radius-pill);font-size:11px;color:var(--text-muted);min-height:24px;font-weight:500;border:0;background:transparent;cursor:pointer;position:relative}
.curr-sort button::after{content:"";position:absolute;inset:-4px}
.curr-sort button[aria-pressed=true]{background:var(--accent);color:var(--accent-on)}
.sort-arrow{font-size:9px;margin-left:2px;font-weight:700}
.curr-sections{display:flex;flex-direction:column;gap:6px}
.curr-section{background:var(--surface-elevated);border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}
.curr-section-head{display:grid;grid-template-columns:auto 1fr auto auto auto;gap:10px;align-items:center;padding:8px 12px;cursor:pointer;min-height:44px;user-select:none;background:var(--surface)}
.curr-section-head .curr-section-bar{grid-column:1/-1;grid-row:2;width:100%;min-width:0;height:6px;margin-top:2px}
@media (min-width:560px){
  .curr-section-head{grid-template-columns:auto 1fr 140px 56px 44px auto}
  .curr-section-head .curr-section-bar{grid-column:auto;grid-row:auto;margin-top:0;min-width:60px;height:8px}
}
.curr-section[data-open=true] .curr-section-head{background:color-mix(in srgb,var(--accent) 5%,var(--surface))}
.curr-section-dot{width:8px;height:8px;border-radius:50%}
.curr-section-name{font-size:13px;color:var(--text);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.curr-section-name small{font-weight:400;color:var(--text-faint);font-size:10px;margin-left:6px}
.curr-section-bar{display:flex;height:6px;border-radius:3px;overflow:hidden;background:var(--surface-elevated);border:1px solid var(--border);min-width:60px}
.curr-section-bar .seg{height:100%}
.curr-section-bar .seg[data-tone=mastered]{background:var(--grade-mastered)}
.curr-section-bar .seg[data-tone=honed]{background:var(--grade-honed)}
.curr-section-bar .seg[data-tone=hazy]{background:var(--grade-hazy)}
.curr-section-bar .seg[data-tone=missed]{background:var(--grade-missed)}
.curr-section-bar .seg[data-tone=untouched]{background:var(--surface);border-left:1px dashed var(--border)}
.curr-section-count{font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums;text-align:right}
.curr-section-count strong{color:var(--text);font-weight:600}
.curr-section-ret{font-size:11px;color:var(--accent);font-weight:600;font-variant-numeric:tabular-nums;text-align:right}
.curr-section-ret[data-tone=low]{color:var(--coral-deep)}
.curr-section-chev{font-size:11px;color:var(--text-faint);transition:transform var(--duration-sm) var(--ease-out)}
.curr-section[data-open=true] .curr-section-chev{transform:rotate(180deg)}
.curr-section-body{display:none;flex-direction:column;gap:4px;padding:6px 8px 10px}
.curr-section[data-open=true] .curr-section-body{display:flex}
.curr-chapter{padding:6px 10px 8px;border-radius:var(--btn-radius);background:var(--surface);border:1px solid color-mix(in srgb,var(--border) 70%,transparent)}
.curr-chapter-head{display:grid;grid-template-columns:1fr auto auto;gap:8px;align-items:center;font-size:12px;margin-bottom:4px}
.curr-chapter-head .curr-chapter-bar{grid-column:1/-1;grid-row:2;width:100%;height:4px;margin-top:2px}
@media (min-width:560px){
  .curr-chapter-head{grid-template-columns:1fr 100px 44px 40px}
  .curr-chapter-head .curr-chapter-bar{grid-column:auto;grid-row:auto;margin-top:0}
}
.curr-chapter-name{color:var(--text-muted);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.curr-chapter-bar{display:flex;height:4px;border-radius:var(--radius-2xs);overflow:hidden;background:var(--surface-elevated);border:1px solid color-mix(in srgb,var(--border) 50%,transparent)}
.curr-chapter-bar .seg{height:100%}
.curr-chapter-bar .seg[data-tone=mastered]{background:var(--grade-mastered)}
.curr-chapter-bar .seg[data-tone=honed]{background:var(--grade-honed)}
.curr-chapter-bar .seg[data-tone=hazy]{background:var(--grade-hazy)}
.curr-chapter-bar .seg[data-tone=missed]{background:var(--grade-missed)}
.curr-chapter-bar .seg[data-tone=untouched]{background:var(--surface);border-left:1px dashed var(--border)}
.curr-chapter-count{font-size:10px;color:var(--text-faint);font-variant-numeric:tabular-nums;text-align:right}
.curr-chapter-ret{font-size:10px;font-weight:600;color:var(--accent);font-variant-numeric:tabular-nums;text-align:right}
.curr-chapter-ret[data-tone=low]{color:var(--coral-deep)}
.curr-topic-list{display:flex;flex-direction:column;gap:2px;padding-top:4px;padding-left:6px;border-left:2px solid color-mix(in srgb,var(--accent) 18%,var(--border));margin-left:2px}
.curr-topic-row{display:grid;grid-template-columns:auto 1fr auto auto;gap:6px;align-items:center;padding:4px 8px;background:var(--surface-elevated);border-radius:var(--radius-tiny);font-size:11px;cursor:pointer;position:relative;min-height:28px}
.curr-topic-row .curr-topic-bar{grid-column:1/-1;grid-row:2;width:100%;height:4px;margin-top:2px}
@media (min-width:560px){
  .curr-topic-row{grid-template-columns:auto 1fr 60px 36px 32px}
  .curr-topic-row .curr-topic-bar{grid-column:auto;grid-row:auto;margin-top:0}
}
.curr-topic-row::after{content:"";position:absolute;inset:-1px;border-radius:5px}
.curr-topic-row:hover{background:color-mix(in srgb,var(--accent) 8%,var(--surface-elevated))}
.curr-topic-dot{width:7px;height:7px;border-radius:50%;flex:none}
.curr-topic-dot[data-state=mastered]{background:var(--grade-mastered)}
.curr-topic-dot[data-state=honed]{background:var(--grade-honed)}
.curr-topic-dot[data-state=hazy]{background:var(--grade-hazy)}
.curr-topic-dot[data-state=missed]{background:var(--grade-missed)}
.curr-topic-dot[data-state=untouched]{background:var(--text-faint);opacity:.4}
.curr-topic-name{color:var(--text);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px}
.curr-topic-row[data-state=untouched] .curr-topic-name{color:var(--text-faint);font-weight:400}
.curr-topic-bar{height:4px;background:var(--surface);border-radius:var(--radius-2xs);overflow:hidden;border:1px solid color-mix(in srgb,var(--border) 50%,transparent);position:relative}
.curr-topic-bar-fill{position:absolute;left:0;top:0;bottom:0;border-radius:var(--radius-2xs)}
.curr-topic-bar-fill[data-state=mastered]{background:var(--grade-mastered)}
.curr-topic-bar-fill[data-state=honed]{background:var(--grade-honed)}
.curr-topic-bar-fill[data-state=hazy]{background:var(--grade-hazy)}
.curr-topic-bar-fill[data-state=missed]{background:var(--grade-missed)}
.curr-topic-bar-fill[data-state=untouched]{background:transparent}
.curr-topic-count{font-size:10px;color:var(--text-muted);font-variant-numeric:tabular-nums;text-align:right;display:flex;flex-direction:column;align-items:flex-end;gap:1px}
.curr-topic-count strong{font-weight:600;color:var(--text)}
.curr-topic-kinds{font-size:9px;color:var(--text-faint);letter-spacing:0.2px}
.curr-topic-ret{font-size:10px;font-weight:600;color:var(--accent);font-variant-numeric:tabular-nums;text-align:right}
.curr-topic-ret[data-tone=low]{color:var(--coral-deep)}
.curr-topic-ret[data-tone=none]{color:var(--text-faint);font-weight:400}
.curr-empty{padding:14px;text-align:center;color:var(--text-muted);font-size:12px;background:var(--surface);border-radius:var(--radius-sm);border:1px dashed var(--border)}

/* ── Threshold banner ─────────────────────────────────────────────────── */
.threshold-banner{font-size:12px;color:var(--text-muted);background:var(--honey-fill);border:1px solid color-mix(in srgb,var(--honey-deep) 30%,transparent);padding:8px 12px;border-radius:var(--radius);display:flex;gap:8px;align-items:center;justify-content:space-between}
.threshold-banner-icon{flex:none;color:var(--honey-deep)}
.threshold-banner-cta{padding:5px 12px;background:var(--accent);color:var(--accent-on);border-radius:var(--radius-pill);font-size:11px;font-weight:600;cursor:pointer;min-height:28px;position:relative;border:0}
.threshold-banner-cta::after{content:"";position:absolute;inset:-6px}

/* ── §7 Session ribbon ────────────────────────────────────────────────── */
.ribbon-section{padding:14px 0 4px;border-top:1px solid var(--border);margin-inline:calc(-1 * var(--page-pad,14px))}
.ribbon-head{display:flex;justify-content:space-between;align-items:center;min-height:32px;margin-bottom:8px;padding-inline:var(--page-pad,14px)}
.ribbon-head h2{font-size:13px;font-weight:600}
.ribbon-head-meta{font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums}
.ribbon-chevron{font-size:12px;color:var(--text-muted);transition:transform var(--duration-sm) var(--ease-out);margin-left:6px}
.ribbon-section[data-expanded=true] .ribbon-chevron{transform:rotate(180deg)}
/* ribbon-list-wrap always visible (sections are non-collapsible blocks) */
.activity-surface .ribbon-list-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;scrollbar-width:thin;padding-bottom:4px;scroll-snap-type:x mandatory;width:100%;margin-inline:0;padding-inline:var(--page-pad,14px)}
/* Scoped: inside .activity-surface the ribbon uses a horizontal flex layout.
   The global .ribbon-list (app-shell css) is flex-column for legacy session
   card lists, so we bump specificity here to win the cascade. */
.activity-surface .ribbon-section .ribbon-list{display:flex !important;flex-direction:row !important;gap:6px;width:max-content;flex-wrap:nowrap}
.ribbon-kebab{width:32px;height:32px;border-radius:var(--btn-radius);border:1px solid var(--border);background:var(--surface);color:var(--text-muted);font-size:14px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;position:relative;line-height:1}
.ribbon-kebab::after{content:"";position:absolute;inset:-4px;border-radius:var(--radius-sm)}
.ribbon-kebab:hover{background:var(--surface-elevated);color:var(--text)}

.day-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;transition:box-shadow var(--duration-sm) var(--ease-out);cursor:pointer;position:relative;width:108px;flex:none;padding:8px 10px;display:flex;flex-direction:column;gap:4px;scroll-snap-align:start;min-height:88px}
.day-card[data-lv="0"]{background:var(--surface-elevated);border:1px solid color-mix(in srgb,var(--border) 70%,transparent)}
.day-card[data-lv="1"]{background:color-mix(in srgb,var(--accent) 22%,var(--surface));border-color:color-mix(in srgb,var(--accent) 18%,var(--border))}
.day-card[data-lv="2"]{background:color-mix(in srgb,var(--accent) 38%,var(--surface));border-color:transparent}
.day-card[data-lv="3"]{background:color-mix(in srgb,var(--accent) 60%,var(--surface));border-color:transparent;color:var(--accent-on)}
.day-card[data-lv="4"]{background:var(--accent);border-color:transparent;color:var(--accent-on)}
.day-card[data-lv="3"] .day-card-weekday,.day-card[data-lv="4"] .day-card-weekday{color:color-mix(in srgb,var(--accent-on) 80%,transparent)}
.day-card[data-lv="3"] .day-card-day,.day-card[data-lv="4"] .day-card-day{color:var(--accent-on)}
.day-card[data-lv="3"] .day-card-mini,.day-card[data-lv="4"] .day-card-mini,.day-card[data-lv="3"] .day-card-progress small,.day-card[data-lv="4"] .day-card-progress small{color:color-mix(in srgb,var(--accent-on) 75%,transparent)}
.day-card[data-lv="3"] .day-card-bar,.day-card[data-lv="4"] .day-card-bar{background:rgba(255,255,255,.25)}
.day-card[data-today=true]{background:var(--coral)!important;border-color:var(--coral-deep)!important;color:var(--bg);box-shadow:0 4px 10px rgba(200,98,90,.35);transform:scale(1.03);z-index:2}
.day-card[data-today=true] .day-card-weekday{color:color-mix(in srgb,var(--bg) 75%,transparent)}
.day-card[data-today=true] .day-card-day,.day-card[data-today=true] .day-card-progress,.day-card[data-today=true] .day-card-mini{color:var(--bg)}
.day-card[data-today=true] .day-card-progress small{color:color-mix(in srgb,var(--bg) 75%,transparent)}
.day-card[data-today=true] .day-card-bar{background:rgba(255,255,255,.3)}
.day-card[data-today=true] .day-card-bar-fill{background:var(--bg)}
.day-card[data-today=true] .day-card-kebab{color:var(--bg);border-color:rgba(255,255,255,.3)}
.day-card::after{content:"";position:absolute;inset:-2px;border-radius:var(--radius-md)}
.day-card[data-active=true]{box-shadow:0 0 0 2px var(--accent);border-color:transparent}
.day-card[data-missed=true]:not([data-today=true]){background:color-mix(in srgb,var(--coral) 5%,var(--surface));border-color:color-mix(in srgb,var(--coral) 25%,var(--border))}
.day-card[data-pending=true]:not([data-today=true])::before{content:"";position:absolute;top:0;right:0;width:0;height:0;border-top:10px solid var(--coral);border-left:10px solid transparent;border-bottom-left-radius:2px}
.day-card[data-archived=true]{opacity:.45;filter:saturate(.3)}
.day-card-kebab{position:absolute;top:5px;right:5px;width:20px;height:20px;border-radius:var(--radius-tiny);border:1px solid transparent;background:transparent;color:var(--text-muted);font-size:14px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;line-height:1;padding:0;z-index:3;opacity:.5;transition:opacity var(--duration-sm),background var(--duration-sm)}
.day-card:hover .day-card-kebab,.day-card .day-card-kebab:focus-visible{opacity:1;background:rgba(0,0,0,.06)}
.day-card-kebab::after{content:"";position:absolute;inset:-6px}
.card-popover{position:fixed;background:var(--surface-elevated);border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-md);z-index:280;display:none;flex-direction:column;min-width:160px;padding:4px 0}
.card-popover[data-open=true]{display:flex}
.card-popover button{text-align:left;padding:8px 14px;font-size:12px;color:var(--text);background:transparent;border:0;cursor:pointer;display:flex;align-items:center;gap:8px;min-height:34px}
.card-popover button:hover{background:var(--surface)}
.card-popover button[data-tone=delete]{color:var(--coral-deep)}
.card-popover button:disabled{opacity:.4;cursor:not-allowed}
.day-card-top{display:flex;align-items:baseline;gap:5px}
.day-card-weekday{font-size:10px;letter-spacing:.04em;text-transform:uppercase;color:var(--text-faint);font-weight:600}
.day-card-day{font-size:14px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums}
.day-card-missed-tag{font-size:9px;color:var(--coral-deep);font-weight:600;letter-spacing:.04em;text-transform:uppercase;margin-left:auto}
.day-card-progress{font-size:11px;color:var(--text);font-weight:600;font-variant-numeric:tabular-nums;display:flex;align-items:baseline;gap:3px}
.day-card-progress small{font-size:10px;color:var(--text-muted);font-weight:400}
.day-card-bar{height:3px;background:var(--surface-elevated);border-radius:var(--radius-2xs);overflow:hidden}
.day-card-bar-fill{height:100%;background:var(--accent);border-radius:var(--radius-2xs)}
.day-card-bar-fill[data-tone=low]{background:var(--coral)}
.day-card-mini{font-size:10px;color:var(--text-muted);font-variant-numeric:tabular-nums;display:flex;justify-content:space-between}
.day-card-mini-ret[data-tone=low]{color:var(--coral-deep);font-weight:600}
.day-card-mini-ret[data-tone=high]{color:var(--accent);font-weight:600}

/* ── §8 Achievements ──────────────────────────────────────────────────── */
.achievements-section{padding:14px var(--page-pad,14px) 4px;border-top:1px solid var(--border);margin-inline:calc(-1 * var(--page-pad,14px))}
.achievements-head{display:flex;justify-content:space-between;align-items:center;min-height:32px;gap:8px}
.achievements-head h2{font-size:13px;font-weight:600}
.achievements-head-meta{font-size:11px;color:var(--text-muted);display:flex;align-items:center;gap:6px;font-variant-numeric:tabular-nums}
.achievements-head-meta strong{color:var(--text);font-weight:600}
.achievements-chevron{font-size:12px;color:var(--text-muted);transition:transform var(--duration-sm) var(--ease-out);margin-left:4px}
.achievements-section[data-expanded=true] .achievements-chevron{transform:rotate(180deg)}
.achievements-body{display:flex;flex-direction:column;gap:10px;margin-top:10px}
.xp-rank{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm)}
.xp-rank-dot{width:10px;height:10px;border-radius:50%;background:var(--text-faint);flex:none}
.xp-rank-text{flex:1;display:flex;flex-direction:column;gap:1px;min-width:0}
.xp-rank-name{font-size:13px;color:var(--text);font-weight:600}
.xp-rank-sub{font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums}
.xp-rank-bar{position:relative;flex:1;max-width:140px;height:6px;background:var(--surface-elevated);border-radius:3px;overflow:hidden}
.xp-rank-bar-fill{position:absolute;left:0;top:0;bottom:0;border-radius:3px;width:0%}
.badge-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
@media (min-width:560px){.badge-grid{grid-template-columns:repeat(6,1fr)}}
@media (min-width:768px){.badge-grid{grid-template-columns:repeat(8,1fr)}}
.badge-tile{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 4px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;text-align:center;min-height:62px;font-size:10px}
.badge-tile[data-locked=true]{opacity:.45}
.badge-tile-icon{font-size:18px;line-height:1}
.badge-tile-name{font-size:9px;color:var(--text);font-weight:600;line-height:1.15;letter-spacing:.02em}
.badge-tile[data-locked=true] .badge-tile-name{color:var(--text-faint)}
.badge-tile-tier{font-size:8px;letter-spacing:.06em;text-transform:uppercase;font-weight:700}
.badge-tile-tier[data-tier=bronze]{color:#A65A1F}
.badge-tile-tier[data-tier=silver]{color:#5A6470}
.badge-tile-tier[data-tier=gold]{color:var(--honey-deep)}
.badge-tile-tier[data-tier=platinum]{color:var(--sky-deep)}
.badge-tier-group{display:flex;flex-direction:column;gap:6px}
.badge-tier-header{display:flex;justify-content:space-between;align-items:center;padding:0 2px}
.badge-tier-name{font-size:10px;letter-spacing:.08em;font-weight:700}
.badge-tier-name[data-tier=bronze]{color:#A65A1F}
.badge-tier-name[data-tier=silver]{color:#5A6470}
.badge-tier-name[data-tier=gold]{color:var(--honey-deep)}
.badge-tier-name[data-tier=platinum]{color:var(--sky-deep)}
.badge-tier-count{font-size:10px;color:var(--text-muted);font-variant-numeric:tabular-nums;font-weight:600}

/* ── Bottom sheet (as-* namespace avoids conflict with existing .sheet-backdrop) ── */
.as-backdrop{position:fixed;inset:0;background:var(--backdrop-sheet,rgba(0,0,0,.5));z-index:250;display:none;animation:as-fadeIn var(--duration-md,var(--duration-md)) var(--ease-out,var(--ease-out))}
.as-backdrop[data-open=true]{display:block}
.as-sheet{position:fixed;left:0;right:0;bottom:0;background:var(--surface-elevated);border-radius:var(--radius-lg) var(--radius-lg) 0 0;z-index:251;height:85dvh;max-height:85dvh;display:flex;flex-direction:column;transform:translateY(100%);transition:transform var(--duration-md,var(--duration-md)) var(--ease-out,var(--ease-out));padding-bottom:env(safe-area-inset-bottom,0);overflow:hidden}
.as-backdrop[data-open=true] + .as-sheet{transform:translateY(0)}
@media (min-width:720px){.as-sheet{left:auto;right:24px;bottom:24px;top:24px;max-width:480px;height:auto;max-height:calc(100dvh - 48px);border-radius:var(--radius-lg);transform:translateX(120%)}.as-backdrop[data-open=true] + .as-sheet{transform:translateX(0)}}
.as-handle{width:36px;height:4px;border-radius:var(--radius-2xs);background:var(--border-strong);margin:8px auto 4px;flex:none}
.as-head{padding:10px 16px 12px;display:flex;justify-content:space-between;align-items:flex-start;gap:12px;border-bottom:1px solid var(--border);flex:none;position:sticky;top:0;background:var(--surface-elevated);z-index:1}
.as-title-block{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.as-eyebrow{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);font-weight:600}
.as-title{margin:0;font-family:var(--font-display);font-size:20px;font-weight:400;line-height:1.1}
.as-totals{font-size:12px;color:var(--text-muted);font-variant-numeric:tabular-nums}
.as-nav{display:flex;gap:6px}
.as-nav button,.as-close{width:32px;height:32px;border-radius:var(--btn-radius);border:1px solid var(--border);background:var(--surface);font-size:14px;color:var(--text-muted);cursor:pointer;position:relative}
.as-nav button::after,.as-close::after{content:"";position:absolute;inset:-6px}
.as-body{flex:1 1 0;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:14px 16px 20px;display:flex;flex-direction:column;gap:14px;-webkit-overflow-scrolling:touch}
/* Prevent flex-shrink from collapsing content blocks — items must overflow to trigger scroll */
.as-body>*{flex-shrink:0}
/* Lock background scroll while a day/cohort sheet is open so scrolling inside .as-body never bubbles to <html>. Toggled by _openSheet / _closeSheet in lore-tab.js. */
body.has-as-sheet{overflow:hidden}

/* Sheet content blocks */
.sheet-hero{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px}
.sheet-hero-tile{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 8px;text-align:center;display:flex;flex-direction:column;gap:2px}
.sheet-hero-label{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);font-weight:600}
.sheet-hero-value{font-family:var(--font-sans);font-weight:700;font-size:18px;line-height:1.1;font-variant-numeric:tabular-nums}
.sheet-grade-strip{display:flex;height:12px;border-radius:var(--radius-tiny);overflow:hidden;background:var(--surface)}
.grade-strip-seg{height:100%}
.grade-strip-seg[data-grade="1"]{background:var(--grade-missed)}
.grade-strip-seg[data-grade="2"]{background:var(--grade-hazy)}
.grade-strip-seg[data-grade="3"]{background:var(--grade-honed)}
.grade-strip-seg[data-grade="4"]{background:var(--grade-mastered)}
.sheet-grade-legend{display:flex;justify-content:space-between;font-size:10px;color:var(--text-muted);padding:0 2px;margin-top:4px;font-variant-numeric:tabular-nums}
.sheet-grade-legend span{display:inline-flex;align-items:center;gap:4px}
.sheet-grade-legend i{width:8px;height:8px;border-radius:var(--radius-2xs);display:inline-block}
.sheet-curr-head{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);font-weight:600;margin-bottom:6px}
.sheet-phase-list{display:flex;flex-wrap:wrap;gap:4px}
.phase-chip{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:var(--radius-pill);font-size:11px;background:var(--surface);border:1px solid var(--border);color:var(--text-muted);font-variant-numeric:tabular-nums}
.phase-chip strong{color:var(--text);font-weight:600}

/* Nested sessions */
.session-block{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;margin-bottom:6px}
.session-block-head{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:10px 12px;cursor:pointer;min-height:44px;background:color-mix(in srgb,var(--accent) 4%,var(--surface))}
.session-block-time{display:flex;flex-direction:column;gap:1px;min-width:0}
.session-block-time strong{font-size:13px;color:var(--text);font-weight:600;font-variant-numeric:tabular-nums}
.session-block-time small{font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums}
.session-block-chev{font-size:12px;color:var(--text-faint);transition:transform var(--duration-sm) var(--ease-out)}
.session-block[data-open=true] .session-block-chev{transform:rotate(180deg)}
.session-block-body{padding:0 10px 10px;display:none;flex-direction:column;gap:6px}
.session-block[data-open=true] .session-block-body{display:flex}
.type-group{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}
.type-group-head{display:flex;justify-content:space-between;align-items:center;padding:6px 10px;border-left:2px solid var(--type-recall);background:var(--surface-elevated);min-height:32px;cursor:pointer;user-select:none}
.type-group[data-type=recall] .type-group-head{border-left-color:var(--type-recall)}
.type-group[data-type=saq] .type-group-head{border-left-color:var(--type-saq)}
.type-group[data-type=pharma] .type-group-head{border-left-color:var(--type-pharma)}
.type-group[data-type=axiom] .type-group-head{border-left-color:var(--type-axiom)}
.type-group-label{font-size:11px;letter-spacing:.04em;text-transform:uppercase;font-weight:600}
.type-group[data-type=recall] .type-group-label{color:var(--type-recall)}
.type-group[data-type=saq] .type-group-label{color:var(--type-saq)}
.type-group[data-type=pharma] .type-group-label{color:var(--type-pharma)}
.type-group[data-type=axiom] .type-group-label{color:var(--type-axiom)}
.type-group-meta{font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums;display:flex;align-items:center;gap:6px}
.type-group-chev{font-size:11px;color:var(--text-faint);transition:transform var(--duration-sm) var(--ease-out)}
.type-group[data-open=true] .type-group-chev{transform:rotate(180deg)}
.type-group-body{padding:6px 10px 8px;display:none;flex-direction:column;gap:3px;background:var(--surface)}
.type-group[data-open=true] .type-group-body{display:flex}

/* Card rows inside cohort sheets */
.card-row{display:grid;grid-template-columns:auto 1fr auto;gap:8px;padding:6px 8px;background:var(--surface);border-radius:var(--radius-tiny);align-items:center;font-size:12px;min-height:34px}
.card-row[data-cohort=atrisk]{background:color-mix(in srgb,var(--c-atrisk) 6%,var(--surface));border-left:2px solid var(--c-atrisk)}
.card-row[data-cohort=leech]{background:color-mix(in srgb,var(--c-leech) 6%,var(--surface));border-left:2px solid var(--c-leech)}
.card-grade-dot{width:9px;height:9px;border-radius:50%;flex:none}
.card-grade-dot[data-grade="1"]{background:var(--grade-missed)}
.card-grade-dot[data-grade="2"]{background:var(--grade-hazy)}
.card-grade-dot[data-grade="3"]{background:var(--grade-honed)}
.card-grade-dot[data-grade="4"]{background:var(--grade-mastered)}
.card-stem{color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12px}
.card-stem .card-topic-tag{font-size:9px;color:var(--text-faint);background:var(--surface-elevated);padding:1px 5px;border-radius:var(--radius-pill);margin-left:6px;white-space:nowrap}
.card-meta{font-size:10px;color:var(--text-faint);font-variant-numeric:tabular-nums;display:flex;gap:6px;align-items:center}
.cohort-sheet-action{background:var(--accent);color:var(--accent-on);padding:12px 16px;border-radius:var(--radius-sm);font-size:13px;font-weight:600;text-align:center;cursor:pointer;display:flex;justify-content:center;align-items:center;gap:6px;min-height:44px;border:0}
.cohort-sheet-meta{font-size:12px;color:var(--text-muted);line-height:1.5}
.cohort-sheet-meta strong{color:var(--text);font-weight:600;font-variant-numeric:tabular-nums}

/* Bulk-action bar (At-risk / Overdue drill sheets) */
.bulk-action-bar{display:flex;justify-content:space-between;align-items:center;padding:10px 12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);gap:8px}
.bulk-action-bar-left{display:flex;flex-direction:column;gap:2px;min-width:0}
.bulk-action-bar-label{font-size:12px;color:var(--text);font-weight:500}
.bulk-action-bar-sub{font-size:11px;color:var(--text-muted)}
.bulk-action-bar-btn{padding:8px 14px;border-radius:var(--btn-radius);font-size:12px;font-weight:600;cursor:pointer;border:0;background:var(--coral);color:#fff;min-height:36px;white-space:nowrap;flex:none}
.bulk-action-bar-btn:disabled{opacity:.4;cursor:not-allowed}
.bulk-preview{padding:8px 12px;background:var(--coral-fill);border:1px solid color-mix(in srgb,var(--coral-deep) 25%,transparent);border-radius:var(--radius-sm);font-size:12px;color:var(--coral-deep)}
.bulk-preview strong{font-weight:600}

/* FSRS health per-class cards (Layout A) */
.fsrs-health-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
@media (min-width:480px){.fsrs-health-grid{grid-template-columns:repeat(4,1fr)}}
.fsrs-health-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px;display:flex;flex-direction:column;gap:6px}
.fsrs-health-class{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);font-weight:600}
.fsrs-health-status{font-size:12px;color:var(--text);font-weight:500;line-height:1.3}
.fsrs-health-status[data-personalised=true]{color:var(--accent)}
.fsrs-health-refresh{font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums}
.fsrs-health-bar-wrap{display:flex;flex-direction:column;gap:2px}
.fsrs-health-bar-label{display:flex;justify-content:space-between;font-size:10px;color:var(--text-faint)}
.fsrs-health-bar{height:5px;border-radius:3px;background:var(--surface-elevated);overflow:hidden}
.fsrs-health-bar-fill{height:100%;border-radius:3px;width:0%}
.fsrs-health-bar-fill[data-quality=excellent]{background:var(--sage)}
.fsrs-health-bar-fill[data-quality=good]{background:var(--honey)}
.fsrs-health-bar-fill[data-quality=needs-work]{background:var(--coral)}
.fsrs-health-opt-bar{height:5px;border-radius:3px;background:var(--surface-elevated);overflow:hidden}
.fsrs-health-opt-fill{height:100%;background:var(--peri);border-radius:3px;width:0%}
.fsrs-health-cache-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-pill);font-size:10px;color:var(--text-faint)}
.fsrs-health-tech{display:flex;flex-direction:column;gap:2px;padding-top:4px;border-top:1px solid var(--border);font-size:10px;color:var(--text-faint);font-variant-numeric:tabular-nums}
/* i-toggle: plain-English vs technical mode */
.health-mode-toggle{display:inline-flex;align-items:center;gap:6px;padding:3px 8px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-pill);font-size:11px;color:var(--text-muted);cursor:pointer}
.health-mode-toggle[aria-pressed=true]{background:var(--accent-soft);color:var(--accent);border-color:transparent}

/* Info modal */
.as-info-backdrop{position:fixed;inset:0;background:var(--backdrop-sheet,rgba(0,0,0,.5));z-index:260;display:none}
.as-info-backdrop[data-open=true]{display:block}
.as-info-modal{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);background:var(--surface-elevated);border-radius:var(--radius-lg);max-width:420px;width:calc(100% - 32px);padding:20px;z-index:261;display:none;box-shadow:var(--shadow-lg);max-height:80vh;overflow-y:auto}
.as-info-modal[data-open=true]{display:block}
.as-info-modal h3{margin:0 0 10px;font-family:var(--font-display);font-size:18px;font-weight:400}
.as-info-modal p{margin:0 0 8px;font-size:13px;color:var(--text-muted);line-height:1.5}
.as-info-modal-close{padding:8px 14px;background:var(--accent);color:var(--accent-on);border-radius:var(--btn-radius);font-size:13px;font-weight:600;float:right;margin-top:8px;cursor:pointer;border:0}

/* Tooltip */
.as-tooltip{position:fixed;background:var(--text);color:var(--bg);padding:6px 10px;border-radius:var(--btn-radius);font-size:12px;pointer-events:none;z-index:300;white-space:nowrap;opacity:0;transform:translateY(4px);transition:opacity var(--duration-sm,var(--duration-sm)) var(--ease-out,var(--ease-out)),transform var(--duration-sm,var(--duration-sm)) var(--ease-out,var(--ease-out));box-shadow:var(--shadow-md)}
.as-tooltip[data-open=true]{opacity:1;transform:translateY(0)}

/* Skeleton loading states */
.as-skel{background:linear-gradient(90deg,var(--surface-elevated) 25%,color-mix(in srgb,var(--border) 60%,var(--surface-elevated)) 50%,var(--surface-elevated) 75%);background-size:200% 100%;animation:as-shimmer 1.4s ease-in-out infinite;border-radius:var(--radius-tiny)}
.as-skel-num{height:52px;width:100px;border-radius:var(--radius-sm)}
.as-skel-bar{height:10px;width:100%;max-width:420px;border-radius:5px}
.as-skel-row{height:20px;width:100%;border-radius:var(--radius-tiny)}
.as-cohort-skel{height:80px;border-radius:var(--radius)}

/* Cohort token vars — kept local so activity-surface.css is self-contained */
:root{
  --c-new:var(--peri,#786BC8); --c-learning:var(--honey,#C8861E); --c-mature:var(--sage,#4F7050);
  --c-atrisk:var(--coral,#C8625A); --c-leech:#8B2424; --c-overdue:#D8463F;
  --backdrop-sheet:rgba(0,0,0,.5);
}

/* ── Day-detail sheet: type chips, meta row, session rows ───────────── */
.cal-day-types{display:flex;flex-wrap:wrap;gap:6px}
.cal-day-meta{display:flex;flex-wrap:wrap;gap:10px;font-size:12px;color:var(--text-muted);font-variant-numeric:tabular-nums}
.cal-day-meta strong{color:var(--text);font-weight:600}
.cal-day-type{padding:3px 10px;border-radius:var(--radius-pill);font-size:11px;font-weight:600;display:inline-flex;align-items:center}
.cal-day-type--recall{background:color-mix(in srgb,var(--accent) 14%,transparent);color:var(--accent)}
.cal-day-type--saq{background:color-mix(in srgb,var(--peri,#786BC8) 14%,transparent);color:var(--peri,#786BC8)}
.cal-day-type--pharma{background:color-mix(in srgb,var(--coral) 14%,transparent);color:var(--coral-deep)}
.cal-day-type--axiom{background:color-mix(in srgb,var(--honey) 14%,transparent);color:var(--honey-deep,#865200)}
.cal-day-type-heading{padding:8px 0 4px;display:flex;align-items:center}
/* Session rows */
.cal-day-session{border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;background:var(--surface)}
.cal-day-session-hdr{display:flex;align-items:center;gap:8px;padding:10px 12px;cursor:pointer;min-height:44px;background:color-mix(in srgb,var(--accent) 4%,var(--surface));user-select:none;-webkit-user-select:none;box-sizing:border-box;width:100%}
.cal-day-session-hdr:hover{background:color-mix(in srgb,var(--accent) 8%,var(--surface))}
.cal-day-session-hdr[aria-expanded=true]{background:color-mix(in srgb,var(--accent) 8%,var(--surface));border-bottom:1px solid var(--border)}
.cal-day-session-title{font-size:13px;font-weight:600;color:var(--text);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cal-day-session-meta{font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums;white-space:nowrap;flex:none}
.cal-day-session-toggle{font-size:11px;color:var(--text-faint);transition:transform var(--duration-sm) ease;flex:none;min-width:20px;text-align:center}
.cal-day-session-hdr[aria-expanded=true] .cal-day-session-toggle{transform:rotate(90deg)}
.cal-day-session-ribbon{padding:8px 12px 12px;display:flex;flex-direction:column;gap:6px}
/* display:flex above overrides the UA [hidden] rule — force it back */
.cal-day-session-ribbon[hidden]{display:none}
/* Force vertical layout for ribbon-list inside session expansion */
.cal-day-session-ribbon .ribbon-list{display:flex!important;flex-direction:column!important;gap:3px;width:auto!important;flex-wrap:nowrap!important;overflow:visible!important}
/* Status badges */
.cal-status{padding:2px 8px;border-radius:var(--radius-pill);font-size:10px;letter-spacing:.04em;text-transform:uppercase;font-weight:600;flex:none;white-space:nowrap}
.cal-status.in-progress,.cal-status.in_progress{background:color-mix(in srgb,var(--honey) 18%,transparent);color:var(--honey-deep,#865200)}
.cal-status.completed{background:color-mix(in srgb,var(--sage) 18%,transparent);color:var(--sage-deep,#1F4020)}
.cal-status.draft{background:var(--surface-elevated);color:var(--text-faint)}
/* Archive/delete footer */
.cal-day-actions{margin-top:16px;padding-top:14px;border-top:1px solid var(--border);display:flex;flex-direction:column;gap:8px}
.cal-day-actions-help{margin:0;font-size:var(--font-size-xs);color:var(--text-faint);line-height:1.4;padding:0 2px}
.cal-day-del-btn{color:var(--grade-1,#e05252)!important}

/* ── Forecast day panel (future tile click) ──────────────────────────────── */
.fcast-phase-row{padding:4px 10px;border-radius:var(--radius-pill);background:color-mix(in srgb,var(--accent) 10%,transparent);font-size:var(--font-size-xs,11px);font-weight:600;color:var(--accent);display:inline-block;margin-bottom:8px}
.fcast-load-row{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:12px}
.fcast-load-chip{padding:3px 10px;border-radius:var(--radius-pill);font-size:var(--font-size-xs,11px);font-weight:600}
.fcast-load-chip--due{background:color-mix(in srgb,var(--honey) 20%,transparent);color:var(--honey-deep,#865200)}
.fcast-load-chip--new{background:color-mix(in srgb,var(--mint,var(--sage)) 20%,transparent);color:var(--sage-deep,#1F4020)}
.fcast-group-hdr{font-size:var(--font-size-xs,11px);font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint);margin:10px 0 4px}
.fcast-card{display:flex;flex-direction:column;gap:3px;padding:7px 10px;border-radius:var(--radius-sm);background:var(--surface-alt,var(--surface-elevated));margin-bottom:4px;border:1px solid var(--border);border-left:3px solid var(--border)}
/* Type accent — shares the design-system type tokens with .ribbon-card[data-type] */
.fcast-card[data-type=recall]{border-left-color:var(--accent)}
.fcast-card[data-type=saq]{border-left-color:var(--peri,#786BC8)}
.fcast-card[data-type=pharma]{border-left-color:var(--coral)}
.fcast-card[data-type=axiom]{border-left-color:var(--honey)}
.fcast-card-title{font-size:var(--font-size-sm,12px);font-weight:500;color:var(--text);line-height:1.35}
.fcast-card-reason{font-size:var(--font-size-xs,11px);color:var(--text-faint);font-variant-numeric:tabular-nums}

/* §5 Time-of-day Got% panel (G4) */
.tod-section{margin-top:18px;padding:16px;background:var(--surface-elevated);border:1px solid var(--border);border-radius:var(--radius-md)}
.tod-head{margin-bottom:10px}
.tod-head h2{margin:0 0 2px;font-size:13px;font-weight:600;color:var(--text);text-transform:uppercase;letter-spacing:.05em}
.tod-sub{font-size:11px;color:var(--text-faint)}
.tod-body{display:flex;flex-direction:column;gap:10px}
.tod-empty{padding:8px 2px;font-size:12px;color:var(--text-faint)}
.tod-spark{width:100%;height:64px;display:block}
.tod-callout{font-size:12px;color:var(--text);padding:6px 10px;background:color-mix(in srgb,var(--accent) 12%,transparent);border-radius:var(--radius-sm);font-weight:500}
.tod-table{width:100%;border-collapse:collapse;font-size:11px;font-variant-numeric:tabular-nums}
.tod-table th,.tod-table td{padding:4px 6px;text-align:left;border-bottom:1px solid var(--border)}
.tod-table th{font-weight:600;color:var(--text-faint);text-transform:uppercase;letter-spacing:.04em;font-size:10px}
.tod-table td:nth-child(2),.tod-table td:nth-child(3),.tod-table th:nth-child(2),.tod-table th:nth-child(3){text-align:right}

/* Keyframes */
@keyframes as-fadeIn{from{opacity:0}to{opacity:1}}
@keyframes as-pulse{0%,100%{opacity:.5}50%{opacity:1}}
@keyframes as-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}
@media (prefers-reduced-motion: reduce){
  .heatmap-resume-action .pulse{animation:none}
  .as-skel{animation:none}
}

/* =====================================================
   BADGE SYSTEM
   ===================================================== */
.badge-block-row{margin:16px 0}
.badge-block-header{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.badge-block-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.badge-block-name{font-size:var(--font-size-md);font-weight:600;color:var(--text)}
.badge-block-count{font-size:var(--font-size-xs);color:var(--text-muted);margin-left:auto}
.badge-shelf-scroll{display:flex;gap:10px;overflow-x:auto;padding-bottom:6px;scrollbar-width:none;}
.badge-shelf-scroll::-webkit-scrollbar{display:none}
.bslot{flex:0 0 88px;height:100px;border-radius:var(--radius);border:1px solid var(--border);background:var(--surface-alt2);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;cursor:pointer;transition:background .15s,color .15s,border-color .15s,box-shadow .15s,transform .15s,opacity .15s;position:relative;padding:8px 6px;text-align:center}
.bslot:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.bslot-icon{font-size:28px;line-height:1}
.bslot-name{font-size:var(--font-size-2xs);font-weight:600;color:var(--text);line-height:1.2}
.bslot-tier{font-size:9px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.04em}
.bslot.earned{border-color:var(--accent);background:var(--accent-soft);box-shadow:var(--shadow-glow)}
.bslot.earned .bslot-name{color:var(--accent-pressed)}
.bslot.earned .bslot-tier{color:var(--accent)}
.bslot-new-dot{position:absolute;top:6px;right:6px;width:8px;height:8px;border-radius:50%;background:var(--accent);border:1.5px solid var(--surface)}
.bslot.locked{filter:saturate(0.1);opacity:0.5}
.bslot.locked:hover{filter:saturate(0.2);opacity:0.65}
.bslot.hidden{border:1.5px dashed var(--border);background:var(--surface-alt2);filter:saturate(0);opacity:0.4}
.bslot.hidden .bslot-icon{font-size:var(--font-size-3xl);opacity:0.4}
@keyframes haulIn{0%{opacity:0;transform:translateY(24px) scale(0.85)}60%{transform:translateY(-4px) scale(1.04)}100%{opacity:1;transform:none;box-shadow:var(--shadow-glow)}}
.bslot.haul{animation:haulIn .45s var(--ease-spring) forwards}
.badge-sheet-backdrop{position:fixed;inset:0;z-index:var(--z-sheet);background:var(--backdrop-sheet);backdrop-filter:blur(2px);display:flex;align-items:flex-end;justify-content:center}
.badge-sheet-inner{background:var(--surface-elevated);border-radius:var(--radius-lg) var(--radius-lg) 0 0;width:100%;max-width:480px;max-height:90dvh;overflow-y:auto;overscroll-behavior:contain;padding:0 0 max(24px,env(safe-area-inset-bottom));animation:sheetUp var(--duration-md) ease-out}
@keyframes sheetUp{from{transform:translateY(100%)}to{transform:none}} /* WS5 canonical: full-slide bottom-sheet enter */
.badge-sheet-handle{width:36px;height:4px;border-radius:var(--radius-2xs);background:var(--border);margin:10px auto 0}
.badge-sheet-body{padding:20px;text-align:center}
.badge-sheet-icon{font-size:52px;margin-bottom:8px}
.badge-sheet-name{font-size:20px;font-weight:700;color:var(--text);margin-bottom:4px}
.badge-sheet-tier{font-size:var(--font-size-xs);font-weight:600;text-transform:uppercase;letter-spacing:0.06em;color:var(--accent);margin-bottom:10px}
.badge-sheet-desc{font-size:var(--font-size-lg);color:var(--text-muted);line-height:1.5;margin-bottom:16px}
.badge-sheet-criteria{background:var(--surface-alt);border-radius:var(--radius-md);padding:12px 14px;font-size:var(--font-size-md);line-height:1.55;text-align:left;margin-bottom:16px}
.badge-sheet-close{width:calc(100% - 40px);display:block;margin:0 20px;padding:14px;border:none;background:var(--surface-alt);border-radius:var(--radius-md);font-size:var(--font-size-lg);font-weight:600;color:var(--text);cursor:pointer}
.badge-sheet-close:hover{background:var(--border)}
.badge-global-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(80px,1fr));gap:10px;margin:13px 0}

/* =====================================================================
   v9.1 Phase 1 — CSS skeletons for Phase 2 wire-up
   --------------------------------------------------------------------
   These rules are authored now so the Phase 2 pass only edits renderers
   in app.js, not styles. Each rule is grouped by the §/AP it satisfies.
   See drift report §12 + brief §10 Phase 1.
   ===================================================================== */

/* §4D Recall card revealed-answer block — solid border + surface-elevated bg.
   Sprint J: .recall-answer selector removed (recallCard() now emits .fc-answer). */
.recall-card.revealed .fc-answer{
  display:block;
  background:var(--surface-elevated);
  border:1px solid var(--border);
  border-style:solid;
  border-radius:var(--radius-sm);
  padding:10px 12px;
  animation:fadeIn .18s ease both;
}

/* §4D Recall action bar — 50/50 split for Got it (§4A primary) /
   Missed (§4B ghost--danger). Phase 2 swaps the renderer to use this. */
.recall-action-bar{display:flex;gap:8px;margin-top:auto}
.recall-action-bar > *{flex:1}

/* §4D SRS due-state indicator — top-right of the status row. Three states:
   Due (accent), Overdue Nd (warn), Scheduled (text-faint). */
.recall-due{
  font-size:var(--font-size-2xs);font-weight:600;letter-spacing:0.05em;
  text-transform:uppercase;font-variant-numeric:tabular-nums;
  white-space:nowrap;
}
.recall-due--due       {color:var(--accent)}
.recall-due--overdue   {color:var(--warn)}
.recall-due--scheduled {color:var(--text-faint)}

/* §4B Ghost button — danger variant. Default border var(--border), text
   stays neutral; hover flips both to var(--err). Used for Missed action. */
.btn-ghost--danger{
  padding:8px 13px;
  border:1.5px solid var(--border);
  border-radius:var(--radius-sm);
  background:var(--surface);
  color:var(--text);
  font-size:var(--font-size-md);font-weight:600;font-family:inherit;
  cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.btn-ghost--danger:hover{
  border-color:var(--err);
  color:var(--err);
}

/* Today-fix v3 — Focus queue mini-card row. Rounded-rectangle pills
   replace the v2 circles so each slot can comfortably show the type
   letter at a readable size while still hinting card type via colour-
   coded border. Slide animation triggers on advance/undo via the
   parent .fc-queue-preview--forward / --back classes. The tooltip is
   rendered as a sibling .fc-queue-tooltip element (single, JS-managed)
   so it can escape parent overflow without ::after clipping issues. */
.fc-queue-preview{
  max-width:640px;
  width:calc(100% - 48px);
  margin:0 auto 4px;
  padding:0 0 12px;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:6px;
  position:relative;
  overflow:visible;
}
.fc-queue-preview[hidden]{display:none}
.fc-queue-dot{
  width:42px;height:30px;border-radius:var(--radius-sm);flex-shrink:0;
  border:1.5px solid currentColor;
  background:color-mix(in srgb,currentColor 8%,var(--surface));
  font-size:var(--font-size-xs);font-weight:700;font-family:inherit;
  font-variant-numeric:tabular-nums;letter-spacing:0.4px;
  cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;
  transition:transform var(--duration-sm),opacity var(--duration-sm),box-shadow var(--duration-sm),border-color var(--duration-sm);
  position:relative;
  opacity:0.85;
}
.fc-queue-dot:hover{transform:translateY(-1px);opacity:1;box-shadow:0 2px 8px color-mix(in srgb,currentColor 30%,transparent)}
/* patch-007 — done dots are now filled-in solids in their identity colour
   instead of low-opacity outlines. Reads as "card complete" at a glance and
   visually balances against future dots (outlined). */
.fc-queue-dot--past{
  background:currentColor;
  color:var(--bg);
  border-color:currentColor;
  opacity:0.85;
}
.fc-queue-dot--past:hover{opacity:1;color:var(--bg)}
.fc-queue-dot--current{
  width:50px;height:34px;font-size:var(--font-size-md);
  background:color-mix(in srgb,currentColor 18%,var(--surface));
  box-shadow:0 0 0 3px color-mix(in srgb,currentColor 22%,transparent);
  cursor:default;
}
.fc-queue-dot--current:hover{transform:none;opacity:0.85;box-shadow:0 0 0 3px color-mix(in srgb,currentColor 22%,transparent)}

/* Slide animation — direction-aware. When advancing, rectangles slide
   in from the right; on undo, from the left. The parent toggles a
   directional class for ~280ms which children animate against. */
@keyframes fcQueueSlideInRight{from{transform:translateX(14px);opacity:0}to{transform:translateX(0);opacity:0.85}}
@keyframes fcQueueSlideInLeft {from{transform:translateX(-14px);opacity:0}to{transform:translateX(0);opacity:0.85}}
.fc-queue-preview--forward .fc-queue-dot{animation:fcQueueSlideInRight var(--duration-lg) var(--ease-out) both}
.fc-queue-preview--back    .fc-queue-dot{animation:fcQueueSlideInLeft  var(--duration-lg) var(--ease-out) both}
@media(prefers-reduced-motion:reduce){
  .fc-queue-preview--forward .fc-queue-dot,
  .fc-queue-preview--back    .fc-queue-dot{animation:fadeIn .15s ease both}
}

/* Hover preview tooltip — single sibling element, JS-positioned. */
.fc-queue-tooltip{
  position:absolute;bottom:calc(100% + 6px);left:50%;
  transform:translateX(-50%);
  background:var(--surface-elevated);
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  padding:8px 10px;
  font-size:var(--font-size-sm);font-weight:400;line-height:1.4;
  color:var(--text);text-align:left;
  white-space:normal;width:260px;max-width:80vw;
  box-shadow:var(--shadow-md);
  opacity:0;pointer-events:none;
  transition:opacity var(--duration-sm);
  z-index:20;
  display:none;
}
.fc-queue-tooltip.visible{display:block;opacity:1}
.fc-queue-tooltip-head{
  font-size:var(--font-size-2xs);font-weight:700;letter-spacing:0.5px;
  text-transform:uppercase;
  color:var(--text-muted);
  margin-bottom:4px;
  display:flex;gap:6px;align-items:center;
}
.fc-queue-tooltip-head .ttip-type-dot{
  width:8px;height:8px;border-radius:50%;background:currentColor;
  display:inline-block;flex-shrink:0;
}

.fc-queue-counter{
  margin-left:8px;font-size:var(--font-size-xs);color:var(--text-muted);
  font-variant-numeric:tabular-nums;
  border-left:1px solid var(--border);padding-left:10px;
}

/* §4D Status row — type pill · counts · last seen [due-state →]. The
   Phase 2 renderer wraps the existing chip cluster into this layout. */
.recall-status-row{
  display:flex;align-items:baseline;gap:8px;
  font-size:var(--font-size-xs);color:var(--text-muted);
  padding-right:32px; /* clear ⋯ button at right:8px, width:24px */
}
.recall-status-row .recall-status-meta{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* §4D Type pill — tpill--{recall|saq|nemesis|fact}. Token-driven; light
   and dark resolve via the multi-accent aliasing in :root / html.dark. */
.tpill{
  display:inline-block;padding:2px 6px;border-radius:var(--radius-tiny);
  font-size:9px;font-weight:500;letter-spacing:0.05em;
  text-transform:uppercase;line-height:1.2;
}
.tpill--recall  {background:var(--sage-fill); color:var(--sage-deep);  border:0.5px solid color-mix(in srgb,var(--sage)  30%,transparent)}
.tpill--saq     {background:var(--honey-fill); color:var(--honey-deep);  border:0.5px solid color-mix(in srgb,var(--honey)  30%,transparent)}
.tpill--nemesis {background:var(--coral-fill);color:var(--coral-deep); border:0.5px solid color-mix(in srgb,var(--coral) 30%,transparent)}
.tpill--fact    {background:var(--sky-fill);  color:var(--sky-deep);   border:0.5px solid color-mix(in srgb,var(--sky)   30%,transparent)}

/* ============================================================
   patch-014 — Sessions today UI (pill strip, history modal,
   new-session wizard modal). Built with token vars only — the
   forthcoming UI redesign can re-skin via tokens without touching
   structural CSS or JS bindings.
   ============================================================ */

/* --- Sessions strip (pill row + history button) --- */
.sessions-strip{
  display:flex;align-items:center;gap:8px;
  margin:10px 0 0;padding:6px 0;
  border-bottom:1px solid var(--border);
}
.sessions-strip-pills{
  flex:1;min-width:0;
  display:flex;align-items:center;gap:6px;
  overflow-x:auto;scrollbar-width:none;
  padding:2px 0;
}
.sessions-strip-pills::-webkit-scrollbar{display:none}
.sessions-strip-history{
  display:inline-flex;align-items:center;gap:5px;flex-shrink:0;
  padding:6px 10px;border:1px solid var(--border);border-radius:var(--radius-sm);
  background:var(--surface);color:var(--text-muted);
  font-size:var(--font-size-sm);font-weight:500;font-family:inherit;cursor:pointer;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.sessions-strip-history:hover{border-color:var(--accent);color:var(--accent)}
.sessions-strip-history .icn{width:13px;height:13px}
.sessions-strip-history-label{display:inline}
@media(max-width:600px){.sessions-strip-history-label{display:none}}

/* --- Session pill (one per session row) --- */
.session-pill{
  display:inline-flex;align-items:center;gap:6px;flex-shrink:0;
  padding:11px 14px;min-height:44px;border-radius:var(--radius-pill);
  border:1px solid var(--border);background:var(--surface);
  color:var(--text-muted);font-size:var(--font-size-sm);font-weight:500;
  font-family:inherit;cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
  white-space:nowrap;
}
.session-pill:hover{border-color:var(--accent);color:var(--text)}
.session-pill.active{
  background:var(--accent-soft);color:var(--accent-pressed);
  border-color:var(--accent);font-weight:600;
}
html.dark .session-pill.active{color:var(--accent)}
.session-pill.completed{opacity:0.7}
.session-pill.draft{border-style:dashed}
.session-pill .pill-icon{width:11px;height:11px;flex-shrink:0}
.session-pill .pill-time{font-variant-numeric:tabular-nums;font-size:var(--font-size-xs);color:var(--text-faint)}
.session-pill.active .pill-time{color:var(--accent-pressed)}
html.dark .session-pill.active .pill-time{color:var(--accent)}

/* + Add new session pill */
.session-pill-add{
  display:inline-flex;align-items:center;gap:5px;flex-shrink:0;
  padding:7px 11px;border-radius:var(--radius-pill);
  border:1.5px dashed var(--border);background:transparent;
  color:var(--accent);font-size:var(--font-size-sm);font-weight:600;
  font-family:inherit;cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.session-pill-add:hover{border-color:var(--accent);background:var(--accent-soft)}
.session-pill-add .icn{width:13px;height:13px}

/* --- New session wizard modal --- */
.ns-modal{
  position:fixed;inset:0;z-index:var(--z-sheet);
  background:var(--backdrop-sheet);
  display:flex;align-items:center;justify-content:center;padding:18px;
  animation:backdropIn .15s;
}
html.dark .ns-modal{background:rgba(0,0,0,0.82)}
.ns-modal-card{
  background:var(--surface-elevated);border:1px solid var(--border);border-radius:var(--radius-lg);
  width:100%;max-width:460px;max-height:90dvh;overflow-y:auto;overscroll-behavior:contain;
  padding:18px 18px 22px;
  box-shadow:var(--shadow-lg);
  animation:sheetCentreIn var(--duration-md) ease-out;
}
/* Phase 4 — suppress translate animations for vestibular / reduced-motion users */
@media(prefers-reduced-motion:reduce){
  .ns-modal{animation:none}
  .ns-modal-card{animation:none}
}
.ns-modal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
/* v141 — h2 → 17px per DESIGN-SYSTEM §2 (was 18px). Weight 500 inherited. */
.ns-modal-head h2{margin:0;padding:0;border:none;font-size:var(--font-size-2xl)}
.ns-modal-close{
  background:none;border:none;color:var(--text-muted);cursor:pointer;
  padding:4px;border-radius:var(--btn-radius);display:inline-flex;align-items:center;
}
.ns-modal-close:hover{background:var(--surface-alt);color:var(--text)}
.ns-modal-close .icn{width:16px;height:16px}
.sheet-close .icn,.iib-dismiss .icn,.fc-close .icn,.bsb-close .icn{width:14px;height:14px}
/* Phase 4 — kb-shortcuts bottom sheet: slides up like badge sheet + pharma session builder */
#kbShortcutsOverlay > div{animation:sheetUp var(--duration-md) ease-out}
@media(prefers-reduced-motion:reduce){#kbShortcutsOverlay > div,.pharma-bulk-bar{animation:none}} /* H-P1-03: pharma-bulk-bar PRM guard (auto via sheetUp→H-P1-02) */

/* R-030 v126 — flag button is position:absolute top-right of card.
   No layout impact — removed from flex flow. Ghost at rest; filled icon when flagged.
   States: --mine (own flag, peri/purple), --others (others flagged, amber),
   --others-factual (others flagged factual error, red). Hover shows red ring. */
/* WS4 (2026-05-05): .recall-flag-btn renamed to .card-flag-btn (Q7). */
.card-flag-btn{
  position:absolute;top:8px;right:8px;
  width:24px;height:24px;border-radius:50%;
  background:transparent;border:none;cursor:pointer;padding:0;
  color:var(--text-muted);opacity:.28;
  display:flex;align-items:center;justify-content:center;
  transition:opacity var(--duration-sm),color var(--duration-sm),box-shadow var(--duration-sm);
  z-index:2;
}
.card-flag-btn:hover{opacity:1;box-shadow:0 0 0 2px var(--coral)}
/* Mine: current user flagged — peri (purple), filled icon, editable */
.card-flag-btn--mine{opacity:1;color:var(--peri)}
.card-flag-btn--mine svg{fill:var(--peri);stroke:var(--peri)}
/* Others: other users reported — amber warning, filled icon */
.card-flag-btn--others{opacity:1;color:var(--honey)}
.card-flag-btn--others svg{fill:var(--honey);stroke:var(--honey)}
/* Others-factual: factual error from another user — red, filled icon */
.card-flag-btn--others-factual{opacity:1;color:var(--grade-missed)}
.card-flag-btn--others-factual svg{fill:var(--grade-missed);stroke:var(--grade-missed)}
/* Legacy alias kept for any inline usages */
.card-flag-btn--active{opacity:1;color:var(--peri)}
.card-flag-btn--active svg{fill:var(--peri);stroke:var(--peri)}

/* =====================================================
   CARD OPTIONS MENU — ⋯ button replacing flag button
   patch-037 (pearl sprint)
   ===================================================== */
.card-options-btn{
  position:absolute;top:8px;right:8px;
  width:24px;height:24px;border-radius:50%;
  background:transparent;border:none;cursor:pointer;padding:0;
  color:var(--text-muted);opacity:.28;
  display:flex;align-items:center;justify-content:center;
  font-size:17px;line-height:1;letter-spacing:.5px;
  transition:opacity var(--duration-sm),color var(--duration-sm),box-shadow var(--duration-sm);
  z-index:2;
}
.card-options-btn:hover{opacity:1;box-shadow:0 0 0 2px var(--border)}
.card-options-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:3px}
.card-options-btn.has-flag{opacity:1}
.card-options-btn.has-pearl{opacity:1}
.card-options-btn.has-flag.has-pearl{opacity:1}

/* Indicator dots on the ⋯ button */
.card-options-dot{
  position:absolute;
  width:5px;height:5px;border-radius:50%;
  pointer-events:none;
}
.card-options-dot--flag{top:3px;right:3px;background:var(--peri)}
.card-options-dot--pearl{bottom:3px;right:3px;background:color-mix(in srgb,#fff 45%,var(--sky))}
html.dark .card-options-dot--pearl{background:color-mix(in srgb,#fff 35%,var(--sky))}

/* Dropdown menu — appended to document.body so it escapes any overflow:hidden ancestor */
.card-options-menu{
  position:fixed;
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-sm);
  box-shadow:0 4px 16px -4px rgba(0,0,0,.18);
  min-width:160px;z-index:9999;
  display:none;flex-direction:column;padding:4px 0;
  overflow:hidden;
}
.card-options-menu.is-open{display:flex}
.card-options-item{
  display:flex;align-items:center;gap:8px;
  padding:8px 12px;cursor:pointer;
  font-size:var(--font-size-sm);color:var(--text);
  background:transparent;border:none;font-family:inherit;
  text-align:left;width:100%;
  transition:background .1s;
}
.card-options-item:hover{background:var(--surface-alt)}
.card-options-item:disabled,.card-options-item[disabled]{
  color:var(--text-muted);opacity:.5;cursor:default;
}
.card-options-item:disabled:hover,.card-options-item[disabled]:hover{background:transparent}
.card-options-sep{height:1px;background:var(--border);margin:3px 0}

/* =====================================================
   PEARL — stripe, badge, card tint
   patch-037 (pearl sprint)
   ===================================================== */

/* Pearl stripe — satin highlight overlay over the left border.
   Uses ::before at left:-6px to cover the wider border area.
   Gradient: sky-deep flanks → pearl-white highlight at 50% */
/* recall-card pearl stripe — transparent border + ::before at left:-6px fills it.
   Dark-mode specificity note: html.dark .recall-card {border-left-color:var(--sage)}
   is [0,2,1] which beats .recall-card[data-is-pearl] [0,2,0], so we need an
   explicit html.dark .recall-card[data-is-pearl] rule to re-apply transparent. */
.recall-card[data-is-pearl]{
  border-left-width:6px;
  border-left-color:transparent;
}
html.dark .recall-card[data-is-pearl]{
  border-left-color:transparent;
}
.recall-card[data-is-pearl]::before{
  content:'';
  position:absolute;
  top:0;left:-6px;bottom:0;
  width:6px;
  border-radius:var(--radius) 0 0 var(--radius);
  background:linear-gradient(to bottom,
    var(--sky-deep) 0%,var(--sky-deep) 28%,
    color-mix(in srgb,#fff 55%,var(--sky)) 42%,
    color-mix(in srgb,#fff 70%,var(--sky)) 50%,
    color-mix(in srgb,#fff 55%,var(--sky)) 58%,
    var(--sky-deep) 72%,var(--sky-deep) 100%);
  pointer-events:none;
  z-index:0;
}
/* Dark mode: --sky = #8EA020 (Axiom lime-gold after WS9). Pearl recall must use
   --sage-deep / --sage = #79B9DD (Recall identity) to match card border colour. */
html.dark .recall-card[data-is-pearl]::before{
  background:linear-gradient(to bottom,
    var(--sage-deep) 0%,var(--sage-deep) 28%,
    color-mix(in srgb,#fff 35%,var(--sage)) 42%,
    color-mix(in srgb,#fff 50%,var(--sage)) 50%,
    color-mix(in srgb,#fff 35%,var(--sage)) 58%,
    var(--sage-deep) 72%,var(--sage-deep) 100%);
}
/* fc-card pearl stripe — border-left:0 removes the card-type stripe so ::before
   at left:0 covers the full left edge alone (single stripe).
   Cannot use left:-6px like recall-card because overflow-y:auto clips it. */
.fc-card[data-is-pearl]{
  padding-left:6px;
  border-left-width:0;
}
.fc-card[data-is-pearl]::before{
  content:'';
  position:absolute;
  top:0;left:0;bottom:0;
  width:6px;
  border-radius:var(--radius-lg) 0 0 var(--radius-lg);
  background:linear-gradient(to bottom,
    var(--sky-deep) 0%,var(--sky-deep) 28%,
    color-mix(in srgb,#fff 55%,var(--sky)) 42%,
    color-mix(in srgb,#fff 70%,var(--sky)) 50%,
    color-mix(in srgb,#fff 55%,var(--sky)) 58%,
    var(--sky-deep) 72%,var(--sky-deep) 100%);
  pointer-events:none;
  z-index:1;
}
html.dark .fc-card[data-is-pearl]::before{
  background:linear-gradient(to bottom,
    var(--sage-deep) 0%,var(--sage-deep) 28%,
    color-mix(in srgb,#fff 35%,var(--sage)) 42%,
    color-mix(in srgb,#fff 50%,var(--sage)) 50%,
    color-mix(in srgb,#fff 35%,var(--sage)) 58%,
    var(--sage-deep) 72%,var(--sage-deep) 100%);
}

/* Pearl sparkle badge in status row */
.recall-pearl-badge{
  font-size:13px;line-height:1;
  color:color-mix(in srgb,#fff 45%,var(--sky));
  cursor:default;
  flex-shrink:0;
}
html.dark .recall-pearl-badge{
  color:color-mix(in srgb,#fff 35%,var(--sky));
}
/* System pearl: filled ✦ — brighter */
.recall-pearl-badge--system{
  color:color-mix(in srgb,#fff 40%,var(--sky-deep));
  filter:drop-shadow(0 0 3px color-mix(in srgb,#fff 60%,var(--sky)));
}
html.dark .recall-pearl-badge--system{
  color:color-mix(in srgb,#fff 50%,var(--sky));
  filter:drop-shadow(0 0 3px color-mix(in srgb,#fff 40%,var(--sky)));
}
/* User pearl: outline ✧ — subtler */
.recall-pearl-badge--user{
  opacity:.75;
}

/* ─── Cluster badge (Task 4) ─────────────────────────────── */
/* Cluster pearl (cluster_size≥2): gradient background accent */
.recall-pearl-badge--cluster{
  background:linear-gradient(45deg,
    color-mix(in srgb,var(--sky-fill) 80%,transparent),
    color-mix(in srgb,var(--sky) 25%,transparent));
  border-radius:3px;padding:0 2px;
}
/* S-tier (strength≥25): brightness boost */
.recall-pearl-badge[data-pearl-strength="25"],
.recall-pearl-badge[data-pearl-strength="26"],
.recall-pearl-badge[data-pearl-strength="27"],
.recall-pearl-badge[data-pearl-strength="28"],
.recall-pearl-badge[data-pearl-strength="29"],
.recall-pearl-badge[data-pearl-strength="30"]{
  filter:brightness(1.15) drop-shadow(0 0 4px color-mix(in srgb,#fff 55%,var(--sky)));
}
.pearl-cluster-count{
  font-size:.72em;margin-left:1px;font-weight:600;
  vertical-align:super;line-height:1;
}

/* ─── R2: pick_reason why-badge (Wave 2) ─────────────────────────────────
   Small 11px pill on recall cards showing dominant pick reason.
   Colour-coded by category via modifier class — no inline styles. */
.recall-why-badge{
  display:inline-flex;align-items:center;
  font-size:11px;font-weight:500;line-height:1;
  padding:2px 5px;border-radius:var(--radius-tiny);
  flex-shrink:0;white-space:nowrap;
  cursor:default;
}
/* due: honey tint */
.recall-why-badge--due{
  background:color-mix(in srgb,var(--honey-fill) 70%,transparent);
  color:var(--honey-deep);
}
html.dark .recall-why-badge--due{
  background:color-mix(in srgb,var(--honey) 18%,transparent);
  color:var(--honey);
}
/* pearl: mint tint */
.recall-why-badge--pearl{
  background:color-mix(in srgb,var(--sage-fill) 70%,transparent);
  color:var(--sage-deep);
}
html.dark .recall-why-badge--pearl{
  background:color-mix(in srgb,var(--sage) 18%,transparent);
  color:var(--sage-fill);
}
/* weak / drift / lapse: coral tint */
.recall-why-badge--weak,
.recall-why-badge--drift,
.recall-why-badge--lapse{
  background:color-mix(in srgb,var(--coral-fill) 70%,transparent);
  color:var(--coral-deep);
}
html.dark .recall-why-badge--weak,
html.dark .recall-why-badge--drift,
html.dark .recall-why-badge--lapse{
  background:color-mix(in srgb,var(--coral) 18%,transparent);
  color:var(--coral);
}
/* new / preferred / quota / ahead: neutral muted (backfill tiers) */
.recall-why-badge--new,
.recall-why-badge--preferred,
.recall-why-badge--quota,
.recall-why-badge--ahead{
  background:color-mix(in srgb,var(--border) 60%,transparent);
  color:var(--text-muted);
}
html.dark .recall-why-badge--new,
html.dark .recall-why-badge--preferred,
html.dark .recall-why-badge--quota,
html.dark .recall-why-badge--ahead{
  background:color-mix(in srgb,var(--border) 40%,transparent);
  color:var(--text-muted);
}

/* ─── R7: post-rating FSRS overlay (Wave 2) ─────────────────────────────
   Transient one-line element appended below the card after rating.
   Fades in then fades out via class toggling. */
.recall-fsrs-overlay{
  font-size:11px;color:var(--text-muted);
  padding:4px 12px;
  opacity:0;
  transition:opacity 0.25s ease;
  pointer-events:none;
  font-variant-numeric:tabular-nums;
  letter-spacing:0.01em;
}
.recall-fsrs-overlay--visible{
  opacity:1;
}
.recall-fsrs-overlay--hidden{
  opacity:0;
  transition:opacity 0.4s ease;
}

/* ─── Pearl hovercard (Task 2) ───────────────────────────── */
.pearl-hovercard{
  position:absolute;
  z-index:900;
  max-width:320px;min-width:220px;
  background:var(--surface-elevated);
  border:1px solid var(--border-strong);
  border-radius:var(--radius);
  box-shadow:0 6px 24px -4px rgba(0,0,0,.18);
  padding:12px 14px;
  font-size:var(--font-size-sm);
  color:var(--text);
  pointer-events:auto;
}
.pearl-hovercard-hdr{
  font-weight:600;line-height:1.3;margin-bottom:6px;
  color:color-mix(in srgb,var(--sky-deep) 90%,var(--text));
}
.pearl-hovercard-sym{font-size:15px;margin-right:3px}
.pearl-hovercard-tier{
  display:inline-block;font-size:.78em;font-weight:700;
  background:color-mix(in srgb,var(--sky) 15%,transparent);
  color:var(--sky-deep);border-radius:3px;padding:1px 5px;
  margin-left:4px;
}
html.dark .pearl-hovercard-tier{
  background:color-mix(in srgb,var(--sky) 20%,transparent);
  color:color-mix(in srgb,#fff 70%,var(--sky));
}
.pearl-hovercard-div{
  height:1px;background:var(--border);margin:8px 0;
}
.pearl-hovercard-body{
  color:var(--text-muted);line-height:1.45;margin-bottom:6px;
}
.pearl-hovercard-quote{
  font-style:italic;color:var(--text-muted);line-height:1.5;
  margin-bottom:8px;
  border-left:3px solid var(--sky);padding-left:8px;
}
.pearl-hovercard-attr{
  font-style:normal;font-size:.85em;color:var(--text-faint);display:block;
  margin-top:3px;
}
.pearl-hovercard-link{
  display:block;width:100%;text-align:left;
  background:none;border:none;padding:0;cursor:pointer;
  color:var(--sky-deep);font-size:var(--font-size-sm);
  font-family:inherit;font-weight:600;
  transition:opacity .15s;
}
.pearl-hovercard-link:hover{opacity:.75}

/* ─── Pearl progress header chip (Task 3) ────────────────── */
.today-header-chip{
  display:inline-flex;align-items:center;gap:3px;
  font-size:var(--font-size-xs);
  padding:1px 6px;border-radius:var(--radius-md);
  border:1px solid var(--border);
  cursor:pointer;transition:background .15s;
  line-height:1.6;white-space:nowrap;
  margin-left:4px;
}
.today-header-chip:hover{background:var(--surface-elevated)}
.today-header-chip--pearl{
  color:var(--sky-deep);
  border-color:color-mix(in srgb,var(--sky) 35%,var(--border));
}
html.dark .today-header-chip--pearl{
  color:color-mix(in srgb,#fff 65%,var(--sky));
}
.pearl-icon{font-size:12px;display:inline-flex;align-items:center}
.pearl-icon .icn{width:11px;height:11px;flex-shrink:0;stroke-width:2}
.streak-flame{font-size:11px}
/* A13 — Axiom-of-block + session pearl mini-chips in the header meta row */
.hdr-chip{display:inline-flex;align-items:center;gap:2px;font-size:10px;font-weight:700;letter-spacing:0.05em;text-transform:uppercase;padding:1px 6px;border-radius:var(--radius-pill);line-height:1.6;white-space:nowrap;margin-left:4px}
.hdr-chip--axiom{color:var(--saltbush);border:1px solid color-mix(in srgb,var(--saltbush) 35%,var(--border));background:color-mix(in srgb,var(--saltbush) 8%,transparent)}
html.dark .hdr-chip--axiom{color:var(--saltbush)}

.ns-section{margin-bottom:16px}
.ns-section-label{
  font-size:var(--font-size-xs);font-weight:600;color:var(--text-muted);
  text-transform:uppercase;letter-spacing:0.05em;margin-bottom:7px;
}

.ns-template-chips{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
@media(max-width:480px){.ns-template-chips{grid-template-columns:repeat(2,1fr);max-height:130px;overflow-y:auto;-webkit-overflow-scrolling:touch}}
.ns-template-chip{
  padding:11px 8px;border:1px solid var(--border);background:var(--surface);
  color:var(--text);border-radius:var(--radius-sm);font-family:inherit;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;gap:3px;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.ns-template-chip:hover{border-color:var(--accent)}
.ns-template-chip.selected{
  background:var(--accent-soft);border-color:var(--accent);
  color:var(--accent-pressed);font-weight:600;
}
html.dark .ns-template-chip.selected{color:var(--accent)}
.ns-template-chip-name{font-size:var(--font-size-md);font-weight:600}
.ns-template-chip-meta{font-size:var(--font-size-xs);color:var(--text-muted)}
.ns-template-chip.selected .ns-template-chip-meta{color:var(--accent-pressed);opacity:0.85}
html.dark .ns-template-chip.selected .ns-template-chip-meta{color:var(--accent)}

.ns-time-row{display:flex;align-items:center;gap:10px}
.ns-time-input{
  width:80px;padding:8px 10px;border:1px solid var(--border);background:var(--surface);
  color:var(--text);border-radius:var(--btn-radius);font-family:inherit;font-size:var(--font-size-lg);
}
.ns-time-unit{color:var(--text-muted);font-size:var(--font-size-md)}

.ns-advanced{margin-bottom:16px}
.ns-advanced-summary{
  font-size:var(--font-size-sm);font-weight:500;color:var(--text-muted);cursor:pointer;
  list-style:none;padding:8px 0;display:flex;align-items:center;gap:7px;
}
.ns-advanced-summary::-webkit-details-marker{display:none}
/* DESIGN-SYSTEM §9: SVG mask (matches details>summary::before at L638-647) — no unicode triangles */
.ns-advanced-summary::before{
  content:"";display:inline-block;width:12px;height:12px;flex-shrink:0;
  background-color:var(--text-muted);
  -webkit-mask-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
          mask-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;
  transition:transform .15s;
}
.ns-advanced[open] .ns-advanced-summary::before{transform:rotate(90deg)}
.ns-advanced-body{padding-top:6px}
.ns-advanced-row{
  display:grid;grid-template-columns:1fr auto;gap:8px 10px;
  align-items:center;margin-bottom:6px;
}
.ns-advanced-row label{font-size:var(--font-size-md);color:var(--text)}
.ns-scope-select{
  padding:5px 8px;border:1px solid var(--border);background:var(--surface);
  color:var(--text);border-radius:var(--btn-radius);font-family:inherit;font-size:var(--font-size-sm);
  min-width:160px;cursor:pointer;
}
.ns-advanced-hint{font-size:var(--font-size-xs);color:var(--text-faint);margin-top:8px;line-height:1.4}

/* B+C hybrid — Smart Brief box */
.ns-brief-box{
  background:var(--surface-alt);border:1px solid var(--border);
  border-radius:var(--radius);padding:11px 13px 12px;margin-bottom:12px;
}
.ns-brief-top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:5px}
.ns-brief-rec{
  font-size:var(--font-size-md);font-weight:600;
  background:var(--accent-soft);border:1px solid var(--accent);
  border-radius:var(--radius-sm);padding:3px 9px;
  color:var(--accent-pressed);white-space:nowrap;flex-shrink:0;
}
html.dark .ns-brief-rec{color:var(--accent)}
.ns-brief-ctx{font-size:var(--font-size-xs);color:var(--text-faint);text-align:right;line-height:1.3}
.ns-brief-reason{font-size:var(--font-size-sm);color:var(--text-muted);line-height:1.45}
/* v143 — Loading state: skeleton shimmer in place of pill + reason while
   /api/sessions/preview resolves (cached path → instant; network → ~1s).
   Token-driven (var(--surface-alt2) → var(--border) sweep). PRM-guarded. */
@keyframes nsShimmer{
  0%   { background-position:-120% 0; }
  100% { background-position: 220% 0; }
}
.ns-skel{
  border-radius:var(--radius-sm);
  background:linear-gradient(90deg,
    var(--surface-alt2) 0%,
    var(--border)       50%,
    var(--surface-alt2) 100%);
  background-size:220% 100%;
  animation:nsShimmer 1.2s ease-in-out infinite;
}
.ns-skel--pill   { width:122px; height:22px; }
.ns-skel--ctx    { width:48px;  height:12px; }
.ns-skel--reason { width:78%;   height:13px; margin-top:2px; }
.ns-skel--reason.short { width:54%; }
.ns-brief-skel{
  display:none;
  flex-direction:column;
  gap:6px;
}
.ns-brief-skel-top{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
}
/* When loading: hide real content, show skeletons */
.ns-brief-box.is-loading .ns-brief-skel        { display:flex; }
.ns-brief-box.is-loading .ns-brief-top,
.ns-brief-box.is-loading .ns-brief-reason,
.ns-brief-box.is-loading .ns-brief-late,
.ns-brief-box.is-loading .ns-brief-lastmiss    { display:none; }
@media (prefers-reduced-motion: reduce){
  .ns-skel{ animation:none; opacity:.7; }
}
/* v141 — softened reason styling when user has overridden the recommendation.
   DESIGN-SYSTEM §2 doesn't list italic as a contentful style; differentiate
   by colour shift only (text-muted → text-faint) for compliance. */
.ns-brief-reason--user-pick{color:var(--text-faint)}
/* v141 — late-adopter + last-session miss banners (subordinate to reason).
   Body type bumped from 11px → 12px (§2: micro-labels are 10–11px reserved
   for uppercase 600 letter-spacing labels; these are sentence-case body).
   Dashed divider → solid 1px hairline + 8px top margin (system rhythm). */
/* v236 — Stacks shortcut row in wizard brief. 70/30 split: primary picker
   (filled, sky token) + secondary Manage (outline). Mirrors hero split. */
.ns-stacks-shortcut{
  display:flex;gap:6px;margin-top:8px;
}
.ns-stacks-pick-btn{
  flex:1;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:9px 12px;min-height:38px;border-radius:var(--radius-sm);
  border:1px solid color-mix(in srgb,var(--sky) 40%,var(--border));
  background:color-mix(in srgb,var(--sky) 12%,var(--surface-alt2));
  color:var(--sky-deep, var(--text));
  font-size:var(--font-size-md);font-weight:600;font-family:inherit;cursor:pointer;
  transition:background var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm);
}
.ns-stacks-pick-btn:hover{
  background:color-mix(in srgb,var(--sky) 20%,var(--surface-alt2));
  border-color:var(--sky);
}
.ns-stacks-pick-btn .icn{width:16px;height:16px;flex-shrink:0}
.ns-stacks-pick-label{flex:1;text-align:left}
.ns-stacks-pick-count{
  font-size:var(--font-size-xs);font-weight:500;opacity:0.7;
  padding:1px 7px;border-radius:var(--radius-md);
  background:color-mix(in srgb,var(--sky) 18%,transparent);
}
.ns-stacks-manage-btn{
  flex:0 0 auto;width:42px;
  display:inline-flex;align-items:center;justify-content:center;
  padding:0;min-height:38px;border-radius:var(--radius-sm);
  border:1px solid var(--border);background:transparent;color:var(--text-muted);
  cursor:pointer;transition:background var(--duration-sm),border-color var(--duration-sm);
}
.ns-stacks-manage-btn:hover{background:var(--surface-alt2);border-color:var(--sky);color:var(--text)}
.ns-stacks-manage-btn .icn{width:16px;height:16px}
html.dark .ns-stacks-pick-btn{color:var(--sky)}
.ns-brief-late,
.ns-brief-lastmiss{
  margin-top:8px;font-size:var(--font-size-sm);color:var(--text-faint);
  padding-top:6px;border-top:1px solid var(--border);
  line-height:1.4;
}
/* v140 — Empty / under-filled section hint card. Shown inside Recall / SAQ /
   Facts grids when the picker returns fewer cards than requested. */
.today-uf-hint{
  border:1px dashed var(--border);border-radius:var(--radius);
  padding:14px 14px 12px;background:var(--surface);
  display:flex;flex-direction:column;gap:6px;
  margin:8px 0;
}
.today-uf-heading{font-size:var(--font-size-md);font-weight:600;color:var(--text);line-height:1.35}
.today-uf-body{font-size:var(--font-size-sm);color:var(--text-muted);line-height:1.45}
.today-uf-cta{
  align-self:flex-start;margin-top:4px;
  font-size:var(--font-size-sm);font-weight:500;font-family:inherit;
  padding:6px 11px;border-radius:var(--radius-sm);
  background:var(--accent-soft);color:var(--accent-pressed);
  border:1px solid var(--accent);cursor:pointer;
  transition:background .15s,opacity .15s;
}
.today-uf-cta:hover{background:var(--accent);color:var(--accent-on)}
.today-uf-cta:active{opacity:.8}
html.dark .today-uf-cta{color:var(--accent)}
/* Customise disclosure (legacy <details>) — kept for back-compat with any
   sites that still reference .ns-customize, but the wizard's Customise is
   now a separate sub-modal (#wizardCustomiseModal) per v145. */
.ns-customize{margin-top:10px;margin-bottom:0;padding-top:4px;border-top:1px solid var(--border)}
.ns-customize .ns-advanced-body{padding-top:10px}
.ns-customize .ns-section{margin-bottom:12px}
.ns-customize .ns-section:last-child{margin-bottom:0}

/* v145 — Inverted-T action layout. Top: Start (primary, --accent fill).
   Bottom row: Revise + Customise (ghost). Revise hides via [hidden] and
   the row's grid-template-columns reflows to a single column. Token-driven;
   no semantic-colour collision with recall grade vocabulary. */
.ns-actions{
  display:flex;flex-direction:column;gap:8px;
}
.ns-actions-row{
  display:grid;grid-template-columns:1fr 1fr;gap:8px;
}
.ns-actions-row:has(> .ns-action[hidden]:first-child){
  grid-template-columns:1fr;  /* Revise hidden → Customise full-width */
}
.ns-action{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:11px 18px;border-radius:var(--radius-sm);
  font-size:var(--font-size-lg);font-weight:500;font-family:inherit;
  cursor:pointer;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.ns-action:disabled{opacity:.55;cursor:not-allowed;transform:none}
.ns-action .icn{width:16px;height:16px;flex-shrink:0}
.ns-action-start{
  background:var(--accent);color:white;
  border:1px solid var(--accent-pressed);
  box-shadow:0 2px 0 var(--accent-pressed);
  font-weight:700;
}
html.dark .ns-action-start{color:var(--bg)}
.ns-action-start:hover{transform:translateY(-1px);box-shadow:0 3px 0 var(--accent-pressed)}
.ns-action-start:active{transform:translateY(1px);box-shadow:0 1px 0 var(--accent-pressed)}
.ns-action-revise,
.ns-action-customise,
.ns-action-secondary{
  background:var(--surface);color:var(--text);
  border:1px solid var(--border);
}
.ns-action-revise:hover,
.ns-action-customise:hover,
.ns-action-secondary:hover{
  border-color:var(--accent);color:var(--accent);
  background:var(--surface-alt);
}
.ns-action-revise:active,
.ns-action-customise:active,
.ns-action-secondary:active{transform:scale(0.98)}
.ns-action-drill{
  width:100%;
  background:var(--surface);color:var(--text);
  border:1px solid var(--border);
  padding:13px 18px;font-weight:500;
}
.ns-action-drill:hover{border-color:var(--accent);color:var(--accent);background:var(--surface-alt)}
.ns-action-drill:active{transform:scale(0.99)}

/* v147 — Targeted-session button: full-width row with icon left + 2-line
   body (name + 1-line description). Same hover/active treatment as ghost
   action buttons. Stacked with 8px gap inside the section. */
.ns-targeted-section{padding-top:6px}
.ns-targeted-section .ns-action-target + .ns-action-target{margin-top:8px}
.ns-action-target{
  width:100%;
  background:var(--surface);color:var(--text);
  border:1px solid var(--border);
  padding:11px 14px;
  display:flex;align-items:center;gap:12px;justify-content:flex-start;text-align:left;
  font-weight:500;
}
.ns-action-target:hover{border-color:var(--accent);color:var(--accent);background:var(--surface-alt)}
.ns-action-target:active{transform:scale(0.99)}
.ns-action-target .icn{width:18px;height:18px;flex-shrink:0}
.ns-target-body{
  display:flex;flex-direction:column;gap:2px;min-width:0;flex:1;
}
.ns-target-name{font-size:var(--font-size-lg);font-weight:500;color:inherit}
.ns-target-desc{font-size:var(--font-size-sm);color:var(--text-muted);line-height:1.35;font-weight:400}
.ns-action-target:hover .ns-target-desc{color:var(--text-muted)}

/* Customise sub-modal — back button echoes ns-modal-close geometry */
.ns-modal-back{
  width:32px;height:32px;border-radius:50%;
  background:transparent;border:1px solid transparent;
  display:inline-flex;align-items:center;justify-content:center;
  cursor:pointer;color:var(--text-muted);font-family:inherit;
  margin-right:auto;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm);
}
.ns-modal-back:hover{background:var(--surface-alt);color:var(--text)}
.ns-modal-back .icn{width:18px;height:18px}

/* Customise modal footer actions — Back + Start side-by-side */
.ns-customise-actions{
  display:grid;grid-template-columns:auto 1fr;gap:8px;
  margin-top:14px;padding-top:14px;
  border-top:1px solid var(--border);
}
.ns-customise-actions .ns-action-secondary{
  padding-left:16px;padding-right:16px;
}

/* Drill section — sits before the footer in the customise modal */
.ns-drill-section{padding-top:6px}

/* ── 1.11 — Wizard refactor CSS ────────────────────────────────────────────── */
/* Saved presets row */
.wiz-presets-row{
  display:flex;gap:8px;overflow-x:auto;padding-bottom:4px;
  scrollbar-width:none;-ms-overflow-style:none;
}
.wiz-presets-row::-webkit-scrollbar{display:none}
.wiz-presets-empty{
  font-size:var(--font-size-sm);color:var(--text-faint);
  padding:8px 2px;font-style:italic;line-height:1.4
}
.wiz-preset-chip{
  flex-shrink:0;display:flex;flex-direction:column;gap:2px;
  padding:8px 12px;border:1px solid var(--border);
  border-radius:var(--radius-sm);background:var(--surface);
  cursor:pointer;font-family:inherit;text-align:left;
  min-width:80px;transition:border-color var(--duration-sm),background var(--duration-sm)
}
.wiz-preset-chip:hover{border-color:var(--accent);background:var(--accent-soft)}
.wiz-preset-chip:active{transform:scale(.97)}
.wiz-preset-name{font-size:var(--font-size-sm);font-weight:600;color:var(--text);line-height:1.2}
.wiz-preset-meta{font-size:var(--font-size-xs);color:var(--text-faint);font-variant-numeric:tabular-nums}

/* Time range + section hint */
.ns-section-hint{font-size:var(--font-size-xs);color:var(--text-faint);font-weight:400;margin-left:6px}
.wiz-time-display{
  float:right;font-size:var(--font-size-sm);font-weight:700;
  color:var(--accent);font-variant-numeric:tabular-nums
}
.wiz-range{
  -webkit-appearance:none;appearance:none;
  width:100%;height:4px;border-radius:var(--radius-2xs);
  background:var(--border-strong);outline:none;cursor:pointer;
  margin:8px 0 4px;display:block
}
.wiz-range::-webkit-slider-thumb{
  -webkit-appearance:none;width:18px;height:18px;border-radius:50%;
  background:var(--accent);border:2px solid var(--surface-elevated);
  box-shadow:0 1px 4px rgba(0,0,0,.18);cursor:pointer
}
.wiz-range::-moz-range-thumb{
  width:16px;height:16px;border-radius:50%;
  background:var(--accent);border:2px solid var(--surface-elevated);cursor:pointer
}
.wiz-range:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.wiz-range-labels{
  display:flex;justify-content:space-between;
  font-size:var(--font-size-xs);color:var(--text-faint);margin-bottom:2px
}

/* Mix sliders */
.wiz-range--mix{margin:4px 0}
.wiz-mix-row{display:flex;flex-direction:column;gap:0;margin-bottom:10px}
.wiz-mix-row:last-child{margin-bottom:0}
.wiz-mix-label{
  display:flex;justify-content:space-between;align-items:baseline;
  font-size:var(--font-size-sm);color:var(--text-muted)
}
.wiz-mix-val{
  font-size:var(--font-size-xs);font-weight:700;
  color:var(--accent);font-variant-numeric:tabular-nums
}

/* Scope select */
.wiz-scope-row{display:flex}
.wiz-scope-select{
  width:100%;padding:8px 10px;border:1px solid var(--border);
  border-radius:var(--radius-sm);background:var(--surface);
  color:var(--text);font-family:inherit;font-size:var(--font-size-sm);
  cursor:pointer;outline:none;
}
.wiz-scope-select:focus-visible{border-color:var(--accent);outline:2px solid var(--accent);outline-offset:1px}

/* Tag tokens + input */
.wiz-tag-list{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:6px;min-height:4px}
.wiz-tag-token{
  display:inline-flex;align-items:center;gap:3px;
  padding:2px 8px 2px 10px;border-radius:var(--radius-pill);
  background:var(--accent-soft);color:var(--accent-deep,var(--accent));
  font-size:var(--font-size-xs);font-weight:600;
}
.wiz-tag-rm{
  background:none;border:none;padding:0;cursor:pointer;
  color:inherit;opacity:.6;font-size:13px;line-height:1;margin-left:1px
}
.wiz-tag-rm:hover{opacity:1}
.wiz-tag-input{
  width:100%;padding:7px 10px;border:1px solid var(--border);
  border-radius:var(--radius-sm);background:var(--surface);
  color:var(--text);font-family:inherit;font-size:var(--font-size-sm);
  outline:none;
}
.wiz-tag-input:focus{border-color:var(--accent)}
.wiz-tag-input::placeholder{color:var(--text-faint)}

/* Wizard footer: Save preset (ghost) + Start (primary) */
.wiz-footer{
  display:flex;gap:8px;align-items:center;
  margin-top:14px;padding-top:14px;
  border-top:1px solid var(--border);
}
.wiz-footer .btn--ghost{
  display:inline-flex;align-items:center;gap:6px;
  padding:10px 14px;border-radius:var(--radius-sm);
  border:1px solid var(--border);background:var(--surface);
  color:var(--text-muted);font-family:inherit;font-size:var(--font-size-sm);
  cursor:pointer;white-space:nowrap;transition:border-color var(--duration-sm),color var(--duration-sm)
}
.wiz-footer .btn--ghost:hover{border-color:var(--accent);color:var(--accent)}
.wiz-footer .btn--ghost .icn{width:14px;height:14px;flex-shrink:0}
.wiz-footer .ns-action-start{flex:1}
/* ── end 1.11 wizard CSS ────────────────────────────────────────────────────── */

/* v149 — Replay-mode banner. Amber/warn fill signals "different mode, pay
   attention" without reading as an error. Uses --warn-bg / --warn / --honey
   tokens already in the system. */
.replay-banner{
  background:var(--warn-bg);
  border:1px solid var(--warn);
  border-radius:var(--radius);
  padding:9px 13px;
  margin-bottom:11px;
  font-size:var(--font-size-md);line-height:1.45;
  color:var(--warn);
  display:flex;align-items:baseline;flex-wrap:wrap;gap:2px;
}
html.dark .replay-banner{color:var(--warn)}
.replay-banner strong{font-weight:500}
.replay-banner-body{color:var(--text-muted)}

/* drag handle — shown only on mobile bottom-sheet */
.ns-drag-handle{
  width:36px;height:4px;border-radius:var(--radius-2xs);
  background:var(--border);margin:0 auto 14px;
  display:none;flex-shrink:0;
}
@media(max-width:600px){
  .ns-modal{padding:0;align-items:flex-end;justify-content:stretch}
  .ns-modal-card{
    border-radius:var(--radius-lg) var(--radius-lg) 0 0;border-bottom:none;
    max-width:none;width:100%;
    /* iOS-render: cap to viewport minus safe-area-inset-top so the card top
       can never sit under the notch / Dynamic Island when the URL bar is
       expanded (88dvh alone could overlap by ~14pt on iPhone Pro). */
    max-height:min(88dvh, calc(100dvh - env(safe-area-inset-top, 0px) - 24px));
    padding-bottom:max(24px,env(safe-area-inset-bottom));
    animation:sheetUp var(--duration-md) ease-out;
  }
  .ns-drag-handle{display:block}
}
/* v141 — Widen the header session-wizard trigger so the click target
   fills the full middle grid column (almost edge-to-edge — flanked only
   by avatar left + icon row right). Hover highlight is painted via a
   pseudo-element that extends ABOVE the element via negative inset, so
   the affordance reads as "the whole strip is clickable" all the way
   up to the viewport top. Token-driven (no hardcoded colours). */
@media(pointer:fine){
  .app-title.sw-trigger{
    cursor:pointer;
    position:relative;
    justify-self:stretch;
    width:100%;
    padding:6px 12px;
    border-radius:var(--radius-sm);
    transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
  }
  .app-title.sw-trigger::before{
    content:"";
    position:absolute;
    inset:-18px 0 0 0;            /* matches .app-header padding-top */
    border-radius:0 0 var(--radius-sm) var(--radius-sm);
    background:transparent;
    transition:background var(--duration-sm);
    pointer-events:none;
    z-index:0;
  }
  .app-title.sw-trigger > *{ position:relative; z-index:1; }
  .app-title.sw-trigger:hover::before,
  .app-title.sw-trigger:focus-visible::before{
    background:var(--surface-alt);
  }
  .app-title.sw-trigger:active{ opacity:.85; }
  .app-title.sw-trigger:focus-visible{
    outline:2px solid var(--accent);
    outline-offset:-1px;
  }
}
@media(pointer:fine) and (max-width:600px){
  /* Mobile pointer-fine: match smaller .app-header padding-top (14px) */
  .app-title.sw-trigger::before{ inset:-14px 0 0 0; }
}

/* --- Sessions history modal — card list --- */
.sessions-history-list{display:flex;flex-direction:column;gap:10px}
.sh-card{
  border:1px solid var(--border);border-radius:var(--radius);
  padding:12px;background:var(--surface);
  display:grid;grid-template-columns:1fr auto;gap:8px;align-items:start;
}
.sh-card.active{border-color:var(--accent);background:var(--accent-soft)}
.sh-card-meta{display:flex;flex-direction:column;gap:3px;min-width:0}
.sh-card-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.sh-card-template{font-size:var(--font-size-lg);font-weight:600;color:var(--text)}
.sh-card-status{
  font-size:var(--font-size-xs);font-weight:600;text-transform:uppercase;letter-spacing:0.04em;
  padding:1px 6px;border-radius:var(--radius-tiny);
}
.sh-card-status.in_progress{background:var(--accent-soft);color:var(--accent-pressed)}
html.dark .sh-card-status.in_progress{color:var(--accent)}
.sh-card-status.draft{background:var(--surface-alt);color:var(--text-muted)}
.sh-card-status.completed{background:var(--surface-alt);color:var(--text-muted)}
.sh-card-time{font-size:var(--font-size-sm);color:var(--text-muted);font-variant-numeric:tabular-nums}
.sh-card-stats{font-size:var(--font-size-sm);color:var(--text-muted);display:flex;align-items:center;gap:8px}
.sh-card-ribbon-toggle{background:none;border:none;padding:0;font-size:var(--font-size-sm);color:var(--accent);cursor:pointer;font-family:inherit;flex:0 0 auto}
.sh-card-ribbon-toggle:hover{text-decoration:underline}
.sh-card-ribbon{display:flex;flex-direction:column;gap:3px;margin-top:6px}
.sh-card-ribbon-empty{font-size:var(--font-size-sm);color:var(--text-faint)}
.sh-card-ribbon .study-ribbon{font-size:var(--font-size-xs);padding:6px 9px;min-height:28px}
.sh-card-ribbon .study-ribbon-summary{font-size:var(--font-size-xs);padding:6px 9px;margin-bottom:3px}
.sh-card-actions{display:flex;flex-direction:column;gap:6px;align-items:flex-end}
.sh-card-action{
  background:none;border:1px solid var(--border);color:var(--text-muted);
  padding:5px 9px;border-radius:var(--btn-radius);font-size:var(--font-size-sm);cursor:pointer;
  font-family:inherit;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.sh-card-action:hover{border-color:var(--accent);color:var(--accent)}
.sh-card-action--danger:hover{border-color:var(--coral);color:var(--coral)}
.sh-empty{
  text-align:center;color:var(--text-muted);padding:20px;
  font-size:var(--font-size-md);font-style:italic;
}

/* patch-013 — per-type scope preference selects in Settings panel */
.scope-pref-select{
  padding:5px 8px;border:1px solid var(--border);background:var(--surface);
  color:var(--text);border-radius:var(--btn-radius);font-family:inherit;font-size:var(--font-size-sm);
  min-width:170px;cursor:pointer;
}
.scope-pref-select:focus{outline:2px solid var(--accent);outline-offset:1px}

/* ============================================================
   iOS UX hardening — Day 1 polish (multi-user readiness)
   ============================================================
   Goals:
     1. ≥44pt touch targets per Apple HIG on coarse pointers.
     2. Suppress webkit gray tap flash on all interactive elements.
     3. Disable double-tap zoom on buttons/tabs (touch-action: manipulation).
     4. Use dynamic viewport height (dvh) on full-screen overlays so the
        iOS keyboard doesn't push content off-screen.
     5. Honor safe-area-inset on the sign-in overlay so notch / home-bar
        don't crowd the form.

   All overrides are additive at the END of the stylesheet so existing
   layout rules win on desktop / wide screens. Touch-only adjustments
   are gated behind @media (pointer: coarse).
   ============================================================ */

/* (1) Suppress iOS gray tap flash + (2) disable double-tap zoom on tap
   targets. Applied universally — looks better on desktop touchscreens too. */
button, a, .tab, .gear-tap, .icon-btn, .setup-pill, .opt,
[role="button"], [data-tap], [tabindex]:not([tabindex="-1"]) {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

@media (pointer: coarse) {
  /* Touch-target hardening — visual size unchanged, hit area grown. */
  .gear-tap          { min-width: 44px; min-height: 44px; }
  .tab               { min-height: 44px; }
  .icon-btn          { min-width: 44px; min-height: 44px; }
  .account-btn       { min-width: 44px; min-height: 44px; }
  .setup-pill        { min-height: 44px; }
  .setup-dropdown .opt { min-height: 44px; padding-top: 12px; padding-bottom: 12px; }
  .btn-primary-fw    { min-height: 44px; }
  .focus-trigger     { min-height: 44px; }
  .focus-action      { min-height: 44px; }
  /* iOS-004 — focus mode controls */
  .fc-close          { min-width: 44px; min-height: 44px; }
  .fc-undo-btn       { min-height: 44px; padding-top: 10px; padding-bottom: 10px; }
  .bsb-close         { min-width: 44px; min-height: 44px; }
}

/* (4) Full-screen overlays — use dvh (dynamic viewport height) so the
   iOS keyboard subtracts from the available height. Falls back to vh
   on iOS Safari < 16 / older browsers. */
.signin-overlay,
.focus-overlay {
  height: 100vh;
  height: 100dvh;
}

/* (5) Sign-in overlay safe-area awareness. Existing padding:32px stays
   for desktop; touch device gets max() so notch / home-bar add to it. */
.signin-overlay {
  padding-top:    max(32px, env(safe-area-inset-top));
  padding-bottom: max(32px, env(safe-area-inset-bottom));
  padding-left:   max(32px, env(safe-area-inset-left));
  padding-right:  max(32px, env(safe-area-inset-right));
}

/* iOS standalone (installed PWA) form input: prevent the auto-zoom-on-focus
   that triggers when input font-size < 16px. The sign-in / search inputs
   already use 16px+ in body styles, but pin defensively. Also covers
   <select> elements which are equally subject to iOS auto-zoom. */
input[type="email"],
input[type="text"],
input[type="search"],
input[type="number"],
select,
textarea {
  font-size: max(16px, 1em);
}

/* (6) Overscroll / rubber-band control.
   body: none → disables pull-to-refresh / elastic bounce on the root.
   Scrollable sheets/panels get 'contain' so they can scroll internally
   without the motion leaking out to the body (iOS propagates scroll at
   the top/bottom edge of any overflow:auto container upward to the body
   by default, which causes the whole page to rubber-band while the sheet
   is still in use). This is a pure feel improvement — no layout impact. */
body {
  overscroll-behavior: none;
}
.settings-panel,
.overlay .sheet,
.search-results,
.fc-stage,
.fc-body,
.ns-modal-card,
.badge-sheet-inner,
.sheet-overlay .sheet,
.sheet-overlay .sheet--bottom,
.preview-overlay {
  overscroll-behavior: contain;
}

/* Phase 2 sheet engine — lock the background while a bottom sheet is open so a
   drag/flick on the sheet can never scroll the page behind it (curriculum and
   textbooks overlays already lock via their own body classes; these families
   did not). Mirrors the existing body:has(.focus-overlay.active) cinema lock. */
body:has(.sheet-overlay),
body:has(.sheet-backdrop),
body:has(.refs-sheet-overlay){
  overflow:hidden;
  overscroll-behavior:none;
}

/* Composite the sheet as a single GPU layer while it is being dragged / flung /
   sprung — paints the (heavy) box-shadow once into the layer instead of every
   frame. sheet.js toggles .sheet--dragging for the whole motion lifecycle.
   Toggled (not permanent) so the sheet's overflow scroll is unaffected at rest. */
.sheet--dragging{ will-change:transform; }

/* Suspend backdrop-filter blur for the whole gesture. Animating an element that
   HAS a backdrop-filter (e.g. the frosted .curriculum-overlay-sheet) — or that
   moves INSIDE a backdrop-filtered scrim — forces the browser to recompute the
   blur every frame, which is the sheet-slide jank. The dim scrim colour stays;
   only the (invisible-while-moving) blur drops, restored at rest. Mirrors the
   cinema .fc-card--motion "flatten effects during motion" pattern. */
.sheet--dragging{ backdrop-filter:none !important; -webkit-backdrop-filter:none !important; }
.sheet-overlay:has(.sheet--dragging),
.sheet-backdrop:has(.sheet--dragging),
.refs-sheet-overlay:has(.sheet--dragging){
  backdrop-filter:none !important;
  -webkit-backdrop-filter:none !important;
}

/* ===================================================== */
/* Sprint B PR3 — Exam Mode launcher (SAQ-only)          */
/* Reuses .ns-modal shell; rose accent overrides since   */
/* SAQ identity is rose, not the global --accent token.  */
/* ===================================================== */
.em-modal-host .ns-modal-card.em-card{
  /* override default ns-modal-card: full-flex column so .em-body can scroll
     while head + curriculum + foot stay pinned. */
  display:flex;flex-direction:column;
  padding:18px 0 0;
  max-width:520px;
  overflow:hidden;
}
.em-modal-host .ns-modal-head{margin:0;padding:0 20px}
.em-sub{
  margin:2px 20px 14px;
  font-size:var(--font-size-md);color:var(--text-muted);
}
.em-modes{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:6px;padding:0 20px;margin-bottom:12px;flex-shrink:0;
}
.em-mode{
  appearance:none;border:1px solid var(--border);
  background:var(--surface2);color:var(--text-muted);
  font-family:inherit;font-size:var(--font-size-sm);font-weight:500;
  padding:10px 6px;border-radius:var(--btn-radius);cursor:pointer;
  display:flex;flex-direction:column;align-items:center;gap:5px;
  text-align:center;line-height:1.15;min-height:62px;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm);
}
.em-mode:hover{
  background:color-mix(in srgb,var(--rose-deep) 8%,var(--surface2));
  color:var(--text);
  border-color:color-mix(in srgb,var(--rose-deep) 30%,var(--border));
}
.em-mode[aria-selected="true"]{
  background:var(--rose-deep);color:#fff;border-color:var(--rose-deep);
  box-shadow:0 1px 3px color-mix(in srgb,var(--rose-deep) 35%,transparent);
}
.em-mode:focus-visible{outline:2px solid var(--rose-deep);outline-offset:2px}
.em-mode svg{width:18px;height:18px;stroke-width:1.75;stroke:currentColor;fill:none;stroke-linecap:round;stroke-linejoin:round}
.em-mode .em-mode-label{font-size:var(--font-size-xs);letter-spacing:.005em}

/* Curriculum trigger — reuses .lib-chip pattern */
.em-curric{margin:0 20px 12px;flex-shrink:0}
.em-curric-trigger{
  appearance:none;font-family:inherit;cursor:pointer;width:100%;
  display:flex;align-items:center;gap:6px;
  background:var(--surface);color:var(--text-muted);
  border:1px solid var(--border);border-radius:var(--btn-radius-pill);
  padding:6px 10px 6px 12px;font-size:var(--font-size-sm);line-height:1.3;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm);
}
.em-curric-trigger:hover{
  border-color:var(--border-strong,var(--border));color:var(--text);
}
.em-curric-trigger:focus-visible{outline:2px solid var(--rose-deep);outline-offset:2px}
.em-curric-trigger.is-active{
  background:color-mix(in srgb,var(--rose-deep) 8%,var(--surface));
  border-color:color-mix(in srgb,var(--rose-deep) 35%,var(--border));
  color:var(--text);
}
.em-curric-icon{flex:0 0 auto;width:14px;height:14px;color:var(--text-faint)}
.em-curric-prefix{color:var(--text-faint);font-weight:500}
.em-curric-sep{color:var(--text-faint);opacity:.6;margin:0 2px}
.em-curric-value{
  flex:1;min-width:0;text-align:left;color:var(--text);font-weight:500;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.em-curric-caret{flex:0 0 auto;width:13px;height:13px;color:var(--text-faint)}

/* Sub-form sections */
.em-body{
  padding:4px 20px 6px;
  flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;
}
.em-form{display:none}
.em-form[data-active="true"]{display:block}
.em-form-sub{margin:0 0 12px;font-size:var(--font-size-md);color:var(--text-muted)}
.em-form-head{margin:0 0 12px}
.em-form-title{margin:0;font-size:var(--font-size-xl);font-weight:600;color:var(--text);line-height:1.25}
.em-form-head .em-form-sub{margin:2px 0 0}

/* Field row helpers */
.em-row{display:flex;gap:10px;margin-bottom:12px}
.em-field{flex:1;min-width:0}
.em-label{
  display:block;font-size:var(--font-size-xs);font-weight:600;
  color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em;
  margin-bottom:4px;
}
.em-input{
  width:100%;appearance:none;
  background:var(--surface-bright);color:var(--text);
  border:1px solid var(--border);border-radius:var(--btn-radius);
  padding:8px 10px;font-family:inherit;font-size:var(--font-size-lg);
  font-variant-numeric:tabular-nums;
  transition:border-color var(--duration-sm),box-shadow var(--duration-sm);
}
.em-input:focus{outline:none;border-color:var(--rose-deep);box-shadow:0 0 0 3px color-mix(in srgb,var(--rose-deep) 22%,transparent)}
.em-meta{
  font-size:var(--font-size-sm);color:var(--text-faint);
  font-variant-numeric:tabular-nums;margin:-4px 0 14px;
}

/* Toggle switch */
.em-toggle{
  display:flex;align-items:flex-start;gap:10px;
  padding:10px 12px;border:1px solid var(--border);
  border-radius:var(--btn-radius);background:var(--surface-elevated);
  margin-bottom:14px;cursor:pointer;
  transition:border-color var(--duration-sm),background var(--duration-sm);width:100%;text-align:left;
  font-family:inherit;
}
.em-toggle:hover{border-color:var(--border-strong)}
.em-toggle-knob{
  flex:0 0 auto;width:34px;height:20px;
  background:var(--surface2);border-radius:var(--radius-pill);
  position:relative;transition:background var(--duration-sm);margin-top:1px;
}
.em-toggle-knob::after{
  content:"";position:absolute;top:2px;left:2px;
  width:16px;height:16px;border-radius:var(--radius-pill);
  background:var(--surface-bright);
  box-shadow:var(--shadow-sm);
  transition:transform .14s var(--ease-out-quart);
}
.em-toggle[aria-checked="true"] .em-toggle-knob{background:var(--rose-deep)}
.em-toggle[aria-checked="true"] .em-toggle-knob::after{transform:translateX(14px)}
.em-toggle-text{flex:1;min-width:0}
.em-toggle-title{font-size:var(--font-size-md);font-weight:600;color:var(--text);line-height:1.2;display:block}
.em-toggle-sub{font-size:var(--font-size-sm);color:var(--text-muted);margin-top:2px;line-height:1.35;display:block}
.em-toggle:focus-visible{outline:2px solid var(--rose-deep);outline-offset:2px}

/* Sitting pill grid */
.em-sittings{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
.em-sit{
  appearance:none;font-family:inherit;cursor:pointer;
  background:var(--surface2);color:var(--text-muted);
  border:1px solid var(--border);border-radius:var(--btn-radius-pill);
  padding:6px 12px;font-size:var(--font-size-sm);font-weight:500;
  font-variant-numeric:tabular-nums;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm);
}
.em-sit:hover{border-color:var(--rose-deep);color:var(--text)}
.em-sit[aria-pressed="true"]{
  background:var(--rose-fill);color:var(--rose-deep);
  border-color:var(--rose-deep);font-weight:600;
  box-shadow:0 0 0 2px color-mix(in srgb,var(--rose-deep) 25%,transparent);
}
.em-sit:focus-visible{outline:2px solid var(--rose-deep);outline-offset:2px}

/* Readiness drill table */
.em-readiness{
  border:1px solid var(--border);border-radius:var(--btn-radius);
  background:var(--surface-elevated);overflow:hidden;margin-bottom:10px;
}
.em-readiness-row{
  display:grid;grid-template-columns:1fr auto auto;
  gap:10px;align-items:center;
  padding:9px 12px;font-size:var(--font-size-md);
  border-bottom:1px solid var(--border);
}
.em-readiness-row:last-child{border-bottom:none}
.em-readiness-name{color:var(--text);font-weight:500}
.em-readiness-pct{color:var(--text-muted);font-variant-numeric:tabular-nums;font-size:var(--font-size-sm)}
.em-readiness-time{
  color:var(--rose-deep);font-weight:600;
  font-variant-numeric:tabular-nums;font-size:var(--font-size-md);
  min-width:48px;text-align:right;
}
.em-readiness-foot{font-size:var(--font-size-xs);color:var(--text-faint);margin:-4px 0 14px}

/* Weakness chips (Readiness drill) — same shape as curriculum chips,
   default-selected; last chip locked. */
.em-weak{
  background:var(--surface);
  border:1px solid var(--border);border-radius:var(--btn-radius);
  padding:10px 12px 12px;margin-bottom:10px;
}
.em-weak-head{
  display:flex;align-items:baseline;justify-content:space-between;gap:8px;
  margin-bottom:8px;
}
.em-weak-title{
  font-size:var(--font-size-xs);font-weight:600;letter-spacing:.04em;
  text-transform:uppercase;color:var(--text-muted);
}
.em-weak-strip{display:flex;flex-wrap:wrap;gap:5px}
.em-weak-chip{
  appearance:none;font-family:inherit;cursor:pointer;flex-shrink:0;
  background:var(--surface2);color:var(--text-muted);
  border:1px solid var(--border);border-radius:var(--btn-radius-pill);
  padding:4px 10px;font-size:var(--font-size-xs);font-weight:500;line-height:1.2;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm);
  white-space:nowrap;
}
.em-weak-chip:hover{border-color:var(--rose);color:var(--text)}
.em-weak-chip[aria-selected="true"]{
  background:var(--rose);color:#fff;
  border-color:var(--rose);font-weight:600;
}
.em-weak-chip[aria-disabled="true"]{cursor:not-allowed;opacity:.95}
.em-weak-chip:focus-visible{outline:2px solid var(--rose);outline-offset:2px}
.em-weak-chip-pct{
  margin-left:4px;color:var(--text-faint);font-weight:500;
  font-variant-numeric:tabular-nums;
}
.em-weak-chip[aria-selected="true"] .em-weak-chip-pct{
  color:color-mix(in srgb,#fff 70%,var(--rose));
}
.em-weak-meta{
  font-size:var(--font-size-xs);color:var(--text-faint);
  margin:8px 0 0;font-variant-numeric:tabular-nums;
}

/* Sitting break-flow info row */
.em-replay-flow{
  display:flex;align-items:flex-start;gap:8px;
  background:var(--surface2);
  border:1px solid var(--border);border-radius:var(--btn-radius);
  padding:9px 11px;font-size:var(--font-size-sm);color:var(--text-muted);
  line-height:1.45;margin-top:10px;
}
.em-replay-flow-icon{flex:0 0 auto;color:var(--rose-deep);margin-top:1px}
.em-replay-flow-icon svg{width:14px;height:14px}
.em-replay-flow-text{flex:1;min-width:0}

/* Sticky Start button */
.em-foot{padding:10px 20px 18px;flex-shrink:0;border-top:1px solid var(--border);background:var(--surface-elevated)}
.em-start{
  appearance:none;border:none;cursor:pointer;font-family:inherit;
  width:100%;background:var(--rose-deep);color:#fff;
  font-weight:700;font-size:var(--font-size-lg);letter-spacing:.05em;
  padding:13px 16px;border-radius:var(--btn-radius);
  box-shadow:0 1px 3px color-mix(in srgb,var(--rose-deep) 35%,transparent);
  transition:background var(--duration-sm),transform var(--duration-sm),box-shadow var(--duration-sm);
}
.em-start:hover{background:var(--rose)}
.em-start:active{transform:translateY(1px)}
.em-start:focus-visible{outline:2px solid var(--rose-deep);outline-offset:2px}
.em-start[disabled]{
  background:var(--surface2);color:var(--text-faint);
  box-shadow:none;cursor:not-allowed;
}

/* ===================================================== */
/* R-01 · FSRS status chip on focus-mode cards           */
/* ===================================================== */
.fc-type-row{display:flex;align-items:center;gap:6px;flex-shrink:0;padding-right:36px}
.fc-status-chip{font-size:var(--font-size-2xs);font-weight:600;letter-spacing:.04em;padding:2px 8px;border-radius:var(--btn-radius);margin-left:auto;white-space:nowrap;flex-shrink:0}
.fc-status-chip--due{background:var(--sage-fill);color:var(--sage-deep)}
.fc-status-chip--overdue{background:var(--coral-fill);color:var(--coral-deep)}
.fc-status-chip--scheduled{background:var(--surface-alt);color:var(--text-muted)}
/* ===================================================== */
/* R-02 · Confidence ghost chips (pre-reveal)            */
/* ===================================================== */
.fc-confidence{display:flex;gap:6px;padding:0 16px 12px;flex-shrink:0}
.fc-confidence-chip{flex:1;padding:8px 4px;border:1.5px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-alt);font-size:var(--font-size-sm);font-weight:500;color:var(--text-muted);cursor:pointer;text-align:center;line-height:1.25;transition:background var(--duration-sm),color var(--duration-sm),border-color .12s}
.fc-confidence-chip:hover{border-color:var(--accent);color:var(--accent)}
.fc-confidence-chip.selected{background:var(--accent-soft);border-color:var(--accent);color:var(--accent);font-weight:700}
/* Per-chip palette: Guess=coral, Unsure=amber, Certain=violet — resting fill + selected state */
.fc-confidence-chip[data-grade="1"]{background:color-mix(in srgb,var(--coral-vivid) 9%,var(--surface));border-color:color-mix(in srgb,var(--coral-vivid) 35%,var(--border));color:var(--coral-deep)}
.fc-confidence-chip[data-grade="2"]{background:color-mix(in srgb,var(--honey) 9%,var(--surface));border-color:color-mix(in srgb,var(--honey) 35%,var(--border));color:var(--honey-deep)}
.fc-confidence-chip[data-grade="4"]{background:color-mix(in srgb,var(--violet) 9%,var(--surface));border-color:color-mix(in srgb,var(--violet) 35%,var(--border));color:var(--violet-deep)}
.fc-confidence-chip[data-grade="1"].selected{background:var(--coral-fill);border-color:var(--coral-vivid);color:var(--coral-deep)}
.fc-confidence-chip[data-grade="2"].selected{background:var(--honey-fill);border-color:var(--honey);color:var(--honey-deep)}
.fc-confidence-chip[data-grade="4"].selected{background:var(--violet-fill);border-color:var(--violet);color:var(--violet-deep)}
/* iOS-007 — :active feedback for tap */
.fc-confidence-chip:active{transform:scale(0.96)}
/* Cinema scope: cream card surface — force cream-relative fills */
.focus-overlay .fc-confidence-chip[data-grade="1"]{background:color-mix(in srgb,var(--coral-vivid) 10%,#F5F1E6);border-color:color-mix(in srgb,var(--coral-vivid) 40%,rgba(0,0,0,.08));color:var(--coral-deep)}
.focus-overlay .fc-confidence-chip[data-grade="2"]{background:color-mix(in srgb,var(--honey) 10%,#F5F1E6);border-color:color-mix(in srgb,var(--honey) 40%,rgba(0,0,0,.08));color:var(--honey-deep)}
.focus-overlay .fc-confidence-chip[data-grade="4"]{background:color-mix(in srgb,var(--violet) 10%,#F5F1E6);border-color:color-mix(in srgb,var(--violet) 40%,rgba(0,0,0,.08));color:var(--violet-deep)}
.focus-overlay .fc-confidence-chip:hover{color:var(--text);border-color:var(--text-muted);background:color-mix(in srgb,var(--text) 5%,transparent)}
.fc-type-chip:active{opacity:1;transform:scale(0.92)}
.nem:active{transform:translateY(1px);box-shadow:none}
.setup-dropdown .opt:active{background:var(--surface-alt)}
.fc-callout-btn:active{transform:translateY(1px)}
/* F8 — .flipped unified into .revealed (SAQ migrated in F0). */
.fc-card.revealed .fc-confidence{display:none}
.fc-card.revealed .fc-timer-pomodoro{display:none}
/* ===================================================== */
/* R-03 · Day-complete ritual sheet                      */
/* ===================================================== */
.dc-icon{font-size:38px;margin-bottom:6px}
.dc-title{font-size:21px;font-weight:500;margin:0 0 4px;font-family:var(--font-display)}
.dc-sub{font-size:var(--font-size-lg);color:var(--text-muted);margin:0 0 18px;line-height:1.4}
.dc-stats{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:20px}
.dc-stat{background:var(--surface-alt);border-radius:var(--radius-md);padding:12px 8px;text-align:center}
.dc-stat-val{font-size:var(--font-size-3xl);font-weight:700;color:var(--accent);font-family:var(--font-display)}
.dc-stat-lbl{font-size:var(--font-size-xs);color:var(--text-muted);margin-top:3px}
.dc-missed-note{font-size:var(--font-size-sm);color:var(--text-muted);padding:10px 12px;background:var(--surface-alt);border-radius:var(--radius-sm);margin-bottom:16px;line-height:1.4}
/* ===================================================== */
/* R-07 · Block-start delight banner                     */
/* ===================================================== */
.block-start-banner{position:fixed;bottom:env(safe-area-inset-bottom,0px);left:0;right:0;z-index:210;background:var(--surface-elevated);border-top:1px solid var(--border);padding:14px 18px max(18px,env(safe-area-inset-bottom));display:flex;align-items:flex-start;gap:12px;box-shadow:0 -4px 20px rgba(0,0,0,.14);animation:sheetCentreIn .3s var(--ease-spring)}
.block-start-banner.hidden{display:none!important}
.bsb-icon{font-size:var(--font-size-3xl);flex-shrink:0;margin-top:2px}
.bsb-body{flex:1;min-width:0}
.bsb-title{font-size:var(--font-size-lg);font-weight:700;color:var(--text);margin:0 0 3px}
.bsb-sub{font-size:var(--font-size-md);color:var(--text-muted);margin:0}
.bsb-close{flex-shrink:0;background:none;border:none;font-size:20px;color:var(--text-muted);cursor:pointer;padding:4px;line-height:1;border-radius:var(--btn-radius)}
.bsb-close:hover{background:var(--surface-alt)}
/* ===================================================== */
/* ONBOARDING WIZARD (patch-011)                         */
/* ===================================================== */
.ob-wrap{
  min-height:100vh;
  min-height:100dvh; /* iOS Safari URL-bar aware */
  display:flex;align-items:center;justify-content:center;
  padding:max(24px,env(safe-area-inset-top,0)) max(24px,env(safe-area-inset-right,0)) max(24px,env(safe-area-inset-bottom,0)) max(24px,env(safe-area-inset-left,0));
  background:var(--bg);
}
.ob-card{
  width:100%;max-width:480px;background:var(--surface);
  border:1px solid var(--border);border-radius:var(--radius-lg);
  padding:36px 32px 32px;box-shadow:var(--shadow-md);
  position:relative; /* anchor for .ob-cancel absolute positioning */
}
@media(max-width:540px){
  .ob-card{padding:28px 20px 24px;}
}
.ob-dots{
  display:flex;gap:8px;margin-bottom:28px;
}
.ob-dot{
  width:8px;height:8px;border-radius:50%;
  background:var(--border-strong);transition:background var(--duration-md);
}
.ob-dot.active{background:var(--accent);}
.ob-title{
  font-family:var(--font-display);font-size:var(--font-size-3xl);font-weight:400;
  margin:0 0 6px;letter-spacing:-0.005em;color:var(--text);
}
.ob-sub{
  font-size:var(--font-size-lg);color:var(--text-muted);margin:0 0 28px;
}
.ob-field{margin-bottom:20px;}
.ob-label{
  display:block;font-size:var(--font-size-md);font-weight:600;
  color:var(--text-muted);margin-bottom:6px;letter-spacing:0.01em;
  text-transform:uppercase;
}
.ob-input,.ob-select{
  width:100%;padding:10px 13px;
  border:1px solid var(--border);border-radius:var(--radius-sm);
  background:var(--surface-bright);color:var(--text);
  font-family:var(--font-sans);font-size:max(16px,1em);
  transition:border-color .15s,box-shadow .15s;
  appearance:none;-webkit-appearance:none;
  box-sizing:border-box;
}
.ob-select{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='8' fill='none' stroke='%2357524A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center;
  padding-right:34px;cursor:pointer;
}
html.dark .ob-select{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='8' fill='none' stroke='%23C2CCC5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1l6 6 6-6'/%3E%3C/svg%3E");
}
.ob-input:focus,.ob-select:focus{
  outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft);
}
.ob-hint{font-size:var(--font-size-sm);color:var(--text-faint);margin-top:5px;}
.ob-hint a{color:var(--accent);text-decoration:none;cursor:pointer;}
.ob-hint a:hover{text-decoration:underline;}
.ob-tz-row{display:flex;align-items:center;gap:8px;}
.ob-tz-row .ob-input{flex:1;}
.ob-tz-change{
  font-size:var(--font-size-sm);color:var(--accent);background:none;border:none;
  cursor:pointer;padding:0;font-family:inherit;text-decoration:underline;
  white-space:nowrap;
}
/* Notifications step */
.ob-notif-row{
  display:flex;align-items:flex-start;gap:12px;
  padding:14px 0;border-bottom:1px solid var(--border);
}
.ob-notif-row:last-child{border-bottom:none;}
.ob-notif-row.disabled{opacity:0.45;pointer-events:none;}
.ob-toggle{
  position:relative;width:38px;height:22px;flex-shrink:0;margin-top:1px;
}
.ob-toggle input{opacity:0;width:0;height:0;position:absolute;}
.ob-toggle-track{
  position:absolute;inset:0;border-radius:11px;
  background:var(--border-strong);cursor:pointer;transition:background var(--duration-md);
}
.ob-toggle input:checked ~ .ob-toggle-track{background:var(--accent);}
.ob-toggle-thumb{
  position:absolute;top:3px;left:3px;width:16px;height:16px;
  border-radius:50%;background:white;transition:transform var(--duration-md); /* O-P2-01 */
  pointer-events:none;
}
.ob-toggle input:checked ~ .ob-toggle-track .ob-toggle-thumb{transform:translateX(16px);}
.ob-notif-body{flex:1;}
.ob-notif-label{font-size:var(--font-size-lg);font-weight:600;color:var(--text);margin-bottom:4px;}
.ob-notif-sub{font-size:var(--font-size-md);color:var(--text-muted);}
.ob-radio-group{display:flex;gap:8px;margin-top:8px;flex-wrap:wrap;}
.ob-radio{
  display:flex;align-items:center;gap:5px;
  font-size:var(--font-size-md);color:var(--text-muted);cursor:pointer;
}
.ob-radio input{accent-color:var(--accent);cursor:pointer;}
.ob-radio input:checked + span{color:var(--text);font-weight:600;}
/* Actions row */
.ob-actions{
  display:flex;justify-content:space-between;align-items:center;
  margin-top:30px;gap:12px;
}
/* O-P2-08 — transition contract: §7 mandates var(--duration-sm); was .15s across all ob-* buttons */
.ob-btn-primary{
  padding:11px 24px;background:var(--accent);color:white; /* O-P2-02 */
  border:none;border-radius:var(--radius-sm);font-size:var(--font-size-lg);font-weight:600;
  font-family:var(--font-sans);cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
  letter-spacing:0.01em;
}
.ob-btn-primary:hover{background:var(--accent-pressed);transform:translateY(-1px);}
.ob-btn-primary:active{transform:translateY(0);}
.ob-btn-primary:disabled{opacity:0.55;cursor:not-allowed;transform:none;}
html.dark .ob-btn-primary{color:var(--bg);}
.ob-btn-ghost{
  padding:11px 16px;background:none;color:var(--text-muted);
  border:1px solid var(--border);border-radius:var(--radius-sm);
  font-size:var(--font-size-lg);font-family:var(--font-sans);cursor:pointer;
  transition:background var(--duration-sm),color var(--duration-sm),border-color var(--duration-sm),box-shadow var(--duration-sm),transform var(--duration-sm),opacity var(--duration-sm);
}
.ob-btn-ghost:hover{border-color:var(--border-strong);color:var(--text);}
/* O-P2-04 — Cancel/close button for re-run path. Hidden on first-run (JS adds
   .ob-cancel--visible when onboarding_completed_at is already set). */
.ob-cancel{
  position:absolute;top:16px;right:16px;
  width:32px;height:32px;border-radius:50%;
  background:var(--surface-alt);border:1px solid var(--border);
  display:none;align-items:center;justify-content:center;cursor:pointer;
  transition:background var(--duration-sm),border-color var(--duration-sm);
}
.ob-cancel.ob-cancel--visible{display:flex}
.ob-cancel:hover{background:var(--surface-alt2);border-color:var(--border-strong)}
.ob-cancel .icn{width:14px;height:14px;color:var(--text-muted)}
/* O-P2-05 — Skip-hint line below actions */
.ob-skip-hint{font-size:var(--font-size-sm);color:var(--text-faint);text-align:center;margin-top:8px}
.ob-warn{
  font-size:var(--font-size-md);color:var(--warn);margin-top:4px;display:none;
}
.ob-err{
  font-size:var(--font-size-md);color:var(--err);margin-top:12px;display:none;
  padding:10px 12px;background:var(--coral-fill); /* O-P2-03: dropped fallback hex */
  border-radius:var(--radius-sm);
}
/* O-redesign — mockup-standard wizard chrome */
.ob-err--inline{margin-top:6px;padding:8px 10px;font-size:var(--font-size-sm);}
.ob-progress{display:flex;gap:6px;margin:2px 0 18px;}
.ob-seg{flex:1;height:4px;border-radius:var(--radius-2xs);background:var(--border);}
.ob-seg.done{background:var(--accent);}
.ob-seg.current{background:var(--accent);opacity:.55;}
.ob-eyebrow{display:block;font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--accent);margin-bottom:8px;}
.ob-optional{font-weight:400;color:var(--text-faint);}
.ob-primer{display:flex;gap:9px;font-size:var(--font-size-md);line-height:1.5;color:var(--text-muted);
  background:var(--surface-alt2,var(--surface));border:1px dashed var(--border-strong);border-radius:var(--radius-sm);
  padding:11px 12px;margin-bottom:18px;}
.ob-primer-ico{font-size:16px;flex:0 0 auto;}
.ob-primer b{color:var(--text);}
.ob-sec-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:4px;max-height:46vh;overflow-y:auto;
  padding:2px;margin-left:-2px;margin-right:-2px;}
.ob-sec{display:flex;align-items:center;gap:9px;padding:11px;border-radius:var(--radius-sm);min-width:0;
  border:1px solid var(--border-strong);background:var(--surface);cursor:pointer;text-align:left;font:inherit;color:var(--text);}
.ob-sec-badge{width:26px;height:26px;flex:0 0 auto;border-radius:7px;display:flex;align-items:center;justify-content:center;
  font-size:13px;font-weight:700;color:#fff;background:var(--accent);}
.ob-sec-name{flex:1;min-width:0;font-size:var(--font-size-sm);font-weight:600;line-height:1.2;color:var(--text-muted);overflow-wrap:anywhere;}
.ob-sec.sel{border-color:var(--accent);background:var(--accent-fill);box-shadow:0 0 0 1px var(--accent);}
.ob-sec.sel .ob-sec-name{color:var(--accent);}
.ob-toggle-card{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);overflow:hidden;}
.ob-tc-row{display:flex;align-items:center;gap:12px;padding:13px 14px;border-bottom:1px solid var(--border);}
.ob-tc-row:last-child{border-bottom:none;}
.ob-tc-meta{flex:1;}
.ob-tc-title{font-size:var(--font-size-md);font-weight:650;color:var(--text);}
.ob-tc-desc{font-size:var(--font-size-sm);color:var(--text-faint);margin-top:2px;line-height:1.4;}
.ob-tc-subs{padding:0 14px;background:var(--bg-sunken,var(--surface));transition:opacity .15s;}
.ob-tc-subs .ob-tc-row{padding:11px 0;}
/* A-P1-02: Admin accordion chevron — SVG-mask ::before pattern.
   Matches §9 disclosure caret from details>summary::before.
   Toggle via .admin-acc-btn--open class (replaces Unicode ▾▸). */
.admin-acc-btn{display:flex;align-items:center;width:100%;gap:8px;padding:11px 14px;background:var(--surface);border:none;cursor:pointer;text-align:left}
.admin-acc-btn::before{
  content:"";display:inline-block;width:11px;height:11px;flex-shrink:0;
  background-color:var(--text-muted);
  -webkit-mask-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
  mask-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
  -webkit-mask-size:contain;mask-size:contain;
  transition:transform .15s;
}
.admin-acc-btn.admin-acc-btn--open::before{transform:rotate(90deg)}
/* A-P1-04: admin flag-sheet and edit-modal close buttons use SVG icn (sheet-close pattern) */
/* A-P1-01: Admin utility classes — replaces ~50 inline style= blocks in admin renderers. */
.admin-stat-pill{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:7px 12px;font-size:var(--font-size-sm);line-height:1.2}
.admin-refresh-btn{margin-left:auto;background:none;border:1px solid var(--border);border-radius:var(--btn-radius);padding:5px 10px;font-size:var(--font-size-xs);color:var(--text-muted);cursor:pointer;display:inline-flex;align-items:center;gap:4px}
.admin-card-row{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px;margin-bottom:8px}
.admin-report-row{background:var(--surface);border:1px solid var(--coral);border-radius:var(--radius-md);padding:12px 14px;margin-bottom:10px;font-size:var(--font-size-md)}
.admin-back-btn{display:inline-flex;align-items:center;gap:5px;background:none;border:none;cursor:pointer;font-size:var(--font-size-md);color:var(--text-muted);padding:0;margin-bottom:16px}
.admin-seg-btn{padding:5px 10px;font-size:var(--font-size-xs);border:none;cursor:pointer;white-space:nowrap;background:transparent;color:var(--text-muted)}
.admin-seg-btn--active{background:var(--accent);color:white}
/* Session-52 Review + Author tabs */
.admin-section-chip{padding:4px 10px;font-size:var(--font-size-xs);border:1px solid var(--border);border-radius:20px;cursor:pointer;background:var(--surface);color:var(--text-muted)}
.admin-section-chip--active{background:var(--accent);color:white;border-color:var(--accent)}
.admin-card-checkbox{width:18px;height:18px;border:2px solid var(--border);border-radius:var(--radius-tiny);flex-shrink:0;cursor:pointer}
.admin-card-checkbox--checked{background:var(--accent);border-color:var(--accent)}
.admin-card-checkbox--checked::after{content:'✓';display:block;text-align:center;color:white;font-size:var(--font-size-xs);line-height:14px}
/* Session-53 keyboard nav focus ring */
.admin-card-row--focused{outline:2px solid var(--accent);outline-offset:-2px;border-radius:var(--radius-sm)}
.admin-form-label{display:block;font-size:var(--font-size-sm);color:var(--text-muted);margin-bottom:4px}
.admin-form-field{width:100%;box-sizing:border-box;padding:10px;border:1px solid var(--border);border-radius:var(--radius-sm);font-family:inherit;font-size:var(--font-size-md);background:var(--surface);color:var(--text);resize:vertical;margin-bottom:12px}
.admin-edit-compact{width:100%;box-sizing:border-box;padding:8px;border:1px solid var(--border);border-radius:var(--radius-sm);font-size:var(--font-size-md);background:var(--surface);color:var(--text)}
.admin-modal-card{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius);width:100%;max-width:560px;max-height:90vh;max-height:90dvh;overflow-y:auto;padding:20px}

/* #6 — Streak ring container */
.streak-ring-container{position:relative;display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;flex-shrink:0}
.streak-ring-svg{position:absolute;inset:0}
.streak-ring-flame{display:flex;align-items:center;justify-content:center}
.streak-chip-zero{display:inline-flex;align-items:center;gap:4px;padding:0 6px 0 4px;border:1.5px dashed var(--border);border-radius:20px;font-size:var(--font-size-sm);height:26px}
/* #10 — recall group header: title case + reduced opacity */
.recall-group-header--meta{opacity:0.75}
/* #9 — routine time-window colour coding */
.routine-in-window > label{border-color:color-mix(in srgb,var(--amber) 50%,var(--border))}
.routine-overdue > label{border-color:color-mix(in srgb,var(--red) 40%,var(--border))}
.routine-overdue:has(input:checked) > label{border-color:var(--border)}
/* #9 — routine progress counter */
#routineProgress{font-size:var(--font-size-sm);font-weight:600;color:var(--text-muted);margin-left:6px}
#routineProgress.routine-progress--done{color:var(--green)}
/* #3 — due-badge context menu */
.due-badge-ctx{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:0 4px 16px rgba(0,0,0,.18);min-width:148px;overflow:hidden;padding:4px 0}
.due-badge-ctx-item{display:block;width:100%;padding:9px 14px;font-size:var(--font-size-md);font-weight:500;text-align:left;background:none;border:none;color:var(--text);cursor:pointer;font-family:inherit}
.due-badge-ctx-item:hover{background:var(--surface-alt)}
/* make hdr-due-badge show pointer + long-press affordance */
.hdr-due-badge{cursor:context-menu;user-select:none}

/* ============================================================
   Stage redesign (2026-05-04) — Alt B
   Spec: docs/TODAY-REDESIGN-2026-05-04.md
   ============================================================ */


/* --- Stage hero (§4) — wide hero card with queue thumbnails --- */
.stage-hero{
  display:flex;align-items:stretch;gap:14px;
  margin:var(--section-gap,12px) 0;padding:18px 20px;
  background:linear-gradient(135deg,
    color-mix(in srgb,var(--accent) 18%,var(--surface)) 0%,
    var(--surface-alt) 75%);
  border:1px solid color-mix(in srgb,var(--accent) 22%,var(--border));
  border-radius:var(--radius-lg);
  cursor:pointer;
  transition:transform .15s,box-shadow .18s,border-color .15s;
  position:relative;overflow:hidden;
}
.stage-hero:hover{
  transform:translateY(-1px);
  box-shadow:0 4px 18px color-mix(in srgb,var(--accent) 14%,transparent);
  border-color:color-mix(in srgb,var(--accent) 38%,var(--border));
}
.stage-hero:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.stage-hero:active{transform:translateY(0)}
.stage-hero[data-empty="true"]{
  background:var(--surface-alt);
  border-color:var(--border);
  opacity:0.85;
}
.stage-hero-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}
.stage-hero-eyebrow{
  font-size:var(--font-size-xs);font-weight:700;
  color:color-mix(in srgb,var(--accent-pressed) 90%,transparent);
  letter-spacing:0.14em;text-transform:uppercase;line-height:1;
}
html.dark .stage-hero-eyebrow{color:var(--accent)}
.stage-hero-title{
  font-size:var(--font-size-3xl);font-weight:700;color:var(--text);line-height:1.15;
  letter-spacing:-0.01em;
}
.stage-hero-meta{
  font-size:var(--font-size-md);color:var(--text-muted);font-weight:500;
  display:flex;align-items:center;gap:6px;flex-wrap:wrap;
}
.stage-hero-meta .sh-sep{opacity:0.5}
.stage-hero-thumbs{
  display:flex;align-items:center;gap:5px;margin-top:8px;
  height:36px;
}
.stage-hero-thumb{
  width:24px;height:34px;border-radius:var(--radius-tiny);
  background:color-mix(in srgb,var(--bg) 75%,var(--accent) 8%);
  border:1px solid color-mix(in srgb,var(--accent) 14%,var(--border));
  flex-shrink:0;
}
/* WS10 — thumb tints aligned with card hue families */
.stage-hero-thumb--saq{background:color-mix(in srgb,var(--bg) 75%,var(--rose) 10%);border-color:color-mix(in srgb,var(--rose) 20%,var(--border))}
.stage-hero-thumb--pharma{background:color-mix(in srgb,var(--bg) 75%,var(--violet) 10%);border-color:color-mix(in srgb,var(--violet) 20%,var(--border))}
.stage-hero-thumb--axiom{background:color-mix(in srgb,var(--bg) 75%,var(--saltbush) 10%);border-color:color-mix(in srgb,var(--saltbush) 20%,var(--border))}
.stage-hero-thumb--more{background:transparent;border-style:dashed;color:var(--text-faint);display:flex;align-items:center;justify-content:center;font-size:var(--font-size-2xs);font-weight:600}
.stage-hero-cta{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:6px;padding:14px 22px;min-width:124px;
  background:var(--accent);color:var(--accent-on);
  border:none;border-radius:var(--radius-lg);
  font-family:inherit;cursor:pointer;
  box-shadow:0 3px 0 var(--accent-pressed);
  transition:transform var(--duration-sm),box-shadow var(--duration-sm);
  flex-shrink:0;
  text-align:center;
}
.stage-hero-cta .play-icn{
  width:36px;height:36px;
  margin-bottom:2px;
  filter:drop-shadow(0 1px 0 color-mix(in srgb,var(--accent-pressed) 50%,transparent));
}
.stage-hero-cta-label{
  font-size:var(--font-size-md);font-weight:700;line-height:1.05;text-align:center;
  letter-spacing:0.01em;
}
.stage-hero-cta-sub{
  /* P2: opacity:0.78 on white-on-mint failed AA (4.3:1). Removed — inherits white
     at full opacity (5.51:1). Visual de-emphasis comes from smaller font-size alone. */
  font-size:var(--font-size-xs);font-weight:500;letter-spacing:0.04em;line-height:1;
  text-align:center;
}
.stage-hero-cta-sub:empty{display:none}
.stage-hero:hover .stage-hero-cta{transform:translateY(-1px);box-shadow:0 5px 14px color-mix(in srgb,var(--accent) 35%,transparent)}
.stage-hero:active .stage-hero-cta{transform:translateY(1px);box-shadow:0 1px 0 var(--accent-pressed)}
@media(max-width:600px){
  .stage-hero{padding:14px 14px;gap:12px}
  .stage-hero-title{font-size:18px}
  .stage-hero-cta{padding:0 16px;min-width:88px}
}
@media(max-width:420px){
  .stage-hero{flex-direction:column;align-items:stretch}
  .stage-hero-cta{width:100%;flex-direction:row;padding:11px 16px;gap:10px}
}

/* --- Status chip row (§A2) — replaces the streak bar --- */
.status-chips{
  display:flex;align-items:center;gap:6px;flex-wrap:wrap;
  margin:0 0 8px;padding:0;font-size:var(--font-size-sm);
  color:var(--text-muted);
}
.status-chip{
  display:inline-flex;align-items:center;gap:4px;
  padding:4px 9px;border-radius:var(--radius-pill);
  background:transparent;border:1px solid var(--border);
  font-size:var(--font-size-xs);font-weight:500;color:var(--text-muted);
  font-variant-numeric:tabular-nums;line-height:1.1;
  white-space:nowrap;
  transition:border-color .15s,color .15s,background .15s;
}
.status-chip strong{color:var(--text);font-weight:600}
.status-chip .lbl{color:var(--text-faint);font-size:var(--font-size-2xs);text-transform:uppercase;letter-spacing:0.04em}
.status-chip svg{width:11px;height:11px}
.status-chip:hover{border-color:color-mix(in srgb,var(--accent) 35%,var(--border));color:var(--text)}
.status-chip--today svg{color:var(--accent)}
.status-chip--streak svg{color:var(--honey)}
.status-chip--exam svg{color:var(--sky)}
.status-chip--xp svg{color:var(--honey)}
.status-chip--badges svg{color:var(--gold)}
.status-chip--freeze{background:var(--sky-fill);color:var(--sky-deep);border-color:transparent}
html.dark .status-chip--freeze{color:var(--sky)}
.status-chip--freeze[hidden]{display:none}
/* Streak + XP chips hidden — both stats now live in the Today hero stats column */
#streakChip,#streakXp{display:none!important}
/* Status chip bar removed from today page */
#statusChips{display:none!important}
.status-chip-active-session{
  display:inline-flex;align-items:center;gap:5px;
  padding:4px 10px;border-radius:var(--radius-pill);
  background:var(--accent-soft);color:var(--accent-pressed);
  border:1px solid color-mix(in srgb,var(--accent) 30%,var(--border));
  font-size:var(--font-size-xs);font-weight:600;font-variant-numeric:tabular-nums;
  line-height:1.1;white-space:nowrap;cursor:pointer;font-family:inherit;
}
html.dark .status-chip-active-session{color:var(--accent)}
.status-chip-active-session[hidden]{display:none}
.status-chip-active-session svg{width:10px;height:10px}
.status-chip--xp.dim{opacity:0.55}
.status-chip--xp.hit{
  border-color:color-mix(in srgb,var(--honey) 50%,var(--border));
  color:var(--honey-deep);
}
html.dark .status-chip--xp.hit{color:var(--honey)}

/* --- Unified history glyph + popover (§A0) --- */
.history-glyph{position:relative}
.history-glyph .pulse-dot{
  position:absolute;top:6px;right:6px;
  width:6px;height:6px;border-radius:50%;
  background:var(--accent);
  box-shadow:0 0 0 2px var(--bg);
  display:none;
}
.history-glyph.has-undo .pulse-dot{display:block}
.history-glyph.idle{opacity:0.6}
.history-popover{
  position:fixed;z-index:240;
  min-width:280px;max-width:340px;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--radius);
  box-shadow:var(--shadow-lg);
  padding:8px 0;
  font-size:var(--font-size-md);
  opacity:0;visibility:hidden;
  transform:translateY(-4px);
  transition:opacity .14s,transform .14s,visibility 0s .14s;
}
.history-popover.show{
  opacity:1;visibility:visible;transform:translateY(0);
  transition:opacity .14s,transform .14s,visibility 0s 0s;
}
.history-popover .hp-section-label{
  display:block;padding:4px 14px;
  font-size:9.5px;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;
  color:var(--text-faint);
}
.history-popover .hp-grades{padding:0 4px}
.history-popover .hp-grade-row{
  display:flex;align-items:center;gap:8px;
  padding:8px 10px;border-radius:var(--btn-radius);
  cursor:pointer;font-size:var(--font-size-md);color:var(--text);
  background:none;border:none;width:100%;text-align:left;font-family:inherit;
}
.history-popover .hp-grade-row:hover{background:var(--surface-alt)}
.history-popover .hp-grade-icon{
  width:8px;height:8px;border-radius:50%;flex-shrink:0;
}
.history-popover .hp-grade-icon.g1{background:var(--coral)}
.history-popover .hp-grade-icon.g2{background:var(--honey)}
.history-popover .hp-grade-icon.g3{background:var(--accent)}
.history-popover .hp-grade-icon.g4{background:var(--peri)}
.history-popover .hp-grade-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.history-popover .hp-grade-time{color:var(--text-faint);font-size:var(--font-size-xs);flex-shrink:0}
.history-popover .hp-empty{
  padding:10px 14px;color:var(--text-faint);font-size:var(--font-size-sm);font-style:italic;
}
.history-popover .hp-divider{
  height:1px;background:var(--border);margin:4px 0;
}
.history-popover .hp-dots{
  display:flex;align-items:center;gap:6px;
  padding:6px 14px 8px;flex-wrap:wrap;
}
.history-popover .hp-dot{
  width:10px;height:10px;border-radius:50%;
  background:var(--surface-alt);border:1px solid var(--border);
  cursor:pointer;flex-shrink:0;
  transition:transform var(--duration-sm),border-color var(--duration-sm),background var(--duration-sm);
}
.history-popover .hp-dot:hover{transform:scale(1.2);border-color:var(--accent)}
.history-popover .hp-dot--completed{background:var(--accent);border-color:var(--accent)}
.history-popover .hp-dot--in_progress{background:color-mix(in srgb,var(--accent) 60%,var(--bg));border-color:var(--accent)}
.history-popover .hp-dot--draft{background:transparent;border-style:dashed}
.history-popover .hp-dot--abandoned{background:var(--coral-fill);border-color:var(--coral-soft);opacity:0.6}
.history-popover .hp-dot--active{
  width:13px;height:13px;
  box-shadow:0 0 0 2px var(--accent-soft);
}
.history-popover .hp-footer-link{
  display:block;padding:8px 14px;font-size:var(--font-size-sm);font-weight:600;
  color:var(--accent-pressed);text-decoration:none;border-top:1px solid var(--border);
  cursor:pointer;background:none;border-left:none;border-right:none;border-bottom:none;
  width:100%;text-align:left;font-family:inherit;
}
html.dark .history-popover .hp-footer-link{color:var(--accent)}
.history-popover .hp-footer-link:hover{background:var(--surface-alt)}

/* --- Stage v2 — hero mode variants (§11.1) --- */
.stage-hero[data-mode="resume"]{
  background:linear-gradient(135deg,
    color-mix(in srgb,var(--accent) 24%,var(--surface)) 0%,
    var(--surface-alt) 70%);
  border-color:color-mix(in srgb,var(--accent) 36%,var(--border));
}
.stage-hero[data-mode="resume"] .stage-hero-cta{
  animation:stagePulse 2.4s ease-in-out infinite;
}
@keyframes stagePulse{
  0%,100%{box-shadow:0 3px 0 var(--accent-pressed)}
  50%{box-shadow:0 3px 0 var(--accent-pressed),0 0 0 4px color-mix(in srgb,var(--accent) 25%,transparent)}
}
@media (prefers-reduced-motion: reduce){.stage-hero[data-mode="resume"] .stage-hero-cta{animation:none}}
.stage-hero[data-mode="block-done"]{
  background:linear-gradient(135deg,
    color-mix(in srgb,var(--mint,var(--accent)) 22%,var(--surface)) 0%,
    var(--surface-alt) 75%);
  border-color:color-mix(in srgb,var(--mint,var(--accent)) 40%,var(--border));
}
.stage-hero[data-mode="block-done"] .stage-hero-eyebrow{
  color:var(--accent-pressed);
}
.stage-hero[data-mode="exam-urgent"]{
  background:linear-gradient(135deg,
    color-mix(in srgb,var(--coral) 16%,var(--surface)) 0%,
    color-mix(in srgb,var(--accent) 8%,var(--surface-alt)) 75%);
  border-color:color-mix(in srgb,var(--coral) 32%,var(--border));
}
.stage-hero[data-mode="exam-urgent"] .stage-hero-eyebrow{
  color:var(--coral-deep);
}
html.dark .stage-hero[data-mode="exam-urgent"] .stage-hero-eyebrow{color:var(--coral)}

/* Progress arc on the CTA play icon (§11.2) — wraps the play icon. */
.stage-hero-cta{position:relative}
.stage-hero-cta-arc{
  position:absolute;top:8px;left:50%;
  transform:translateX(-50%);
  width:48px;height:48px;
  pointer-events:none;
}
.stage-hero-cta-arc circle{
  fill:none;stroke-width:2.5;
  transform-origin:center;transform:rotate(-90deg);
  transition:stroke-dasharray .35s ease,stroke .25s ease;
}
.stage-hero-cta-arc .arc-track{stroke:rgba(0,0,0,0.18);stroke-dasharray:0 119.4}
.stage-hero-cta-arc .arc-fill{stroke:var(--bg);stroke-linecap:round;stroke-dasharray:0 119.4}
.stage-hero-cta-arc[data-pct="100"] .arc-fill{stroke:var(--bg)}
.stage-hero-cta-arc[hidden]{display:none}

/* v237.1 — Hero CTA wrapper. Stacks the dominant Focus button on top with a
   narrower Queue/Manage row beneath (inverted-T composition). Inherits the
   CTA's right-cell sizing on desktop; goes full-width on mobile. */
.stage-hero-cta-wrap{
  display:flex;flex-direction:column;gap:6px;align-items:stretch;
  flex-shrink:0;min-width:128px;
}
@media(max-width:599px){.stage-hero-cta-wrap{width:100%}}

/* v237.1 — Queue/Manage subordinate row. Smaller height, quieter sky tint
   so the Focus CTA stays the loudest element. 70/30 split. Hidden when
   user has no stacks. */
.stage-stacks-row{
  display:flex;gap:4px;width:100%;
}
.stage-stacks-row[hidden]{display:none}
.stage-stacks-pick{
  flex:7;
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  padding:5px 9px;min-height:28px;border-radius:7px;
  border:1px solid color-mix(in srgb,var(--sky) 30%,var(--border));
  background:color-mix(in srgb,var(--sky) 7%,var(--surface-alt2));
  color:var(--sky-deep, var(--text));
  font-size:var(--font-size-sm);font-weight:600;font-family:inherit;cursor:pointer;
  letter-spacing:0.01em;
  transition:background var(--duration-sm),border-color var(--duration-sm),transform var(--duration-sm);
}
.stage-stacks-pick:hover{
  background:color-mix(in srgb,var(--sky) 14%,var(--surface-alt2));
  border-color:color-mix(in srgb,var(--sky) 50%,var(--border));
}
.stage-stacks-pick:active{transform:translateY(1px)}
.stage-stacks-pick .icn{width:13px;height:13px;flex-shrink:0;opacity:0.85}
.stage-stacks-pick-label{font-weight:600}
.stage-stacks-pick-count{
  font-size:var(--font-size-2xs);font-weight:500;
  padding:0 5px;border-radius:var(--radius-sm);line-height:1.6;
  background:color-mix(in srgb,var(--sky) 22%,transparent);
}
.stage-stacks-manage{
  flex:3;
  display:inline-flex;align-items:center;justify-content:center;
  padding:5px 6px;min-height:28px;border-radius:7px;
  border:1px solid var(--border);background:transparent;color:var(--text-faint);
  font-size:var(--font-size-xs);font-weight:600;font-family:inherit;cursor:pointer;
  letter-spacing:0.02em;
  transition:background var(--duration-sm),border-color var(--duration-sm),color var(--duration-sm);
}
.stage-stacks-manage:hover{
  background:var(--surface-alt2);
  border-color:color-mix(in srgb,var(--sky) 30%,var(--border));
  color:var(--text-muted);
}
.stage-stacks-manage:active{transform:translateY(1px)}
html.dark .stage-stacks-pick{color:var(--sky)}

/* Inline streak flame in hero corner (§11.5) */
.stage-hero-streak-flame{
  position:absolute;top:12px;right:14px;
  display:inline-flex;align-items:center;gap:3px;
  font-size:var(--font-size-xs);font-weight:600;color:var(--honey-deep);
  font-variant-numeric:tabular-nums;line-height:1;
  opacity:0.55;transition:opacity var(--duration-md);
  pointer-events:none;
}
html.dark .stage-hero-streak-flame{color:var(--honey)}
.stage-hero:hover .stage-hero-streak-flame{opacity:1}
.stage-hero-streak-flame svg{width:12px;height:12px}
.stage-hero-streak-flame[hidden]{display:none}

/* Topic-coded thumbnails (§11.3) */
.stage-hero-thumb{
  position:relative;cursor:pointer;
  display:flex;align-items:flex-end;justify-content:center;
  padding:0 0 3px;
  font-size:8.5px;font-weight:700;letter-spacing:0.04em;
  color:var(--text-faint);text-transform:uppercase;
  background-clip:padding-box;
  transition:transform var(--duration-sm),border-color var(--duration-sm);
}
.stage-hero-thumb:hover{
  transform:translateY(-2px);
  border-color:color-mix(in srgb,var(--accent) 50%,var(--border));
  color:var(--text);
}
.stage-hero-thumb--recall{color:var(--accent-pressed)}
/* WS10 — icon colours aligned with card hue families */
.stage-hero-thumb--saq{color:var(--rose-deep)}
.stage-hero-thumb--pharma{color:var(--violet-deep,var(--violet))}
.stage-hero-thumb--axiom{color:var(--saltbush-deep)}
html.dark .stage-hero-thumb--recall{color:var(--sage)}
html.dark .stage-hero-thumb--saq{color:var(--rose)}
html.dark .stage-hero-thumb--pharma{color:var(--violet)}
html.dark .stage-hero-thumb--axiom{color:var(--saltbush)}
.stage-hero-thumb:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-radius:5px}

/* ── Stage Hero v2 (sh-*) — 3-column session-focused layout ────────────── */
.sh-hero{--sh-accent:var(--mint,#10B981);display:flex;margin:0 0 14px;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface-elevated);overflow:hidden;min-height:128px;position:relative;isolation:isolate}
/* Left: stats column — 1/3 */
.sh-stats{flex:0 0 33.33%;min-width:80px;padding:13px 11px;border-right:1px solid var(--border);display:flex;flex-direction:column;gap:3px}
/* Middle: chips + card row — 2/3 */
.sh-mid{flex:1;display:flex;flex-direction:row;min-width:0;position:relative;padding:0}
/* Chip column — 1/3 of total (= 50% of sh-mid). Flush stack. */
.sh-chips{display:flex;flex-direction:column;flex:0 0 50%;min-width:0}
.sh-chip{display:flex;align-items:center;gap:7px;padding:0 10px;flex:1;min-height:40px;border:none;border-bottom:0.5px solid var(--border);background:transparent;color:var(--text-faint);cursor:pointer;font-family:inherit;font-size:var(--font-size-sm,12px);text-align:left;white-space:nowrap;transition:background var(--duration-sm),color var(--duration-sm);position:relative}
.sh-chip:last-child{border-bottom:none}
/* no border-radius on right edges — action card is flush against chip column */
.sh-chip:hover:not(.sh-chip--active){background:color-mix(in srgb,var(--sh-accent) 10%,transparent);color:var(--text-muted)}
.sh-chip--active{background:var(--sh-accent);color:#fff;border-right-color:transparent;font-weight:600}
html:not(.dark) .sh-chip--active{background:color-mix(in srgb,var(--sh-accent) 80%,#000)}
.sh-chip--recovery{color:var(--coral,#F05A50)}
.sh-chip--recovery:hover{background:color-mix(in srgb,var(--coral,#F05A50) 10%,transparent)}
.sh-chip:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;z-index:1}
.sh-chip-icon{display:flex;align-items:center;flex-shrink:0;opacity:.65;transition:opacity .12s}
.sh-chip-icon svg{display:block}
.sh-chip--active .sh-chip-icon{opacity:1}
.sh-chip-label{font-size:var(--font-size-sm,12px);line-height:1}
/* 1.11 — chip meta (right-aligned count/label) + disabled state */
.sh-chip-meta{margin-left:auto;font-size:var(--font-size-xs,11px);color:var(--text-faint);font-variant-numeric:tabular-nums;flex-shrink:0}
.sh-chip--active .sh-chip-meta{color:rgba(255,255,255,.75)}
.sh-chip--disabled{opacity:.4;cursor:not-allowed;pointer-events:none}
/* Action card — fills remaining 50% of sh-mid. align-items:stretch on sh-mid makes it match chip column height exactly.
   Sprint D D6 — right outer corners squared so the accent paint reaches the hero's outer right edge (no inward curve). */
.sh-act-card{flex:1;min-width:0;margin:0;border-radius:0;background:var(--sh-accent);border:none;color:#fff;cursor:pointer;font-family:inherit;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;padding:12px 10px;text-align:center;transition:filter var(--duration-sm),transform var(--duration-sm);overflow:hidden}
.sh-act-card:hover{filter:brightness(1.08)}
/* .sh-act-card:active — REMOVED, consolidated into the hero press binding (motion/motion.css #8). */
html:not(.dark) .sh-act-card{background:color-mix(in srgb,var(--sh-accent) 82%,#000)}
html.dark .sh-act-card{background:color-mix(in srgb,var(--sh-accent) 58%,#000 42%)}
html.dark .sh-chip--active{background:color-mix(in srgb,var(--sh-accent) 58%,#000 42%)}
html:not(.dark) .sh-chip--active{background:color-mix(in srgb,var(--sh-accent) 82%,#000)}
.sh-act-card:focus-visible{outline:3px solid rgba(255,255,255,.7);outline-offset:-3px}
.sh-act-icon{display:flex;align-items:center;justify-content:center;margin-bottom:1px}
.sh-act-icon svg{display:block;stroke:#fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;fill:none}
.sh-act-name{font-size:var(--font-size-lg,14px);font-weight:600;line-height:1.2}
.sh-act-meta{font-size:var(--font-size-xs,11px);opacity:.72;margin-top:1px;line-height:1.3}
.sh-act-cta{font-size:var(--font-size-xs,11px);font-weight:700;margin-top:6px;background:rgba(255,255,255,.18);padding:3px 12px;border-radius:var(--btn-radius);letter-spacing:.03em;min-height:36px;display:flex;align-items:center;justify-content:center;text-transform:uppercase}
/* Ghost label — travels from chip to card during chip selection */
.sh-ghost{position:absolute;pointer-events:none;z-index:10;font-weight:600;white-space:nowrap;transform-origin:left center;color:rgba(255,255,255,.45)}
@keyframes shNameArrive{from{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:translateY(0)}}
.sh-act-name--arrive{animation:shNameArrive .1s ease forwards}
/* Stats column children */
.sh-stat{display:flex;align-items:center;gap:5px;font-size:var(--font-size-sm,12px);color:var(--text-faint)}
.sh-stat-dot{width:5px;height:5px;border-radius:50%;flex-shrink:0}
.sh-stat-val{color:var(--text-muted);font-weight:500;min-width:14px;display:inline-block}
.sh-stat-lbl{color:var(--text-faint)}
.sh-stats-divider{height:1px;background:var(--border);margin:4px 0;flex-shrink:0}
.sh-streak{display:flex;align-items:center;gap:4px;font-size:var(--font-size-xs,11px);color:var(--honey,#F59E0B);font-weight:600}
.sh-streak svg{width:10px;height:10px;fill:currentColor;flex-shrink:0}
.sh-exam-badge{font-size:var(--font-size-xs,11px);color:var(--coral,#F05A50);font-weight:700;letter-spacing:.03em;line-height:1.3}
.sh-empty-nudge{font-size:var(--font-size-2xs,10px);color:var(--text-faint);font-style:italic;line-height:1.4}
/* ── Block pill — matches other-tab mode toggle height ───────────────────── */
.sh-block-pill{display:flex;align-items:center;gap:7px;padding:0 10px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-alt2,var(--surface-alt));cursor:pointer;font-family:inherit;text-align:left;color:inherit;margin-bottom:5px;transition:background var(--duration-sm);width:100%;box-sizing:border-box;min-height:40px}
.sh-block-pill:hover{background:color-mix(in srgb,var(--accent) 10%,var(--surface-alt2,var(--surface-alt)))}
.sh-block-pill-dot{width:7px;height:7px;border-radius:50%;background:var(--accent);flex-shrink:0}
.sh-block-pill-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--font-size-sm,12px);font-weight:600;color:var(--text)}
.sh-block-pill-swap{flex-shrink:0;opacity:.5;font-size:11px;color:var(--text-faint);transition:opacity .12s}
.sh-block-pill:hover .sh-block-pill-swap{opacity:.85}
/* ── Block panel — absolute overlay (desktop) / fixed full-width (mobile) ── */
/* Desktop: slides in from left over stats column, zero layout shift */
.sh-block-panel{position:absolute;top:0;bottom:0;left:0;width:33.33%;display:flex;flex-direction:column;background:var(--surface-elevated);border-right:1px solid var(--border);transform:translateX(-110%);transition:transform .22s cubic-bezier(.4,0,.2,1);z-index:3}
.sh-hero.sh--block-open .sh-block-panel{transform:translateX(0)}
.sh-block-panel-hdr{display:flex;align-items:center;justify-content:space-between;padding:7px 8px 5px;border-bottom:1px solid var(--border);flex-shrink:0;gap:4px}
.sh-block-panel-title{font-size:var(--font-size-2xs,10px);font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.06em;white-space:nowrap}
.sh-block-panel-close{background:none;border:none;color:var(--text-faint);cursor:pointer;padding:1px 3px;font-size:13px;line-height:1;border-radius:var(--radius-tiny);transition:color var(--duration-sm);flex-shrink:0;font-family:inherit}
.sh-block-panel-close:hover{color:var(--text)}
.sh-block-list{display:flex;flex-direction:column;padding:5px 5px;gap:3px;overflow-y:auto;flex:1;-webkit-overflow-scrolling:touch}
.sh-block-item{display:flex;flex-direction:column;gap:1px;padding:6px 9px;border-radius:var(--btn-radius);border:1px solid var(--border);background:var(--surface-alt2,var(--surface-alt));cursor:pointer;font-family:inherit;text-align:left;color:inherit;transition:background var(--duration-sm),border-color var(--duration-sm);flex-shrink:0;width:100%;box-sizing:border-box}
.sh-block-item:not(:disabled):hover{background:color-mix(in srgb,var(--accent) 12%,var(--surface-alt2,var(--surface-alt)));border-color:color-mix(in srgb,var(--accent) 30%,var(--border))}
.sh-block-item--active{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,var(--surface-alt2,var(--surface-alt)));cursor:default}
.sh-block-item-name{font-size:var(--font-size-sm,12px);font-weight:600;color:var(--text);line-height:1.3}
.sh-block-item-sub{font-size:var(--font-size-2xs,10px);color:var(--text-muted);line-height:1.3}
/* Real scrim (JS-managed): sits above content, below tab bar — tabs stay tappable */
@keyframes sh-scrim-in{from{opacity:0}to{opacity:1}}
.sh-block-scrim{display:none;position:fixed;inset:0;bottom:calc(56px + env(safe-area-inset-bottom,0px));z-index:195;background:rgba(0,0,0,.38);animation:sh-scrim-in .18s ease forwards;pointer-events:auto}
/* Stats row-break: forces streak/XP onto a new centred row on mobile */
.sh-stats-row-break{display:none;width:100%;height:0;flex-basis:100%}
/* Mobile: full-width fixed sheet from top — full screen width, scrollable */
@media(max-width:480px){
  .sh-block-panel{position:fixed;top:0;left:0;right:0;bottom:auto;width:100%;max-height:75dvh;overflow-y:auto;-webkit-overflow-scrolling:touch;border-right:none;border-bottom:1px solid var(--border);border-radius:0 0 18px 18px;transform:translateY(-100%);transition:transform var(--duration-lg) cubic-bezier(.4,0,.2,1);z-index:9999;box-shadow:0 8px 32px rgba(0,0,0,.22);padding-top:env(safe-area-inset-top,0px)}
  .sh-hero.sh--block-open .sh-block-panel{transform:translateY(0)}
  /* scrim handled by JS #shBlockScrim element */
}
/* Mobile: stats strip hoisted ABOVE hero as cap (all hero tabs) ────────── */
@media(max-width:480px){
  /* Hero loses top border+radius — stats cap provides them */
  .sh-hero{flex-wrap:wrap;overflow:visible;border-top:none;border-radius:0 0 14px 14px;margin-bottom:16px;margin-top:0}
  /* Stats as a visual "cap" above the hero */
  .sh-stats{order:0;flex:0 0 100%;min-width:0;border-right:none;border-top:1px solid var(--border);border-left:1px solid var(--border);border-right:1px solid var(--border);border-bottom:none;border-radius:12px 12px 0 0;flex-direction:row;flex-wrap:wrap;gap:4px 10px;padding:7px 12px;background:var(--surface-elevated);overflow:visible;position:relative;justify-content:center;margin-bottom:-1px;z-index:1}
  .sh-stats-row-break{display:block}
  /* Mid section clips its own bottom corners to match hero border-radius */
  .sh-mid{order:1;flex:0 0 100%;overflow:hidden;border-radius:0 0 12px 12px}
  .sh-stats-divider{display:none}
  .sh-chips{flex:0 0 50%;min-width:0}
  .sh-act-cta{min-height:32px;padding:2px 10px}
  .pharma-hero-slots{flex-direction:column;gap:3px}
}
/* ── Narrow hero collapse (≤360px) — stats hidden until toggled ─────────── */
.sh-stats-toggle{display:none;align-items:center;justify-content:center;gap:3px;width:100%;background:none;border:none;border-top:1px solid var(--border);font-family:inherit;font-size:var(--font-size-2xs,10px);color:var(--text-faint);padding:4px 8px;cursor:pointer;order:4;transition:color .12s}
.sh-stats-toggle:hover{color:var(--text-muted)}
.sh-stats-toggle-arrow{display:inline-block;transition:transform .15s ease;line-height:1;font-style:normal}
@media(max-width:360px){
  .sh-stats-toggle{display:flex}
  .sh-hero:not(.sh--stats-open) .sh-stats{display:none}
  .sh-hero.sh--stats-open .sh-stats-toggle-arrow{transform:rotate(180deg)}
  /* iOS/mobile: hoist Drugs|Classes toggle above the hero — looks connected via
     matching border-radius and border colour. The toggle stays in .sh-stats DOM
     but is moved visually via order + negative margin trick. */
  .sh-hero .sh-mode-toggle{
    order:-1;          /* before .sh-mid and .sh-stats */
    width:calc(100% - 0px);
    border-radius:10px 10px 0 0;
    border-bottom:none;
    min-height:44px;
    margin-bottom:0;
    background:var(--surface-elevated);
  }
  /* Wrapper must not clip the above-hero toggle */
  .sh-hero{overflow:visible;border-radius:0 0 14px 14px}
  /* Push hero up to meet toggle with no gap */
  #pharmaLibHero{margin-bottom:14px}
}
/* ── Today hero v3 — tabs inside hero, stats strip below (hero redesign 2026-05-06) ──
   NOTE: This CSS is additive — all .sh-hero rules above are PRESERVED for the
   Recall, Pharma, and SAQ tab heroes which still use the .sh-hero/.sh-* classes.
   TODO: propagate this identity-bar + 33/33/33 + collapse pattern to:
     - Recall hero: renderRecallHero() ~app.js:L3520
     - Pharma hero: renderPharmaHero() ~app.js:L5200
     - SAQ hero: renderSaqHero() ~app.js:L5900
   (deferred to sub-block 1.10 per STATUS.md §7 cross-tab hero propagation)
*/
.hero{--sh-accent:var(--mint,#157570);display:flex;flex-direction:column;margin:0 0 6px;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface-elevated);overflow:hidden;position:relative;isolation:isolate}
html.dark .hero{}
.hero-tabs{display:flex;gap:2px;padding:4px;border-bottom:1px solid var(--border);background:var(--surface)}
.hero-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:8px 12px;border:none;background:transparent;border-radius:var(--radius-sm);cursor:pointer;font-family:inherit;font-size:var(--font-size-sm);color:var(--text-muted);transition:background var(--duration-sm),color .12s}
.hero-tab:hover{color:var(--text)}
.hero-tab[aria-selected="true"]{background:var(--surface-elevated);color:var(--text);font-weight:600;box-shadow:0 1px 2px rgba(0,0,0,.05)}
.hero-tab .tab-dot{width:7px;height:7px;border-radius:50%;background:var(--accent);flex-shrink:0}
.hero-tab .tab-count{font-size:var(--font-size-xs);color:var(--text-faint);font-variant-numeric:tabular-nums}
.hero-tab[aria-selected="true"] .tab-count{color:var(--text-muted)}
.hero-tab .tab-menu{margin-left:4px;color:var(--text-faint);font-size:14px;line-height:1;padding:0 4px;border-radius:var(--radius-tiny);cursor:pointer}
.hero-tab[aria-selected="true"] .tab-menu{color:var(--text-muted)}
.hero-tab[aria-selected="true"] .tab-menu:hover{background:var(--surface);color:var(--text)}
.tab-name-mobile{display:none}
@media(max-width:480px){.tab-name-full{display:none}.tab-name-mobile{display:inline}}
.hero-body{display:flex;min-height:128px}
.hero-stats-col{flex:0 0 33.33%;display:flex;flex-direction:column;border-right:1px solid var(--border);padding:12px 14px;gap:0;min-width:0;overflow:hidden}
.hero-stats-col-section{display:flex;flex-direction:column;gap:3px;padding:7px 0}
.hero-stats-col-section:first-child{padding-top:0}
.hero-stats-col-section:last-child{padding-bottom:0}
.hero-stats-col-hdr{font-size:var(--font-size-2xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint)}
.hero-stats-col-val{font-size:var(--font-size-xl);color:var(--text);font-weight:700;font-variant-numeric:tabular-nums;line-height:1.15}
.hero-stats-col-meta{font-size:var(--font-size-xs);color:var(--text-muted);line-height:1.35}
.hero-stats-col-divider{height:1px;background:var(--border)}
.today-stat-chips{display:grid;grid-template-columns:1fr 1fr;gap:4px}
.today-stat-chip{display:flex;align-items:center;gap:5px}
.today-stat-chip-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}
.today-stat-chip-label{font-size:var(--font-size-xs);color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;font-variant-numeric:tabular-nums}
.hero-stats-col-section--heatmap{flex:1;min-height:0;overflow:hidden;max-height:106px}
.hero-stats-col-pulse{display:inline-flex;align-items:baseline;gap:6px;font-size:var(--font-size-md);font-weight:600;color:var(--text)}
.hero-stats-col-dot{width:7px;height:7px;border-radius:50%;background:var(--accent);align-self:center;box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 22%,transparent)}
.hero-chips{display:flex;flex-direction:column;flex:0 0 33.33%;min-width:0;border-right:1px solid var(--border)}
.hero-chip{flex:1;display:flex;align-items:center;gap:8px;padding:0 14px;min-height:40px;border:none;border-bottom:1px solid var(--border);background:transparent;cursor:pointer;text-align:left;color:var(--text);font-family:inherit;font-size:var(--font-size-sm);transition:background .12s}
.hero-chip:last-child{border-bottom:none}
.hero-chip:hover{background:color-mix(in srgb,var(--sh-accent) 10%,transparent)}
.hero-chip[aria-pressed="true"]{font-weight:600;border-bottom-color:transparent}
html:not(.dark) .hero-chip[aria-pressed="true"]{background:color-mix(in srgb,var(--sh-accent) 82%,#000);color:#fff}
html.dark .hero-chip[aria-pressed="true"]{background:color-mix(in srgb,var(--sh-accent) 58%,#000 42%);color:#fff}
.hero-chip-icon{width:14px;height:14px;color:var(--text-faint)}
.hero-chip[aria-pressed="true"] .hero-chip-icon{color:#fff}
.hero-chip[aria-pressed="true"] .hero-chip-meta{color:rgba(255,255,255,.80)} /* AA: white on dark accent bg */
.hero-chip-meta{margin-left:auto;font-size:var(--font-size-xs);color:var(--text-faint);font-variant-numeric:tabular-nums}
.hero-act{flex:1;min-width:0;margin:0;border-radius:0;background:color-mix(in srgb,var(--sh-accent) 82%,#000);border:none;color:#fff;cursor:pointer;font-family:inherit;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;padding:12px 10px;text-align:center;transition:filter .12s}
html.dark .hero-act{background:color-mix(in srgb,var(--sh-accent) 58%,#000 42%)}
.hero-act:hover{filter:brightness(1.08)}
.hero-act-icon{font-size:18px;line-height:1}
.hero-act-name{font-size:var(--font-size-lg);font-weight:600;line-height:1.2}
.hero-act-meta{font-size:var(--font-size-xs);opacity:.72;line-height:1.3}
.hero-act-cta{font-size:var(--font-size-xs);font-weight:700;margin-top:6px;background:rgba(255,255,255,.18);padding:3px 12px;border-radius:var(--btn-radius);letter-spacing:.03em;min-height:28px;display:inline-flex;align-items:center;justify-content:center;text-transform:uppercase}
.hero--active{--sh-accent:var(--honey)}
.hero--active .hero-chips{display:none}
.hero--active .hero-act{flex:1;align-items:flex-start;text-align:left;border-radius:0;padding:14px 16px}
.hero--active .hero-act-progress{font-size:var(--font-size-2xs);opacity:.85;letter-spacing:.05em;text-transform:uppercase}
.hero--active .hero-act-name{font-size:var(--font-size-xl);font-weight:700;margin-top:2px}
.hero--active .hero-act-row{display:flex;gap:10px;width:100%;margin-top:10px;align-items:center}
.hero--active .hero-act-resume{flex:1;background:rgba(255,255,255,.22);padding:9px 14px;border-radius:var(--btn-radius);font-size:var(--font-size-sm);font-weight:700;letter-spacing:.03em;text-transform:uppercase;text-align:center}
.hero--active .hero-act-end{background:transparent;color:rgba(255,255,255,.75);border:1px solid rgba(255,255,255,.4);padding:5px 12px;border-radius:var(--btn-radius);font-size:var(--font-size-xs)}
.hero--empty{--sh-accent:var(--fc-badge-mastered)}
.hero--empty .hero-chips{display:none}
.hero--empty .hero-act{padding:18px 16px}
/* 1.10 — multi-tab "Active in another tab" state. Muted grey accent so it
   never feels like an action you should take by default; user must click
   "Continue here" to claim the session in this tab. */
.hero--takenover{--sh-accent:var(--text-faint)}
.hero--takenover .hero-chips{display:none}
.hero--takenover .hero-stats-col{opacity:.65}
.hero--takenover .hero-act{flex:1;align-items:flex-start;text-align:left;padding:14px 16px;background:color-mix(in srgb,var(--text-faint) 78%,#000);box-shadow:inset 0 3px 0 color-mix(in srgb,#000 38%,var(--text-faint))}
.hero--takenover .hero-act-name{font-size:var(--font-size-xl);font-weight:700;margin-top:2px}
.hero--takenover .hero-act-meta{font-size:var(--font-size-sm);opacity:.85;margin-top:3px}
.hero--takenover .hero-act-row{display:flex;gap:10px;width:100%;margin-top:12px;align-items:center}
.hero--takenover .hero-act-resume{flex:1;background:rgba(255,255,255,.22);padding:9px 14px;border-radius:var(--btn-radius);font-size:var(--font-size-sm);font-weight:700;letter-spacing:.03em;text-transform:uppercase;text-align:center;cursor:pointer}
.hero--takenover .hero-act-resume:hover{background:rgba(255,255,255,.32)}

/* ─── Hero FSRS drill tiles (left column) ───────────────────────────────────
   2×2 grid of clickable bucket tiles + a context row; replaces the old
   readiness chips. Sized to fit the existing .hero-stats-col footprint. */
.hero-drill-tiles{display:flex;flex-direction:column;gap:6px;padding:1px 0}
/* Single compact row of 4 bucket tiles (was 2×2 — kept the hero too tall). */
.hero-drill-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:5px}
.hero-drill-tile{--tc:var(--text-muted);position:relative;display:flex;flex-direction:column;gap:0;padding:6px 6px 6px 9px;border:1px solid var(--border);border-radius:8px;background:var(--surface);cursor:pointer;text-align:left;font:inherit;color:var(--text);overflow:hidden;min-width:0;transition:transform .1s,border-color .12s,background .12s}
.hero-drill-tile::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--tc)}
.hero-drill-tile:hover{transform:translateY(-1px);border-color:var(--tc);background:color-mix(in srgb,var(--tc) 9%,var(--surface))}
.hero-drill-tile:active{transform:translateY(0)}
.hero-drill-tile.is-zero{opacity:.5;cursor:default}
.hero-drill-tile.is-zero:hover{transform:none;border-color:var(--border);background:var(--surface)}
/* Loading microanimation: tile pulses + shimmer-sweeps while the drill queue is
   fetched and the preview modal opens (cleared on iatro:session-preview-open). */
.hero-drill-tile.is-loading{cursor:progress;animation:heroDrillPulse 1s ease-in-out infinite}
.hero-drill-tile.is-loading::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(100deg,transparent 28%,color-mix(in srgb,var(--tc) 20%,transparent) 50%,transparent 72%);
  transform:translateX(-100%);animation:heroDrillSweep 1.05s ease-in-out infinite}
@keyframes heroDrillPulse{0%,100%{border-color:var(--tc)}50%{border-color:color-mix(in srgb,var(--tc) 50%,var(--border))}}
@keyframes heroDrillSweep{to{transform:translateX(100%)}}
@media (prefers-reduced-motion: reduce){
  .hero-drill-tile.is-loading{animation:none}
  .hero-drill-tile.is-loading::after{animation:none;opacity:.35;transform:none}
}
.hero-drill-tile--new{--tc:var(--sky-deep)}
.hero-drill-tile--learn{--tc:var(--honey)}
.hero-drill-tile--mat{--tc:var(--saq-pass)}
.hero-drill-tile--over{--tc:var(--coral)}
.hero-drill-num{display:flex;align-items:baseline;gap:3px;font-size:var(--font-size-lg);font-weight:800;line-height:1.1;font-variant-numeric:tabular-nums;color:var(--tc);min-width:0}
/* Overdue urgency is carried by the coral tile colour; no "!" needed in the
   compact single-row tile (it stole width from the in-scope subcount). */
.hero-drill-here{font-size:var(--font-size-2xs);font-weight:700;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hero-drill-lbl{display:flex;align-items:center;gap:4px;font-size:var(--font-size-2xs);color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hero-drill-dot{width:5px;height:5px;border-radius:50%;background:var(--tc);flex-shrink:0}
@media(max-width:600px){.hero-drill-grid{grid-template-columns:1fr 1fr}}
.hero-drill-ctx{display:flex;justify-content:space-between;align-items:center;font-size:var(--font-size-xs);color:var(--text-muted);padding-top:4px;border-top:1px solid var(--border)}
.hero-drill-ctx b{color:var(--text);font-weight:700;font-variant-numeric:tabular-nums}
.hero-drill-ctx .warn{color:var(--coral)}

/* ─── Graded action card (post-session) — New session + Review overdue ─────── */
.hero-act--graded{flex:1;min-width:0;display:flex;flex-direction:column;padding:0;border:none;border-radius:0;background:color-mix(in srgb,var(--sh-accent) 58%,var(--black) 42%);color:var(--white)}
html:not(.dark) .hero-act--graded{background:color-mix(in srgb,var(--sh-accent) 82%,var(--black))}
.hero-graded-done{display:flex;align-items:center;gap:6px;justify-content:center;padding-block:8px;padding-inline:10px;border-bottom:1px solid rgba(255,255,255,.14);background:color-mix(in srgb,var(--saq-pass) 22%,transparent)}
.hero-graded-check{font-weight:800}
.hero-graded-ttl{font-size:var(--font-size-sm);font-weight:700}
.hero-graded-primary{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;border:none;cursor:pointer;font:inherit;color:var(--white);background:transparent;padding:10px;transition:filter .12s}
.hero-graded-primary:hover{filter:brightness(1.12)}
.hero-graded-name{font-size:var(--font-size-lg);font-weight:700}
.hero-graded-meta{font-size:var(--font-size-xs);opacity:.78}
.hero-graded-secondary{flex:0 0 auto;display:flex;align-items:center;justify-content:center;gap:7px;border:none;border-top:1px solid rgba(255,255,255,.14);cursor:pointer;font:inherit;font-size:var(--font-size-sm);font-weight:600;color:var(--white);background:rgba(0,0,0,.18);padding:9px;transition:filter .12s}
.hero-graded-secondary:hover{filter:brightness(1.12)}
.hero-graded-secondary:disabled{opacity:.5;cursor:default}
.hero-graded-badge{background:rgba(255,255,255,.2);border-radius:999px;padding:1px 7px;font-size:var(--font-size-2xs);font-weight:800}

.hero-stats{display:none;align-items:center;justify-content:center;gap:14px;flex-wrap:wrap;font-size:var(--font-size-xs);color:var(--text-muted);background:var(--surface-elevated);border:1px solid var(--border);border-top:none;border-radius:0 0 var(--radius-lg) var(--radius-lg);padding:9px 14px;margin:0 0 14px}
.hero-stats .stat{display:inline-flex;align-items:baseline;gap:3px}
.hero-stats .stat strong{color:var(--text);font-weight:700;font-variant-numeric:tabular-nums;font-size:var(--font-size-sm)}
.hero-stats .meta-divider{color:var(--text-faint);user-select:none;opacity:.6}
.hero-stats .meta-flame{color:var(--coral)}
/* Heatmap bar — always in DOM as sibling after .hero--today, hidden on desktop.
   On mobile it becomes visible and the hero's bottom corners flatten to meet it. */
.hero-heatmap-bar{display:none;background:var(--surface-elevated);border:1px solid var(--border);border-top:none;border-radius:0 0 var(--radius-lg) var(--radius-lg);padding:10px 14px;margin-bottom:14px}
@media(max-width:768px){
  .hero-stats-col{display:none}
  .hero-chips{flex:0 0 50%}
  .hero{border-radius:var(--radius-lg) var(--radius-lg) 0 0;margin-bottom:0}
  .hero-stats{display:flex}
  /* Today hero: stats col wraps to full-width cap above chips/act row */
  .hero--today .hero-body{flex-wrap:wrap}
  .hero--today .hero-stats-col{display:flex;order:-1;flex:0 0 100%;border-right:none;border-bottom:1px solid var(--border);max-height:160px;overflow-y:auto;padding:8px 14px}
  /* Cap shows scope toggle only — hide heatmap slot + its divider */
  .hero--today #th-activity-slot{display:none}
  .hero--today .hero-stats-col-divider{display:none}
  /* Heatmap bar visible below hero on mobile */
  .hero-heatmap-bar{display:block}
  /* Hero gets flat bottom corners so bar connects seamlessly */
  .hero--today.has-heatmap-bar{border-radius:var(--radius-lg) var(--radius-lg) 0 0;margin-bottom:0}
}
/* Block-switch bottom sheet — opened from active tab ⋮ menu */
@keyframes heroSheetFade{from{opacity:0}to{opacity:1}}
@keyframes heroSheetSlideUp{from{transform:translateY(100%)}to{transform:translateY(0)}}
.sheet-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.45);display:flex;flex-direction:column;justify-content:flex-end;z-index:9998;animation:heroSheetFade var(--duration-md) ease}
.sheet{background:var(--surface-elevated);border-radius:var(--radius-lg) var(--radius-lg) 0 0;border:1px solid var(--border);border-bottom:none;padding:10px 18px 22px;box-shadow:0 -8px 32px rgba(0,0,0,.18);animation:heroSheetSlideUp .25s cubic-bezier(.2,.9,.3,1);max-height:80dvh;overflow-y:auto;-webkit-overflow-scrolling:touch}
/* v10 (2026-05-19) — phase-context sheet trim (Tier-D discipline rule #3): when a sheet
   carries phase identity (set via inline --phase-color), show a 3 px top trim. No header
   fill, no side trims — quiet wayfinding cue only. See DEC-026 + DESIGN-SYSTEM.md §1 v10. */
.sheet[style*="--phase-color"]{border-top:3px solid var(--phase-color)}
.sheet-handle{width:40px;height:4px;background:var(--border-strong);border-radius:var(--radius-2xs);margin:0 auto 14px;opacity:.6;touch-action:none}
.sheet-hdr{display:flex;align-items:baseline;gap:10px;margin-bottom:14px}
.sheet-hdr h3{margin:0;font-size:var(--font-size-xl);font-weight:700;color:var(--text)}
.sheet-hdr .sheet-sub{margin-left:auto;font-size:var(--font-size-xs);color:var(--text-faint)}
.sheet-list{display:flex;flex-direction:column;gap:6px}
.sheet-item{display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);cursor:pointer;font-family:inherit;font-size:var(--font-size-md);color:var(--text);text-align:left;transition:background var(--duration-sm),border-color var(--duration-sm);width:100%;box-sizing:border-box}
.sheet-item:hover{background:color-mix(in srgb,var(--accent) 6%,var(--surface))}
.sheet-item--current{background:var(--accent-soft);border-color:var(--accent)}
.sheet-item-dot{width:8px;height:8px;border-radius:50%;background:var(--text-faint);flex-shrink:0}
.sheet-item--current .sheet-item-dot{background:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 22%,transparent)}
.sheet-item-block{font-weight:600;color:var(--text-faint);font-size:var(--font-size-sm);font-variant-numeric:tabular-nums;min-width:24px}
.sheet-item--current .sheet-item-block{color:var(--accent)}
.sheet-item-name{flex:1;font-weight:500}
.sheet-item--current .sheet-item-name{font-weight:700}
.sheet-item-badge{font-size:var(--font-size-2xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--accent);background:transparent;padding:2px 8px;border-radius:var(--radius-pill);border:1px solid var(--accent)}
.sheet-item-count{font-size:var(--font-size-xs);color:var(--text-faint);font-variant-numeric:tabular-nums}
.sheet-cancel{width:100%;padding:11px;margin-top:14px;background:transparent;border:1px solid var(--border);border-radius:var(--btn-radius);font-family:inherit;font-size:var(--font-size-md);color:var(--text-muted);cursor:pointer}
.sheet-cancel:hover{background:var(--surface)}
/* Sheet segmented tab bar (Switch / Progress) — sub-block 1.13 */
.sheet-tabs{display:flex;gap:2px;padding:4px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);margin:0 0 14px}
.sheet-tab{flex:1;padding:9px 12px;border:none;background:transparent;border-radius:var(--radius-sm);cursor:pointer;font-family:inherit;font-size:var(--font-size-sm);font-weight:600;color:var(--text-muted);transition:background var(--duration-sm),color .12s}
.sheet-tab:hover{color:var(--text)}
.sheet-tab[aria-selected="true"]{background:var(--surface-elevated);color:var(--text);box-shadow:0 1px 2px rgba(0,0,0,.05)}
.sheet-tab-panel[hidden]{display:none}
/* Per-block progress list (Progress tab) */
.sheet-progress-list{display:flex;flex-direction:column;gap:10px;max-height:340px;overflow-y:auto;padding-right:4px}
.sheet-progress-empty{padding:24px 16px;text-align:center;color:var(--text-faint);font-size:var(--font-size-sm)}
.sheet-progress-row{padding:10px 12px;border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);display:flex;flex-direction:column;gap:6px}
.sheet-progress-row--current{border-color:var(--accent);background:var(--accent-soft)}
.sheet-progress-row-hdr{display:flex;align-items:baseline;gap:8px;font-size:var(--font-size-md)}
.sheet-progress-block{font-weight:700;color:var(--text-faint);font-size:var(--font-size-sm);font-variant-numeric:tabular-nums;min-width:24px}
.sheet-progress-row--current .sheet-progress-block{color:var(--accent)}
.sheet-progress-name{flex:1;font-weight:500;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sheet-progress-row--current .sheet-progress-name{font-weight:700}
.sheet-progress-current-tag{font-size:var(--font-size-2xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--accent);padding:2px 7px;border-radius:var(--radius-pill);border:1px solid var(--accent)}
.sheet-progress-flags{display:inline-flex;gap:3px}
.sheet-progress-flag{font-size:14px;line-height:1}
.sheet-progress-flag--red{color:var(--coral, var(--coral-vivid))}
.sheet-progress-flag--amber{color:var(--honey)}
.sheet-progress-pct{margin-left:auto;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;font-size:var(--font-size-md)}
.sheet-progress-row--current .sheet-progress-pct{color:var(--accent)}
.sheet-progress-bar{height:6px;background:var(--border);border-radius:3px;overflow:hidden}
.sheet-progress-fill{height:100%;background:var(--accent);transition:width .25s ease}
.sheet-progress-row--current .sheet-progress-fill{background:var(--accent)}
.sheet-progress-meta{font-size:var(--font-size-xs);color:var(--text-muted)}
/* ── Cross-tab hero tab row (Phase 1.6 Track B) ─────────────────────────────
   .hero-tabs--cross is injected above the existing sh-hero shell on Recall,
   Pharma, and SAQ tabs. Reuses hero-tab/tab-name CSS; adds connecting border. */
.hero-tabs--cross{display:flex;gap:2px;padding:4px;border:1px solid var(--border);border-bottom:none;border-radius:var(--radius-lg) var(--radius-lg) 0 0;background:var(--surface);margin-bottom:0}
.hero-tabs--cross + .sh-hero,.hero-tabs--cross + .recall-hero,.hero-tabs--cross + .pharma-hero{border-top:0;border-radius:0 0 var(--radius-lg) var(--radius-lg)}
/* ── Unified hero+filter container ─────────────────────────────────────────
   Wraps tab row + hero + toolbar as one continuous rounded rectangle.
   Container owns the outer border/radius; children shed their own. */
.hero-unified{border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;margin-bottom:14px}
.hero-unified .hero-tabs--cross{border:none;border-radius:0}
.hero-unified .sh-hero{border:none;border-radius:0;margin:0}
.hero-unified .lib-toolbar-v54,.hero-unified .lib-toolbar,.hero-unified .pharma-toolbar{border:none;border-top:1px solid var(--border);border-radius:0;margin:0}
.hero-unified[data-view="sittings"] #saqToolbar{display:none}
/* ── Today hero footer ─────────────────────────────────────────────────────
   Parity with Recall/SAQ/Drugs `.lib-toolbar` footer — hosts banners,
   stats, drift notices, push prompts under the Today hero body.
   Empty state (no children with content) collapses; first non-empty child
   reveals the border-top so layout stays clean when nothing is queued. */
.hero-today-footer{display:flex;flex-wrap:wrap;gap:7px;align-items:center;padding:10px 12px;margin-top:0;background:var(--surface-alt);border:1px solid var(--border);border-top:none;border-radius:0 0 var(--radius-lg) var(--radius-lg);font-size:var(--font-size-sm)}
.hero-today-footer:empty{display:none}
.hero-today-footer__slot{display:contents}
.hero-today-footer__slot:empty{display:none}
.hero--today + .hero-today-footer{margin-top:-14px}  /* close gap below .hero */
/* Mode-milestone banner — appears in the footer when exam-distance crosses
   a threshold and the user is still in the prior mode. */
.hero-today-banner{display:flex;align-items:center;gap:8px;flex:1 1 100%;padding:6px 8px;background:var(--surface-elevated);border:1px solid var(--border);border-radius:var(--radius-sm);font-size:var(--font-size-sm);color:var(--text)}
.hero-today-banner__dot{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0}
.hero-today-banner__txt{flex:1;min-width:0;line-height:1.35}
.hero-today-banner__action{background:var(--accent);color:#fff;border:none;border-radius:var(--btn-radius);padding:4px 10px;font-size:var(--font-size-xs);font-weight:600;cursor:pointer;font-family:inherit;white-space:nowrap}
.hero-today-banner__action:hover{filter:brightness(1.08)}
.hero-today-banner__dismiss{background:none;border:none;color:var(--text-faint);cursor:pointer;font-size:18px;line-height:1;padding:0 4px;font-family:inherit}
.hero-today-banner__dismiss:hover{color:var(--text)}
/* ── Pharma hero — sh-* extensions ────────────────────────────────────────── */
/* Class picker pills inside action card */
.pharma-hero-class-pills{display:flex;flex-wrap:wrap;gap:3px;margin:4px 0 2px;overflow:hidden;max-height:54px}
.pharma-hero-class-pill{background:rgba(255,255,255,.12);border:none;color:rgba(255,255,255,.75);border-radius:var(--radius-tiny);padding:2px 6px;font-size:var(--font-size-2xs,10px);cursor:pointer;font-family:inherit;line-height:1.4;transition:background .1s,color .1s;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:82px}
.pharma-hero-class-pill.active{background:rgba(255,255,255,.28);color:#fff;font-weight:600}
.pharma-hero-class-pill:hover:not(.active){background:rgba(255,255,255,.2)}
/* Compare drug slots */
.pharma-hero-slots{display:flex;gap:4px;margin:4px 0 2px;width:100%}
.pharma-hero-slot{background:rgba(255,255,255,.1);border:2px dashed rgba(255,255,255,.35);color:rgba(255,255,255,.7);border-radius:7px;padding:7px 10px;font-size:var(--font-size-sm,12px);font-weight:500;cursor:pointer;font-family:inherit;display:flex;align-items:center;gap:4px;transition:background .1s,border-color .1s;flex:1;min-width:0;min-height:38px;text-align:left;white-space:nowrap;overflow:hidden}
.pharma-hero-slot.filled{background:rgba(255,255,255,.16);border-style:solid;border-color:rgba(255,255,255,.45);color:#fff}
.pharma-hero-slot:hover{background:rgba(255,255,255,.2);border-color:rgba(255,255,255,.55)}
.pharma-hero-slot-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:var(--font-size-sm,12px)}
.pharma-hero-slot-clear{background:none;border:none;color:rgba(255,255,255,.55);cursor:pointer;padding:0 2px;font-size:14px;line-height:1;flex-shrink:0;font-family:inherit}
.pharma-hero-slot-clear:hover{color:#fff}
/* Inline drug search (Compare picker state) */
.pharma-hero-picker-header{display:flex;justify-content:space-between;align-items:center;color:rgba(255,255,255,.8);font-size:var(--font-size-xs,11px);font-weight:600;margin-bottom:4px}
.pharma-hero-picker-back{background:none;border:none;color:rgba(255,255,255,.55);cursor:pointer;font-size:16px;line-height:1;padding:0 2px;font-family:inherit}
.pharma-hero-picker-back:hover{color:#fff}
.pharma-hero-picker-input{width:100%;background:rgba(255,255,255,.14);border:none;border-radius:var(--radius-tiny);padding:4px 7px;color:#fff;font-size:var(--font-size-xs,11px);font-family:inherit;outline:none;box-sizing:border-box;margin-bottom:3px}
.pharma-hero-picker-input::placeholder{color:rgba(255,255,255,.4)}
.pharma-hero-picker-input:focus{background:rgba(255,255,255,.2)}
.pharma-hero-picker-list{overflow-y:auto;max-height:70px;display:flex;flex-direction:column;gap:1px}
.pharma-hero-picker-item{display:flex;align-items:center;gap:5px;background:rgba(255,255,255,.07);border:none;border-radius:3px;padding:3px 6px;color:#fff;cursor:pointer;font-family:inherit;font-size:var(--font-size-xs,11px);text-align:left;transition:background .1s;width:100%}
.pharma-hero-picker-item:hover{background:rgba(255,255,255,.18)}
.pharma-hero-picker-drug-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pharma-hero-picker-empty{font-size:var(--font-size-xs,11px);color:rgba(255,255,255,.38);text-align:center;padding:8px 0}
/* CTA dimmed / disabled state (Class + Compare pre-selection) */
.sh-act-cta--dim{opacity:.4;cursor:default}

/* ── sh-mode-toggle (Recall/Axiom · Drugs/Classes) ─────────────────────────── */
/* Lives in .sh-stats (surface-elevated bg), so uses solid surface colours.   */
/* flex:1 1 0 → takes top-1/3 of vertical space; max-height caps on tall screens */
.sh-mode-toggle{display:flex;flex-direction:row;gap:0;border-radius:var(--radius-sm);overflow:hidden;border:1px solid var(--border);margin-bottom:5px;width:100%;min-height:40px}
.sh-mode-btn{flex:1;background:none;border:none;color:var(--text-muted);font-family:inherit;font-size:var(--font-size-sm,12px);font-weight:600;padding:8px 6px;cursor:pointer;transition:background var(--duration-sm),color var(--duration-sm);white-space:nowrap;display:flex;align-items:center;justify-content:center;min-height:40px}
.sh-mode-btn+.sh-mode-btn{border-left:1px solid var(--border);border-top:none}
.sh-mode-btn:hover:not(.active){background:color-mix(in srgb,var(--accent) 8%,var(--surface));color:var(--text)}
/* Active: tint bg + text uses --mode-color set inline via JS */
.sh-mode-btn.active{
  background:color-mix(in srgb,var(--mode-color,var(--accent)) 15%,var(--surface-elevated));
  color:var(--mode-color,var(--accent));
  font-weight:700;
}

/* ── SAQ Sittings view ───────────────────────────────────────────────────────── */
.saq-sittings-wrap{padding:0 2px 12px}
.saq-sittings-year{margin-bottom:8px}
.saq-sittings-year-hdr{display:flex;align-items:center;gap:8px;padding:6px 4px 4px;cursor:pointer;user-select:none}
.saq-sittings-year-label{font-size:var(--font-size-sm,12px);font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.04em}
.saq-sittings-year-count{font-size:var(--font-size-2xs,10px);color:var(--text-faint);margin-left:auto}
.saq-sittings-row{display:flex;align-items:center;gap:8px;width:100%;background:none;border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 10px;margin-bottom:5px;cursor:pointer;text-align:left;transition:background .12s}
.saq-sittings-row:hover{background:color-mix(in srgb,var(--accent) 6%,var(--surface-elevated))}
.saq-sittings-row-left{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}
.saq-sittings-row-right{display:flex;align-items:center;gap:10px;flex-shrink:0}
.saq-sittings-label{font-size:var(--font-size-sm,12px);font-weight:700;color:var(--text);white-space:nowrap}
.saq-sittings-badge{display:inline-block;font-size:var(--font-size-2xs,10px);font-weight:700;padding:1px 5px;border-radius:var(--radius-tiny);margin-left:5px;vertical-align:middle}
.saq-sittings-badge--weak{background:color-mix(in srgb,var(--rose,#C44484) 18%,transparent);color:var(--rose,#C44484)}
.saq-sittings-pass{display:flex;flex-direction:column;align-items:center;gap:1px;min-width:36px}
.saq-sittings-pass-lbl{font-size:var(--font-size-2xs,10px);color:var(--text-faint)}
.saq-sittings-pass-val{font-size:var(--font-size-sm,12px);font-weight:700}
.saq-sittings-pass-val--high{color:var(--sage,#5BA08A)}
.saq-sittings-pass-val--mid{color:var(--honey,#D68000)}
.saq-sittings-pass-val--low{color:var(--rose,#C44484)}
.saq-sittings-hy{display:flex;flex-direction:column;align-items:center;gap:1px;min-width:28px}
.saq-sittings-count{display:flex;flex-direction:column;align-items:center;gap:1px;min-width:24px}
.saq-sittings-done{display:flex;flex-direction:column;align-items:center;gap:1px;min-width:28px}
.saq-sittings-stat-val{font-size:var(--font-size-sm,12px);font-weight:600;color:var(--text)}
.saq-sittings-stat-lbl{font-size:var(--font-size-2xs,10px);color:var(--text-faint)}
.saq-sittings-drill{font-size:var(--font-size-sm,12px);color:var(--text-faint);flex-shrink:0;padding-left:4px}
.saq-sitting-crumb{display:flex;align-items:center;gap:6px;padding:5px 8px;background:color-mix(in srgb,var(--rose,#C44484) 10%,var(--surface-elevated));border-radius:var(--btn-radius);margin-bottom:8px;border:1px solid color-mix(in srgb,var(--rose,#C44484) 25%,transparent)}
.saq-sitting-crumb-label{font-size:var(--font-size-sm,12px);color:var(--rose,#C44484);font-weight:600;flex:1}
.saq-sitting-crumb-clear{background:none;border:none;color:var(--text-faint);font-size:14px;cursor:pointer;padding:0 2px;line-height:1;border-radius:3px}
.saq-sitting-crumb-clear:hover{color:var(--text)}

/* ── sh-scope-row (Block | All) ──────────────────────────────────────────────── */
.sh-scope-row{display:flex;gap:0;border-radius:var(--btn-radius);overflow:hidden;border:1px solid var(--border);margin-top:1px;margin-bottom:1px}
.sh-scope-btn{flex:1;background:none;border:none;color:var(--text-faint);font-family:inherit;font-size:var(--font-size-2xs,10px);padding:3px 6px;cursor:pointer;transition:background var(--duration-sm),color .12s}
.sh-scope-btn:hover:not(.active){background:color-mix(in srgb,var(--accent) 8%,var(--surface));color:var(--text-muted)}
.sh-scope-btn.active{background:color-mix(in srgb,var(--accent) 12%,var(--surface-elevated));color:var(--text);font-weight:600}

/* ── sh-topic-pills (section pills inside Topic action card) ─────────────────── */
.sh-topic-pills{display:flex;flex-wrap:wrap;gap:3px;margin:4px 0 2px;overflow:hidden;max-height:60px}
.sh-topic-pill{background:rgba(255,255,255,.12);border:none;color:rgba(255,255,255,.75);border-radius:var(--radius-tiny);padding:2px 8px;font-size:var(--font-size-2xs,10px);font-weight:600;cursor:pointer;font-family:inherit;line-height:1.5;transition:background .1s,color .1s}
.sh-topic-pill.active{background:rgba(255,255,255,.3);color:#fff}
.sh-topic-pill:hover:not(.active){background:rgba(255,255,255,.2)}

/* ── sh-nem-list (nemesis preview inside action card) ────────────────────────── */
.sh-nem-list{display:flex;flex-direction:column;gap:2px;margin:4px 0 2px;overflow:hidden;max-height:72px}
.sh-nem-row{display:flex;align-items:center;gap:5px;padding:1px 0}
.sh-nem-pct{font-size:var(--font-size-xs,11px);font-weight:700;min-width:30px;flex-shrink:0}
.sh-nem-label{font-size:var(--font-size-2xs,10px);color:rgba(255,255,255,.72);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}


/* recall-lib-inner wrapper (mirrors pharma-lib-inner) */
.recall-lib-inner{display:flex;flex-direction:column}
/* ─────────────────────────────────────────────────────────────────────────── */

/* Up-next chip below hero (§11.6) */
.stage-up-next{
  display:inline-flex;align-items:center;gap:6px;
  margin:6px 0 10px;padding:5px 12px;
  border-radius:var(--radius-pill);
  background:transparent;border:1px dashed var(--border);
  color:var(--text-muted);font-size:var(--font-size-sm);font-weight:500;
  font-family:inherit;
}
.stage-up-next .un-arrow{color:var(--accent);font-weight:600}
.stage-up-next[hidden]{display:none}

/* --- Stage peek modal (§11.4) — tap-to-peek thumbnail --- */
.stage-peek-overlay{
  position:fixed;inset:0;z-index:280;
  background:rgba(0,0,0,0.55);backdrop-filter:blur(3px);
  display:flex;align-items:center;justify-content:center;
  padding:18px;
  opacity:0;visibility:hidden;
  transition:opacity .18s,visibility 0s .18s;
}
.stage-peek-overlay.show{opacity:1;visibility:visible;transition:opacity .18s,visibility 0s 0s}
.stage-peek-card{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--radius-lg);
  width:100%;max-width:480px;
  padding:18px 20px 16px;
  box-shadow:var(--shadow-lg);
  transform:translateY(8px);
  transition:transform .22s ease-out;
}
.stage-peek-overlay.show .stage-peek-card{transform:translateY(0)}
@media(prefers-reduced-motion:reduce){
  .stage-peek-card{transform:none;transition:none}
}
.stage-peek-eyebrow{
  font-size:9.5px;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;
  color:var(--text-faint);margin-bottom:8px;
  display:flex;align-items:center;gap:8px;
}
.stage-peek-eyebrow .pk-tag{
  padding:2px 7px;border-radius:var(--radius-sm);
  background:var(--accent-soft);color:var(--accent-pressed);
  font-weight:700;letter-spacing:0.04em;text-transform:none;
}
html.dark .stage-peek-eyebrow .pk-tag{color:var(--accent)}
.stage-peek-prompt{
  font-size:15px;line-height:1.5;color:var(--text);
  font-weight:500;margin:0 0 16px;
}
.stage-peek-actions{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding-top:10px;border-top:1px solid var(--border);
}
.stage-peek-close{
  background:transparent;border:none;
  font-size:var(--font-size-md);font-weight:500;color:var(--text-muted);
  cursor:pointer;font-family:inherit;padding:6px 10px;border-radius:var(--btn-radius);
}
.stage-peek-close:hover{background:var(--surface-alt);color:var(--text)}
.stage-peek-focus{
  display:inline-flex;align-items:center;gap:6px;
  padding:8px 16px;border-radius:var(--radius-md);
  background:var(--accent);color:var(--accent-on);
  border:none;font-size:var(--font-size-md);font-weight:700;font-family:inherit;cursor:pointer;
  box-shadow:0 2px 0 var(--accent-pressed);
}
.stage-peek-focus:hover{transform:translateY(-1px);box-shadow:0 3px 6px color-mix(in srgb,var(--accent) 30%,transparent)}
.stage-peek-focus svg{width:14px;height:14px}

/* --- Queue manager modal (Stage v2 §11.7) — manage focus-mode queue --- */
.queue-mgr-overlay{
  position:fixed;inset:0;z-index:280;
  background:rgba(0,0,0,0.55);backdrop-filter:blur(3px);
  display:flex;align-items:center;justify-content:center;
  padding:18px;
  opacity:0;visibility:hidden;
  transition:opacity .18s,visibility 0s .18s;
}
.queue-mgr-overlay.show{opacity:1;visibility:visible;transition:opacity .18s,visibility 0s 0s}
.queue-mgr-card{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--radius-lg);
  width:100%;max-width:560px;max-height:80vh;max-height:80dvh;
  display:flex;flex-direction:column;
  box-shadow:var(--shadow-lg);
  transform:translateY(8px);
  transition:transform .22s ease-out;
  overflow:hidden;
}
.queue-mgr-overlay.show .queue-mgr-card{transform:translateY(0)}
@media(prefers-reduced-motion:reduce){
  .queue-mgr-card{transform:none;transition:none}
}
.queue-mgr-head{
  display:flex;align-items:center;justify-content:space-between;
  padding:14px 18px 12px;border-bottom:1px solid var(--border);
}
.queue-mgr-title{
  font-size:var(--font-size-lg);font-weight:700;color:var(--text);letter-spacing:-0.01em;
}
.queue-mgr-sub{
  font-size:var(--font-size-xs);color:var(--text-muted);font-weight:500;margin-left:8px;
}
.queue-mgr-close{
  background:transparent;border:none;font-size:20px;color:var(--text-muted);
  cursor:pointer;padding:4px 10px;border-radius:var(--btn-radius);font-family:inherit;line-height:1;
}
.queue-mgr-close:hover{background:var(--surface-alt);color:var(--text)}
.queue-mgr-body{
  flex:1;overflow-y:auto;padding:6px 8px;
}
.queue-mgr-row{
  display:flex;align-items:center;gap:10px;
  padding:10px 12px;border-radius:var(--radius-sm);
  font-size:var(--font-size-md);color:var(--text);
}
.queue-mgr-row + .queue-mgr-row{border-top:1px solid var(--border)}
.queue-mgr-row.is-skipped{opacity:0.45}
.queue-mgr-row.is-skipped .qmr-prompt{text-decoration:line-through}
.qmr-tag{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:34px;padding:2px 6px;border-radius:var(--btn-radius);
  font-size:9px;font-weight:700;letter-spacing:0.04em;text-transform:uppercase;
  flex-shrink:0;
}
/* WS10 — qmr-tags aligned with card hue families */
.qmr-tag--recall{background:color-mix(in srgb,var(--sky)  22%,var(--surface));color:var(--sky-deep)}
.qmr-tag--saq{background:color-mix(in srgb,var(--rose) 22%,var(--surface));color:var(--rose-deep)}
.qmr-tag--pharma{background:color-mix(in srgb,var(--violet) 22%,var(--surface));color:var(--violet-deep,var(--violet))}
.qmr-tag--axiom{background:color-mix(in srgb,var(--saltbush) 22%,var(--surface));color:var(--saltbush-deep)}
html.dark .qmr-tag--recall{color:var(--sage)}
html.dark .qmr-tag--saq{color:var(--rose)}
html.dark .qmr-tag--pharma{color:var(--violet-deep)}
html.dark .qmr-tag--axiom{color:var(--saltbush)}
.qmr-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.qmr-topic{font-size:var(--font-size-xs);font-weight:600;color:var(--text-muted);letter-spacing:0.04em;text-transform:uppercase}
.qmr-prompt{
  font-size:var(--font-size-md);color:var(--text);line-height:1.35;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.qmr-actions{display:flex;align-items:center;gap:6px;flex-shrink:0}
.qmr-action{
  background:transparent;border:1px solid var(--border);
  font-size:var(--font-size-xs);font-weight:500;color:var(--text-muted);
  padding:5px 10px;border-radius:var(--btn-radius);cursor:pointer;font-family:inherit;
  transition:border-color var(--duration-sm),color var(--duration-sm),background var(--duration-sm);
}
.qmr-action:hover{border-color:var(--accent);color:var(--accent)}
.qmr-action--restore{color:var(--accent-pressed);border-color:color-mix(in srgb,var(--accent) 30%,var(--border))}
html.dark .qmr-action--restore{color:var(--accent)}
.queue-mgr-foot{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 18px;border-top:1px solid var(--border);
  font-size:var(--font-size-sm);color:var(--text-muted);
}
.queue-mgr-foot .qm-count{font-weight:600;color:var(--text)}
.queue-mgr-foot .qm-restore-all{
  background:transparent;border:none;color:var(--accent-pressed);
  font-size:var(--font-size-sm);font-weight:500;cursor:pointer;font-family:inherit;
  padding:4px 8px;border-radius:var(--btn-radius);
}
html.dark .queue-mgr-foot .qm-restore-all{color:var(--accent)}
.queue-mgr-foot .qm-restore-all:hover{background:var(--surface-alt)}
.queue-mgr-foot .qm-restore-all[hidden]{display:none}

/* +N overflow / Manage chip — always-on entrypoint to the queue manager.
   Default state shows "+N" or "Manage" depending on whether overflow exists.
   .stage-hero-thumb--has-skipped tints the chip subtly so removed-card state
   is visible at a glance. .stage-hero-thumb-skipped-badge sits inside the
   chip and shows "−M" for the count of skipped cards this session. */
.stage-hero-thumb--more{
  position:relative;cursor:pointer;font-weight:700;
  font-size:9px;letter-spacing:0.04em;
  padding:0 6px;min-width:34px;
  display:inline-flex;align-items:center;justify-content:center;gap:4px;
}
.stage-hero-thumb--more:hover{
  background:color-mix(in srgb,var(--accent) 8%,transparent);
  border-color:color-mix(in srgb,var(--accent) 50%,var(--border));
  color:var(--accent-pressed);
}
html.dark .stage-hero-thumb--more:hover{color:var(--accent)}
.stage-hero-thumb--more.stage-hero-thumb--has-skipped{
  border-color:color-mix(in srgb,var(--coral) 35%,var(--border));
  color:var(--coral-deep);
}
html.dark .stage-hero-thumb--more.stage-hero-thumb--has-skipped{color:var(--coral)}
.stage-hero-thumb-skipped-badge{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:18px;height:14px;padding:0 4px;border-radius:var(--radius-sm);
  background:color-mix(in srgb,var(--coral) 20%,var(--surface));
  color:var(--coral-deep);
  font-size:8.5px;font-weight:700;letter-spacing:0;
  line-height:1;
}
html.dark .stage-hero-thumb-skipped-badge{
  background:var(--coral-soft);color:var(--coral);
}

/* --- Bulk-clear empty drafts (sessions history modal) --- */
.sh-bulk-clear{
  display:inline-flex;align-items:center;gap:6px;
  padding:6px 11px;margin-left:8px;
  border-radius:var(--radius-sm);background:transparent;
  border:1px solid color-mix(in srgb,var(--coral) 28%,var(--border));
  color:var(--coral-deep);font-size:var(--font-size-sm);font-weight:500;
  font-family:inherit;cursor:pointer;
  transition:background var(--duration-sm),border-color var(--duration-sm),color var(--duration-sm);
}
html.dark .sh-bulk-clear{color:var(--coral)}
.sh-bulk-clear:hover{
  background:color-mix(in srgb,var(--coral) 8%,transparent);
  border-color:var(--coral);
}
.sh-bulk-clear[hidden]{display:none}
.sh-bulk-clear svg{width:12px;height:12px}

/* --- Routine briefing recall row (§C) --- */
.routine-briefing-row{
  display:flex;align-items:center;gap:10px;
  padding:8px 12px;border-radius:var(--radius-sm);
  background:color-mix(in srgb,var(--accent) 6%,var(--surface));
  border:1px dashed color-mix(in srgb,var(--accent) 25%,var(--border));
  cursor:pointer;font-size:var(--font-size-md);color:var(--accent-pressed);
  font-weight:500;font-family:inherit;width:100%;text-align:left;
}
html.dark .routine-briefing-row{color:var(--accent)}
.routine-briefing-row:hover{background:color-mix(in srgb,var(--accent) 10%,var(--surface))}
.routine-briefing-row svg{width:13px;height:13px;flex-shrink:0}
.routine-briefing-row .rbr-label{flex:1}
.routine-briefing-row .rbr-hint{color:var(--text-faint);font-size:var(--font-size-xs);font-weight:400}

/* ─── Sprint E — Curriculum spine ─────────────────────────────────────── */

/* Readiness band colour tokens (light mode) */
:root {
  --band-untouched: #9CA3AF;
  --band-sparse:    #64748B;
  --band-building:  #84A98C;
  --band-honed:     #0EA5E9;
  --band-mastered:  var(--grade-mastered); /* UI-01/06/12: was stale fuchsia #C026D3 */
}

/* Page wrappers */
.curriculum-page {
  /* iOS-render audit 2026-05-23 — full width to match the main tab pages.
     width:100% + margin:0 is load-bearing: the page is a flex item in the
     column-flex .curriculum-overlay-sheet, and `margin:0 auto` (the old value)
     cancels the default align-items:stretch, collapsing the card to its content
     width (~617px) and centring it. Explicit full width avoids that. */
  max-width: none;
  width: 100%;
  margin: 0;
  padding: 24px 16px 100px;
}
.curriculum-page--master {}

/* Page header — 3-column grid: left (Study/Browse) | centre (title) | right (search icon) */
.curriculum-page-header { margin-bottom: 20px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
.curriculum-page-header-left  { display: flex; align-items: center; }
/* iOS-render audit 2026-05-23 — when the master search is open, the header
   collapses from a 3-col grid to a flex row so the input fills the full width. */
.curriculum-page-header--searching { display: flex; align-items: center; gap: 8px; }
.curriculum-page-header--searching .curriculum-page-header-left { flex: 1; }
.curriculum-page-header-right { display: flex; align-items: center; justify-content: flex-end; }
/* v10 (2026-05-19): unified modal/page-title typography per DEC-026 — body-system mapping +
   Linear/Notion philosophy. Title 18/600 -0.01em; sublabel above title uses 11/700 uppercase 0.06em. */
.curriculum-page-title  { font-size: 18px; font-weight: 600; letter-spacing: -0.01em; color: var(--text); text-align: center; }
.curriculum-page-byline { font-size: 13px; color: var(--text-muted); }
.curriculum-search-icon-btn {
  width: 36px; height: 36px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm); border: none; background: none;
  color: var(--text-muted); cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.curriculum-search-icon-btn:hover,
.curriculum-search-icon-btn.is-active { background: var(--sage-fill); color: var(--sage-deep); }
.curriculum-search__input--header { flex: 1; min-width: 0; padding: 6px 10px; font-size: 13px; }
.curriculum-study-btn {
  flex-shrink: 0;
  padding: 6px 16px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 600;
  border: 1.5px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  cursor: pointer;
  transition: background 0.15s;
}
.curriculum-study-btn:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); }
/* WS11 v9.7-foundation: was hardcoded #38BDF8 (Tailwind sky-400) bypassing the theme system.
   --info resolves to --sky-deep (light) / #79B9DD (dark) — both AA on their surface. */
.curriculum-study-btn--browse {
  border-color: var(--info);
  background: color-mix(in srgb, var(--info) 12%, transparent);
  color: var(--info);
}
.curriculum-study-btn--browse:hover { background: color-mix(in srgb, var(--info) 22%, transparent); }

/* ── Tonight's Focus CTA ── */
.curriculum-tonight-cta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 12px 16px;
  margin-bottom: 20px;
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--sage) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--sage) 30%, var(--border));
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  transition: background var(--duration-sm);
}
a.curriculum-tonight-cta:hover {
  background: color-mix(in srgb, var(--sage) 14%, var(--surface));
}
.curriculum-tonight-cta--plain {
  color: var(--text-muted);
  font-weight: 400;
}
.cta-label  { color: var(--text-muted); font-weight: 400; }
.cta-node   { font-weight: 700; font-family: var(--font-mono,monospace); color: var(--sage-deep); }
.cta-line   { color: var(--text-muted); }
.cta-sep    { color: var(--border-strong); }
.cta-due    { color: var(--text-faint); font-size: 13px; }

/* ── Search ── */
.curriculum-search { position: relative; margin-bottom: 16px; }
.curriculum-search__input {
  width: 100%;
  padding: 9px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-bright);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  outline: none;
  transition: border-color var(--duration-sm);
}
.curriculum-search__input:focus { border-color: var(--sage); }
.curriculum-search__results {
  position: absolute;
  top: calc(100% + 4px);
  left: 0; right: 0;
  background: var(--surface-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  z-index: 50;
  max-height: 360px;
  overflow-y: auto;
}
.curriculum-search__row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  text-decoration: none;
  font-size: 13px;
  transition: background 0.1s;
}
.curriculum-search__row:last-child { border-bottom: none; }
.curriculum-search__row:hover { background: color-mix(in srgb, var(--sage) 5%, var(--surface-elevated)); }
.curriculum-search__empty { padding: 12px 14px; color: var(--text-faint); font-size: 13px; }
.search-code { font-family: var(--font-mono,monospace); font-size: 12px; font-weight: 700; color: var(--text-muted); flex-shrink: 0; }
.search-dot  { color: var(--border-strong); flex-shrink: 0; }
.search-line { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Sort segmented control ── */
.curriculum-sort {
  display: inline-flex;
  gap: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: 16px;
}
.curriculum-sort__btn {
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 500;
  font-family: inherit;
  background: transparent;
  border: none;
  border-right: 1px solid var(--border);
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.curriculum-sort__btn:last-child { border-right: none; }
.curriculum-sort__btn:hover { background: color-mix(in srgb, var(--sage) 6%, var(--surface)); color: var(--text); }
.curriculum-sort__btn.is-active {
  background: color-mix(in srgb, var(--sage) 12%, var(--surface));
  color: var(--sage-deep);
  font-weight: 600;
}

/* ── Sections grid ── */
.curriculum-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
}

/* ── Section card ── */
.section-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 16px 12px;
  cursor: pointer;
  transition: box-shadow var(--duration-sm), border-color var(--duration-sm), transform var(--duration-sm);
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
}
.section-card:hover {
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  border-color: var(--border-strong);
  transform: translateY(-1px);
}
/* ── Study-mode square checkbox (.cs-checkbox) ──────────────────────────── */
.cs-checkbox {
  display: none !important;
  align-items: center; justify-content: center;
  width: 22px; height: 22px;
  flex-shrink: 0;
  border-radius: var(--radius-tiny);
  border: 2px solid var(--border-strong, rgba(0,0,0,0.25));
  background: var(--surface);
  cursor: pointer;
  transition: background var(--duration-sm), border-color var(--duration-sm);
}
.cs-checkbox svg {
  width: 12px; height: 12px;
  stroke: #fff; stroke-width: 2.2;
  fill: none; stroke-linecap: round; stroke-linejoin: round;
  opacity: 0;
}
.cs-checkbox[aria-checked="true"] { background: var(--accent); border-color: var(--accent); }
.cs-checkbox[aria-checked="true"] svg { opacity: 1; }
.cs-checkbox:hover { border-color: var(--accent); }
/* Show checkboxes only in study mode */
.curriculum-page--study .cs-checkbox { display: inline-flex !important; }
/* Section card: checkbox is absolutely pinned to left edge (column-flex card) */
.section-card > .cs-checkbox {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%); z-index: 2;
}
.curriculum-page--study .section-card { padding-left: 44px; }
/* Chapter/topic rows: checkbox is a flex item, vertically centered */
.chapter-callout-row > .cs-checkbox,
.topic-callout-row > .cs-checkbox { align-self: center; }
/* Selected highlight for all row types */
.section-card.cs-selected,
.chapter-callout-row.cs-selected,
.topic-callout-row.cs-selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 5%, var(--surface));
}
.section-card-header {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.section-badge {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 700;
  flex-shrink: 0;
}
.section-meta { flex: 1; min-width: 0; }
.section-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  margin-bottom: 5px;
  line-height: 1.3;
}
.section-tier-row {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
}
.tier-dot { font-size: 11px; line-height: 1; flex-shrink: 0; }

/* Coverage stat row */
.section-stats {}
.section-stat-row {
  display: flex;
  align-items: center;
  gap: 7px;
}
.section-stat-label {
  font-size: 11px;
  color: var(--text-faint);
  min-width: 56px;
}
.section-stat-bar-wrap {
  flex: 1;
  height: 4px;
  background: var(--border);
  border-radius: var(--radius-2xs);
  overflow: hidden;
}
.section-stat-bar-fill {
  height: 100%;
  border-radius: var(--radius-2xs);
  transition: width 0.3s;
}
.section-stat-value {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  min-width: 28px;
  text-align: right;
}

/* Counts footer */
.section-counts {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}
.count-chip {
  font-size: 11px;
  color: var(--text-faint);
  display: flex;
  align-items: center;
  gap: 3px;
}
.count-chip strong { font-weight: 600; color: var(--text-muted); }
.count-chip--new strong { color: var(--sky-deep); }
.count-chip--due strong { color: var(--honey-deep); }
.count-sep { color: var(--border-strong); font-size: 10px; }

/* ── Band pills ── */
.band-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
  white-space: nowrap;
}
/* Untouched: outline-only (transparent fill, 1px solid border) */
.band-pill--untouched {
  background: transparent;
  color: var(--band-untouched);
  border: 1px solid var(--band-untouched);
}
.band-pill--sparse {
  background: color-mix(in srgb, var(--band-sparse) 12%, var(--surface));
  color: var(--band-sparse);
  border: 1px solid color-mix(in srgb, var(--band-sparse) 30%, var(--border));
}
.band-pill--building {
  background: color-mix(in srgb, var(--band-building) 14%, var(--surface));
  color: #2D5A35;
  border: 1px solid color-mix(in srgb, var(--band-building) 35%, var(--border));
}
.band-pill--honed {
  background: color-mix(in srgb, var(--band-honed) 12%, var(--surface));
  color: #0369A1;
  border: 1px solid color-mix(in srgb, var(--band-honed) 35%, var(--border));
}
/* Mastered — canonical --grade-mastered (UI-01/06/12: stale fuchsia retired) */
.band-pill--mastered {
  background: color-mix(in srgb, var(--grade-mastered) 10%, var(--surface));
  color: var(--grade-mastered-label);
  border: 1px solid color-mix(in srgb, var(--grade-mastered) 30%, var(--border));
}

/* ── CRC mini-glyph ── */
.crc-glyph {
  display: inline-block;
  vertical-align: middle;
  flex-shrink: 0;
}

/* ── Grade tally ── */
.grade-tally {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  font-weight: 600;
}
/* UI-04/07/13: text colors -> --grade-*-label tokens (dark overrides included;
   #F05A50-as-text was the 3.34:1 AA fail). */
.gt-missed  { color: var(--grade-missed-label); }
.gt-hazy    { color: var(--grade-hazy-label); }
.gt-honed   { color: var(--grade-honed-label); }
.gt-mastered{ color: var(--violet-deep); }

/* ── E2: Sticky breadcrumb ── */
.curriculum-breadcrumb-sticky {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  margin: -24px -16px 20px;
  background: var(--surface-elevated);
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.curriculum-breadcrumb-sticky__back {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 10px 3px 7px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  transition: background var(--duration-sm), color var(--duration-sm);
}
.curriculum-breadcrumb-sticky__back:hover { background: var(--sage-fill); color: var(--sage-deep); }
.curriculum-breadcrumb-sticky__sep { color: var(--border-strong); }
.curriculum-breadcrumb-sticky__crumb {
  color: var(--sage);
  text-decoration: none;
  font-weight: 500;
}
.curriculum-breadcrumb-sticky__crumb:hover { text-decoration: underline; }
.curriculum-breadcrumb-sticky__current { color: var(--text-muted); }

/* ── E2: Section header card ── */
.curriculum-section-header-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px 20px 18px;
  margin-bottom: 12px;
  display: flex;
  gap: 18px;
  align-items: flex-start;
}
.curriculum-section-badge {
  width: 56px;
  height: 56px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  font-weight: 700;
  flex-shrink: 0;
}
.curriculum-section-header-body { flex: 1; min-width: 0; }
.curriculum-section-header-name {
  font-size: 18px;
  font-weight: 500;
  color: var(--text);
  margin-bottom: 8px;
  line-height: 1.3;
}
.curriculum-section-header-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.curriculum-section-tier-label {
  font-size: 11px;
  color: var(--text-faint);
}

/* Inline mastery summary — always visible, NOT collapsible */
.curriculum-section-mastery-grid {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
}
.curriculum-section-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.curriculum-section-stat-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.curriculum-section-stat-value {
  font-size: 16px;
  font-weight: 500;
  color: var(--text);
}
.curriculum-section-stat-value--new { color: var(--sky-deep); }
.curriculum-section-stat-value--due { color: var(--honey-deep); }

/* ── E2: Section progression stacked bar ── */
.section-progress-stack {
  display: flex;
  width: 100%;
  height: 8px;
  border-radius: var(--radius-tiny);
  overflow: hidden;
  margin-bottom: 20px;
  background: var(--border);
}
.section-progress-stack__missed   { background: var(--grade-missed);   flex-shrink: 0; }
.section-progress-stack__hazy     { background: var(--grade-hazy);     flex-shrink: 0; }
.section-progress-stack__honed    { background: var(--grade-honed);    flex-shrink: 0; }
.section-progress-stack__mastered { background: var(--grade-mastered); flex-shrink: 0; }
.section-progress-stack__new      { background: var(--border-strong); flex-shrink: 0; }

/* ── E2: Chapters heading ── */
.curriculum-section-chapters-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 10px;
}

/* ── E2: Chapter callout list ── */
.chapter-callout-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.chapter-callout-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  cursor: pointer;
  display: flex;
  align-items: flex-start;
  gap: 14px;
  transition: box-shadow var(--duration-sm), border-color var(--duration-sm), background var(--duration-sm);
}
.chapter-callout-row:hover {
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  border-color: var(--border-strong);
  background: color-mix(in srgb, var(--sage) 4%, var(--surface));
}
.chapter-callout-badge {
  min-width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  background: var(--surface-elevated);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  font-family: var(--font-mono, monospace);
  color: var(--text-muted);
  flex-shrink: 0;
}
.chapter-callout-body { flex: 1; min-width: 0; }
.chapter-callout-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  margin-bottom: 6px;
  line-height: 1.3;
}
.chapter-callout-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.chapter-callout-stats {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.chapter-callout-stat {
  font-size: 11px;
  color: var(--text-faint);
}
.chapter-callout-stat--due { color: var(--honey-deep); font-weight: 600; }
.chapter-callout-sep { font-size: 10px; color: var(--border-strong); }
.chapter-callout-bar-wrap {
  max-width: 240px;
  height: 4px;
  background: var(--border);
  border-radius: var(--radius-2xs);
  overflow: hidden;
}
.chapter-callout-bar-fill {
  height: 100%;
  border-radius: var(--radius-2xs);
  background: var(--sky);
  transition: width 0.3s;
}
.chapter-callout-chevron {
  color: var(--text-faint);
  font-size: 16px;
  align-self: center;
  flex-shrink: 0;
}

/* ── E2: Not-found fallback ── */
.curriculum-section-not-found {
  padding: 40px 20px;
  text-align: center;
  color: var(--text-muted);
  font-size: 14px;
}
.curriculum-section-back-link {
  display: inline-block;
  margin-top: 12px;
  color: var(--sage);
  text-decoration: none;
  font-weight: 500;
}
.curriculum-section-back-link:hover { text-decoration: underline; }

/* ── E3: Chapter header card ── */
.curriculum-chapter-header-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px 20px 18px;
  margin-bottom: 12px;
  display: flex;
  gap: 18px;
  align-items: flex-start;
}
.curriculum-chapter-badge {
  min-width: 52px;
  height: 52px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  font-weight: 700;
  font-family: var(--font-mono, monospace);
  flex-shrink: 0;
  letter-spacing: 0.02em;
}
.curriculum-chapter-header-body { flex: 1; min-width: 0; }
.curriculum-chapter-header-name {
  font-size: 17px;
  font-weight: 500;
  color: var(--text);
  margin-bottom: 3px;
  line-height: 1.3;
}
.curriculum-chapter-header-sub {
  font-size: 12px;
  color: var(--text-faint);
  margin-bottom: 10px;
}
.curriculum-chapter-header-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

/* ── E3: Topic callout list ── */
.topic-callout-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* topic-callout-row extends chapter-callout-row visually */
.topic-callout-row { align-items: flex-start; }
.topic-callout-badge {
  min-width: 52px;
  height: auto;
  min-height: 36px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  font-family: var(--font-mono, monospace);
  flex-shrink: 0;
  padding: 4px 6px;
  letter-spacing: 0.02em;
  text-align: center;
  word-break: break-all;
  line-height: 1.2;
  margin-top: 2px;
}
.topic-callout-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  margin-bottom: 6px;
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.topic-callout-verb {
  font-weight: 600;
  color: var(--sage-deep);
  margin-right: 4px;
}
.topic-callout-syllabus {
  color: var(--text-muted);
}

/* Slim retention bar inside topic row */
.topic-callout-bar-row {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.topic-callout-bar-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
}
.topic-callout-bar-wrap {
  flex: 1;
  min-width: 80px;
  max-width: 200px;
  height: 5px;
  background: var(--border);
  border-radius: 3px;
  overflow: hidden;
}
.topic-callout-bar-fill {
  height: 100%;
  border-radius: 3px;
  transition: width 0.3s;
}
.topic-callout-bar-pct {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  min-width: 28px;
  text-align: right;
}

/* Recency badge (shown when last reviewed >30 days ago) */
.topic-callout-recency {
  font-size: 10px;
  color: var(--coral-deep);
  background: var(--coral-fill);
  border: 1px solid color-mix(in srgb, var(--coral) 25%, var(--border));
  border-radius: var(--radius-pill);
  padding: 1px 7px;
  font-weight: 600;
  white-space: nowrap;
}

/* ── E4: Topic deep page ────────────────────────────────────────────────── */

/* Topic header card */
.curriculum-topic-header-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px 16px;
  margin-bottom: 14px;
}
.curriculum-topic-header-code-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.curriculum-topic-header-code {
  font-size: 11px;
  font-weight: 700;
  font-family: var(--font-mono, monospace);
  border-radius: var(--btn-radius);
  padding: 2px 8px;
}
.curriculum-topic-header-title {
  font-size: 19px;
  font-weight: 500;
  color: var(--text);
  line-height: 1.35;
  margin-bottom: 5px;
}
.curriculum-topic-header-verb {
  font-weight: 700;
  color: var(--sage-deep);
}
.curriculum-topic-header-syllabus {
  font-size: 13px;
  color: var(--text-muted);
  font-style: italic;
}

/* Stats bar */
.curriculum-stats-bar {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 18px;
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  overflow-x: auto;
}
.curriculum-stats-bar-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex-shrink: 0;
}
.curriculum-stats-bar-mastery {
  font-size: 28px;
  font-weight: 500;
  color: var(--text);
  line-height: 1;
}
.curriculum-stats-bar-mastery-unit {
  font-size: 14px;
  font-weight: 400;
  color: var(--text-muted);
}
.curriculum-stats-bar-mastery-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.curriculum-stats-bar-band { flex-shrink: 0; }
.curriculum-stats-bar-divider {
  width: 1px;
  height: 36px;
  background: var(--border);
  flex-shrink: 0;
}
.curriculum-stats-bar-item {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex-shrink: 0;
}
.curriculum-stats-bar-item-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.curriculum-stats-bar-item-value {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
}
.curriculum-stats-bar-item-sub {
  font-size: 10px;
  font-weight: 400;
  color: var(--text-faint);
  margin-left: 4px;
}
.curriculum-stats-bar-caldelta--ok   { color: var(--sage-deep); }
.curriculum-stats-bar-caldelta--warn { color: var(--honey-deep, #a07800); }
.curriculum-stats-bar-caldelta--bad  { color: var(--coral-deep); }
.curriculum-stats-bar-tally {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
}
.curriculum-stats-bar-tally-item {
  font-size: 12px;
  font-weight: 600;
}
.curriculum-stats-bar-tally--missed   { color: #F05A50; }
.curriculum-stats-bar-tally--hazy     { color: #a07800; }
.curriculum-stats-bar-tally--honed    { color: #15803D; }
.curriculum-stats-bar-tally--mastered { color: var(--violet-deep); }
.curriculum-stats-bar-last-reviewed {
  font-size: 11px;
  color: var(--text-faint);
}

/* Retention sparkline */
.curriculum-sparkline {
  display: block;
  vertical-align: middle;
}

/* Content sections */
.curriculum-topic-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 14px;
}
.curriculum-topic-section-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  background: var(--surface-elevated);
  border-bottom: 1px solid var(--border);
}
.curriculum-topic-section-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-muted);
  flex: 1;
}
.curriculum-topic-section-count {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-faint);
  background: var(--border);
  border-radius: var(--radius-pill);
  padding: 1px 7px;
}
.curriculum-topic-section-body {}
.curriculum-topic-empty {
  padding: 14px 16px;
  font-size: 12px;
  color: var(--text-faint);
  font-style: italic;
}

/* Loading skeleton rows */
.curriculum-topic-section-body--loading {}
.curriculum-cardrow-skeleton {
  height: 52px;
  margin: 10px 16px;
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--border) 25%, var(--surface-elevated) 50%, var(--border) 75%);
  background-size: 200% 100%;
  animation: curriculum-skeleton-shimmer 1.4s infinite linear;
}
@keyframes curriculum-skeleton-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Card rows */
.curriculum-cardrow {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 16px;
  border-bottom: 1px solid var(--border);
  transition: background 0.1s;
}
.curriculum-cardrow:last-child { border-bottom: none; }
.curriculum-cardrow:hover { background: color-mix(in srgb, var(--sage) 4%, var(--surface)); }
.curriculum-cardrow--stem {
  border-left: 3px solid var(--sky-deep, #0369A1);
}
.curriculum-cardrow--leaf {
  padding-left: 32px;
  border-left: 3px solid color-mix(in srgb, var(--sky-deep, #0369A1) 35%, var(--border));
  position: relative;
}
.curriculum-cardrow--leaf::before {
  content: '';
  position: absolute;
  left: 14px;
  top: 50%;
  width: 12px;
  height: 1px;
  background: color-mix(in srgb, var(--sky-deep, #0369A1) 40%, var(--border));
}
.curriculum-cardrow-check {
  width: 16px;
  height: 16px;
  border-radius: 3px;
  border: 1.5px solid var(--border-strong);
  background: var(--surface-bright);
  cursor: pointer;
  flex-shrink: 0;
  margin-top: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.1s, border-color 0.1s;
}
.curriculum-cardrow-check.is-checked {
  background: var(--sage);
  border-color: var(--sage);
}
.curriculum-cardrow-check.is-checked::after {
  content: '✓';
  font-size: 10px;
  color: #fff;
  font-weight: 700;
}
.curriculum-cardrow-body { flex: 1; min-width: 0; }
.curriculum-cardrow-prompt {
  font-size: 13px;
  color: var(--text);
  margin-bottom: 4px;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.curriculum-cardrow-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.curriculum-cardrow-pp {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-faint);
  background: var(--surface-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 1px 7px;
  white-space: nowrap;
}
.curriculum-cardrow-right {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
.curriculum-cardrow-grade {
  font-size: 11px;
  font-weight: 700;
  border-radius: var(--radius-pill);
  padding: 2px 8px;
}
.curriculum-cardrow-grade--new     { background: var(--border); color: var(--text-faint); }
.curriculum-cardrow-grade--missed  { background: color-mix(in srgb, #F05A50 12%, var(--surface)); color: #C0392B; border: 1px solid color-mix(in srgb, #F05A50 30%, var(--border)); }
/* UI-04/07/13: hex → grade tokens. Backgrounds/borders are byte-identical in
   light mode (the tokens resolve to the same hexes); label colors move to the
   --grade-*-label set, which carries html.dark overrides — the dark-mode AA
   fail class is fixed by construction. */
.curriculum-cardrow-grade--hazy    { background: color-mix(in srgb, var(--grade-hazy) 12%, var(--surface)); color: var(--grade-hazy-label); border: 1px solid color-mix(in srgb, var(--grade-hazy) 30%, var(--border)); }
.curriculum-cardrow-grade--honed   { background: color-mix(in srgb, var(--grade-honed) 12%, var(--surface)); color: var(--grade-honed-label); border: 1px solid color-mix(in srgb, var(--grade-honed) 30%, var(--border)); }
.curriculum-cardrow-grade--mastered{ background: color-mix(in srgb, var(--grade-mastered) 10%, var(--surface)); color: var(--grade-mastered-label); border: 1px solid color-mix(in srgb, var(--grade-mastered) 30%, var(--border)); }

/* Pearl glyph */
.curriculum-pearl-glyph {
  font-size: 10px;
  color: var(--violet-deep);
  flex-shrink: 0;
}

/* Last-5 grade dot row */
.last-5-dots {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}
.hdot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
}
.hdot--missed   { background: #F05A50; }
.hdot--hazy     { background: var(--grade-hazy); }
.hdot--honed    { background: var(--grade-honed); }
.hdot--mastered { background: var(--grade-mastered); }
.hdot--new      { background: var(--border-strong); }

/* Coverage gaps */
.curriculum-gaps-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
}
.curriculum-gaps-row:last-child { border-bottom: none; }
.curriculum-gaps-text {
  font-size: 12px;
  color: var(--text-muted);
  flex: 1;
  font-style: italic;
}
.curriculum-gaps-ghost-btn {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-faint);
  background: transparent;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-pill);
  padding: 3px 10px;
  cursor: not-allowed;
  font-family: inherit;
  opacity: 0.6;
}

/* References sheet */
.curriculum-refs-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 14px;
}
.curriculum-refs-header {
  padding: 12px 16px;
  background: var(--surface-elevated);
  border-bottom: 1px solid var(--border);
}
.curriculum-refs-header-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.curriculum-refs-group {
  border-bottom: 1px solid var(--border);
}
.curriculum-refs-group:last-child { border-bottom: none; }
.curriculum-refs-group-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  cursor: pointer;
  background: transparent;
  border: none;
  width: 100%;
  text-align: left;
  font-family: inherit;
  transition: background 0.1s;
}
.curriculum-refs-group-toggle:hover { background: color-mix(in srgb, var(--sage) 4%, var(--surface)); }
.curriculum-refs-group-chevron {
  font-size: 10px;
  color: var(--text-faint);
  flex-shrink: 0;
}
.curriculum-refs-group-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  flex: 1;
}
.curriculum-refs-group-count {
  font-size: 11px;
  color: var(--text-faint);
  background: var(--border);
  border-radius: var(--radius-pill);
  padding: 1px 6px;
}
.curriculum-refs-group-body {
  display: none;
  flex-direction: column;
}
.curriculum-refs-group-body.is-open { display: flex; }
.curriculum-refs-pending-note {
  padding: 10px 16px 10px 32px;
  font-size: 12px;
  color: var(--text-faint);
  font-style: italic;
}

/* Sticky multi-select footer */
.curriculum-multi-footer {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  transform: none;
  border-radius: 0;
  border-top: 1px solid var(--border);
  padding: 10px 20px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 0;
  background: var(--surface-elevated);
  box-shadow: 0 -2px 12px rgba(0,0,0,0.08);
  z-index: 1100;
}
.curriculum-multi-footer-left {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-faint);
}
.curriculum-multi-footer-centre {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
}
.curriculum-multi-footer-right {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: flex-end;
}
.curriculum-multi-footer-btn {
  padding: 7px 13px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  border: none;
  font-family: inherit;
  transition: background var(--duration-sm), color var(--duration-sm);
}
.curriculum-multi-footer-btn--primary {
  background: var(--sage);
  color: #fff;
}
.curriculum-multi-footer-btn--primary:hover { background: var(--sage-deep); }
.curriculum-multi-footer-btn--ghost {
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
}
.curriculum-multi-footer-btn--ghost:hover { background: var(--sage-fill); color: var(--sage-deep); }
.curriculum-multi-footer-btn--push {
  background: color-mix(in srgb, var(--coral, #E07A5F) 12%, transparent);
  color: var(--coral, #E07A5F);
  border: 1.5px solid var(--coral, #E07A5F);
}
.curriculum-multi-footer-btn--push:hover { background: color-mix(in srgb, var(--coral, #E07A5F) 22%, transparent); }
.curriculum-multi-footer-btn--mastered {
  background: color-mix(in srgb, var(--grade-mastered) 10%, transparent);
  color: var(--grade-mastered-label);
  border: 1.5px solid var(--grade-mastered);
}
.curriculum-multi-footer-btn--mastered:hover { background: color-mix(in srgb, var(--grade-mastered) 20%, transparent); }
/* iOS-render audit 2026-05-23 — the 1fr/auto/1fr grid packs 7 buttons across
   one row; on phones the right column (Select all / Cancel) is shoved off the
   right edge and "Change Scope" is clipped. Stack to a single column with
   wrapping button rows, and fold safe-area into the padding so the bar clears
   the home indicator (bottom) and notch (sides) in standalone mode. */
@media (max-width: 600px) {
  .curriculum-multi-footer {
    grid-template-columns: 1fr;
    gap: 8px;
    padding: 10px max(20px, env(safe-area-inset-right, 0px))
                  max(10px, env(safe-area-inset-bottom, 0px))
                  max(20px, env(safe-area-inset-left, 0px));
  }
  .curriculum-multi-footer-left { text-align: center; }
  .curriculum-multi-footer-centre,
  .curriculum-multi-footer-right { flex-wrap: wrap; justify-content: center; }
  .curriculum-multi-footer-btn { padding: 7px 11px; }
}
/* iOS-render audit 2026-05-23 — Change Scope acts on a selection, so hide it
   when nothing is selected; Select all + Cancel (the way out of select mode)
   stay. Applies at every width. */
.curriculum-multi-footer[data-n="0"] .curriculum-multi-footer-btn--primary { display: none; }

/* ── E5: Header centre tap target ─────────────────────────────────────── */
/* flex:1 is already set by .app-title's grid column; min-inline-size
   keeps the tap zone away from the side button clusters. */
[data-curriculum-tap="1"] { min-inline-size: 96px; }
@media (hover: hover) {
  [data-curriculum-tap="1"] { cursor: pointer; }
  [data-curriculum-tap="1"]:hover .wordmark {
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 1px;
    text-decoration-color: color-mix(in srgb, var(--text) 35%, transparent);
  }
}

/* ── E6: Backlink chip row ─────────────────────────────────────────────── */
/* Base chip — no fill, no outline (Sprint-D pattern). */
.chip {
  display: inline-flex;
  align-items: center;
  font-size: 10.5px;
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
  padding: 1px 0;
  background: none;
  border: none;
  transition: color 0.1s;
}
.chip:hover { color: var(--sage-deep, #2D5A35); }
/* Curriculum chips inherit base; the sep spans sit between them. */
.chip--curriculum { color: var(--sage, #4F7050); }
.chip--curriculum:hover { color: var(--sage-deep, #2D5A35); }
/* Breadcrumb container row */
.curriculum-breadcrumb {
  display: flex;
  align-items: center;
  gap: 0;
  margin-bottom: 6px;
  flex-wrap: nowrap;
  overflow: hidden;
}
.curriculum-breadcrumb__sep {
  font-size: 10.5px;
  color: var(--text-faint);
  padding: 0 2px;
  user-select: none;
}

/* ─── Curriculum overlay — bottom sheet (iOS-render audit 2026-05-23) ─────────
   Was a centred full-screen card with a floating ✕ that collided with the
   Dynamic Island. Now a bottom-up sheet: anchored to the bottom, slides up,
   dismissed by dragging the grab handle (touch) or tapping the backdrop / Esc.
   No ✕ button. The sheet top sits ~8dvh below the viewport top, clearing the
   island in standalone mode with no safe-area-top padding needed. */
.curriculum-overlay[hidden]{display:none}
.curriculum-overlay{
  position:fixed; inset:0; z-index:1000;
  display:flex; align-items:flex-end; justify-content:center;
  animation:backdropIn .15s ease;
}
.curriculum-overlay-backdrop{
  position:absolute; inset:0;
  /* Heavy cinema-style backdrop so the underlying tab fully recedes. */
  background:rgba(8,8,16,0.78);
  -webkit-backdrop-filter:blur(10px) saturate(140%);
  backdrop-filter:blur(10px) saturate(140%);
}
/* Fallback if backdrop-filter unsupported: darker scrim alone still hides content. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .curriculum-overlay-backdrop{ background:rgba(8,8,16,0.92); }
}
/* Sheet container — grab handle + scroll body, anchored bottom, rounded top. */
.curriculum-overlay-sheet{
  position:relative; z-index:1;
  display:flex; flex-direction:column;
  /* iOS-render audit 2026-05-23 — full viewport width (no centred 1100px cap)
     and a FIXED 92dvh height (not max-height) so the sheet keeps constant
     dimensions while navigating section → chapter → topic, even when a node has
     little content. Inner .curriculum-page still caps its own readable width. */
  width:100%; max-width:none;
  height:92dvh;
  background:var(--surface); color:var(--text);
  border-radius:20px 20px 0 0;
  box-shadow:0 -20px 50px -10px rgba(0,0,0,0.45);
  overflow:hidden;
  will-change:transform;
  animation:sheetUp var(--duration-md, var(--duration-lg)) cubic-bezier(.32,.72,0,1);
}
html.dark .curriculum-overlay-sheet{
  box-shadow:0 -20px 50px -10px rgba(0,0,0,0.70);
  border:1px solid var(--border-strong); border-bottom:none;
}
/* Grab handle — drag target for swipe-to-dismiss (wired via _addSheetDragClose). */
.curriculum-overlay-grab{
  flex:none; height:26px; display:flex; align-items:center; justify-content:center;
  cursor:grab; touch-action:none;
}
.curriculum-overlay-grab::before{
  content:''; width:40px; height:5px; border-radius:3px;
  background:var(--border-strong);
}
/* Scroll body — holds the curriculum render (header, breadcrumb, lists). */
.curriculum-overlay-card{
  flex:1; min-height:0;
  overflow-x:hidden; overflow-y:auto;
  overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  padding-bottom:60px;
}
/* ── Sprint E dark-mode overrides ──────────────────────────────────────────
   Hardcoded foreground colours that are too dark for Slate Dusk surfaces.
   Backgrounds already adapt via color-mix(…var(--surface)) — only text needs
   lifting. Band token dark lifts are defined in html.dark :root above. */
html.dark .band-pill--building { color: var(--mint); }
html.dark .band-pill--honed    { color: #79B9DD; }
html.dark .band-pill--mastered {
  color: var(--violet-deep);
  background: color-mix(in srgb, var(--violet-deep) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--violet-deep) 30%, var(--border));
}
html.dark .gt-hazy { color: var(--honey); }
html.dark .curriculum-stats-bar-tally--hazy   { color: var(--honey); }
html.dark .curriculum-cardrow-grade--missed   { color: var(--coral); }
html.dark .curriculum-cardrow-grade--hazy     { color: var(--honey); }
html.dark .curriculum-cardrow-grade--mastered { color: var(--violet-deep); }
html.dark .curriculum-cardrow-skeleton {
  background: linear-gradient(90deg,
    var(--surface-elevated) 25%,
    var(--surface-bright)   50%,
    var(--surface-elevated) 75%);
  background-size: 200% 100%;
}
/* Lock body scroll while the overlay is open */
body.curriculum-overlay-open{ overflow:hidden; }

/* Layering — overlays/sheets/modals opened FROM within the curriculum overlay
   must sit ABOVE it (curriculum overlay is z-index 1000). Bump common backdrop
   surfaces to 1100 only while the curriculum overlay is open, so the rest of
   the app's z-index scheme is undisturbed. */
body.curriculum-overlay-open .ns-modal,
body.curriculum-overlay-open .sheet-backdrop,
body.curriculum-overlay-open .preview-overlay,
body.curriculum-overlay-open .search-palette,
body.curriculum-overlay-open .settings-backdrop,
body.curriculum-overlay-open #curriculumPickerSheet,
body.curriculum-overlay-open .overlay,
body.curriculum-overlay-open #flagSheetOverlay,
body.curriculum-overlay-open #refsSheet,
body.curriculum-overlay-open .refs-sheet-backdrop,
body.curriculum-overlay-open .refs-sheet,
body.curriculum-overlay-open .miss-tag-overlay,
body.curriculum-overlay-open .focus-overlay{
  z-index:1100;
}
/* Bottom-attached select bars (e.g. lib-select-bar) need to clear the curriculum
   overlay when triggered from card multi-select inside it. */
body.curriculum-overlay-open .lib-select-bar{ z-index:1110; }

/* ============================================================
   UNIFIED CARD PRIMITIVE — v3.1 spec
   Additive: coexists with legacy .recall-card / .saq-card-face / .axiom / .pharma-card.
   Activated by `data-state` + `data-type` attributes; opt-in via wrapping JS during migration.
   ============================================================ */
.card[data-state] {
  position: relative;
  background: var(--surface-bright);
  color: var(--text);
  border: 1px solid var(--border);
  border-left: var(--card-stripe-width) solid var(--card-accent, var(--type-recall));
  border-radius: var(--card-radius);
  padding: var(--card-padding-block) var(--card-padding-inline);
  box-shadow: var(--card-shadow, 0 1px 2px rgba(0,0,0,0.06));
  display: flex; flex-direction: column;
  gap: 10px;
  transition: box-shadow 160ms ease;
}
.card[data-type="recall"] { --card-accent: var(--type-recall); }
.card[data-type="saq"]    { --card-accent: var(--type-saq); }
.card[data-type="axiom"]  { --card-accent: var(--type-axiom); }
.card[data-type="pharma"] { --card-accent: var(--type-pharma); }

.card[data-state="inactive"] {
  --card-padding-block:  var(--study-card-padding-cmp-y, 10px);
  --card-padding-inline: var(--study-card-padding-cmp-x, 12px);
  background: var(--surface-elevated);
}

/* Header — single geometry */
.card__header {
  display: flex; align-items: center; gap: 6px;
  height: 28px; min-height: 28px;
}
.card__header-left { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; }
.card__header-right { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

.card__logo {
  width: 24px; height: 24px;
  background: var(--card-accent);
  border-radius: 5px;
  display: inline-flex; align-items: center; justify-content: center;
  color: white; flex-shrink: 0;
  position: relative;
}
.card__logo .lucide { stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; fill: none; }

@keyframes card-pearl-breath {
  0%, 100% { box-shadow: inset 0 0 0 0 rgba(255,255,255,0); }
  50%      { box-shadow: inset 0 0 6px 1px rgba(255,255,255,0.55); }
}
.card__logo.is-pearl { animation: card-pearl-breath 2s ease-in-out infinite; cursor: help; }

.card__type-chip {
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
  padding: 2px 7px; border-radius: var(--radius-tiny);
  background: color-mix(in srgb, var(--card-accent) 14%, var(--surface));
  color: var(--card-accent);
  border: 1px solid color-mix(in srgb, var(--card-accent) 28%, transparent);
  flex-shrink: 0; line-height: 1.5;
}
.card__type-chip--narrow { padding: 2px 6px; }

.card__breadcrumb {
  font-size: var(--font-size-sm-plus);
  color: var(--text);
  background: transparent; border: 0;
  padding: 2px 4px;
  cursor: pointer; white-space: nowrap;
  text-decoration: none;
  overflow: hidden; text-overflow: ellipsis;
}
.card__breadcrumb:hover { text-decoration: underline; }

.card__rail { width: 96px; height: 22px; display: flex; align-items: center; justify-content: flex-end; flex-shrink: 0; position: relative; }
.card__menu {
  background: none; border: none; color: var(--text-muted);
  font-size: 16px; cursor: pointer; padding: 0 4px; line-height: 1;
}
.card__menu:hover { color: var(--text); }

/* Footer — fixed footprint, all three states overlap */
.card__footer { position: relative; height: 96px; margin-top: 14px; }
.card__reveal, .card__grades, .card__miss-tags { position: absolute; inset: 0; transition: opacity 180ms ease; }
.card__reveal {
  width: 100%;
  background: color-mix(in srgb, var(--card-accent) 12%, var(--surface-bright));
  border: 1.5px solid color-mix(in srgb, var(--card-accent) 30%, var(--border));
  border-radius: var(--radius-sm);
  font-size: var(--font-size-md); font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--card-accent);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-family: inherit;
}
.card__grades { display: flex; flex-direction: column; gap: 4px; opacity: 0; pointer-events: none; }
.card__grades.is-visible { opacity: 1; pointer-events: auto; }
.card__grade-top { flex: 0 0 calc(50% - 2px); display: flex; }
.card__grade-bottom { flex: 0 0 calc(50% - 2px); display: flex; gap: 4px; }
.card__grade-btn {
  border: none; border-radius: var(--radius-sm); cursor: pointer;
  flex: 1; height: 100%;
  font-family: inherit;
  transition: filter 100ms ease, transform var(--duration-xs) ease;
  position: relative;
}
.card__grade-btn:hover { filter: brightness(1.06); transform: translateY(-1px); }
.card__grade-btn--mastered { background: var(--grade-mastered); }
.card__grade-btn--missed   { background: var(--grade-missed); }
.card__grade-btn--honed    { background: var(--grade-honed); }
.card__miss-tags { display: flex; gap: 4px; opacity: 0; pointer-events: none; }
.card__miss-tags.is-visible { opacity: 1; pointer-events: auto; }
.card__miss-tag {
  flex: 1; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--grade-missed) 12%, var(--surface-bright));
  border: 1.5px solid color-mix(in srgb, var(--grade-missed) 30%, var(--border));
  color: var(--grade-missed);
  font-size: var(--font-size-sm-plus); font-weight: 600;
  cursor: pointer; font-family: inherit;
}

/* ============================================================
   PHASE 5 — pearl / nemesis / streak burst / dot rail morph
   Additive: extends classes already defined in Phase 1 universal primitive.
   ============================================================ */

/* PEARL — stripe sheen + holographic radial behind body */
@keyframes card-pearl-stripe-sheen {
  0%   { background-position: 0 -100%, 0 0; }
  60%  { background-position: 0 200%,  0 0; }
  100% { background-position: 0 200%,  0 0; }
}
@keyframes card-pearl-holo-rotate {
  from { filter: hue-rotate(0deg); }
  to   { filter: hue-rotate(360deg); }
}
.card.is-pearl,
.recall-card.is-pearl,
.saq-card-face.is-pearl,
.axiom.is-pearl,
.pharma-card.is-pearl,
.fc-card.is-pearl {
  position: relative;
}
.card.is-pearl::before,
.recall-card.is-pearl::before,
.saq-card-face.is-pearl::before,
.axiom.is-pearl::before,
.pharma-card.is-pearl::before,
.fc-card.is-pearl::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0;
  width: var(--card-stripe-width, 4px);
  background:
    linear-gradient(180deg,
      transparent 0%, transparent 20%,
      color-mix(in srgb, white 55%, var(--card-accent)) 48%,
      color-mix(in srgb, white 55%, var(--card-accent)) 52%,
      transparent 80%, transparent 100%),
    var(--card-accent);
  background-size: 100% 300%, 100% 100%;
  background-position: 0 -100%, 0 0;
  background-repeat: no-repeat;
  animation: card-pearl-stripe-sheen 4.5s ease-in-out infinite;
  z-index: 1;
  pointer-events: none;
  border-radius: var(--card-radius, 12px) 0 0 var(--card-radius, 12px);
}
.card.is-pearl > .card__holo-bg,
.recall-card.is-pearl > .card__holo-bg,
.saq-card-face.is-pearl > .card__holo-bg,
.axiom.is-pearl > .card__holo-bg,
.pharma-card.is-pearl > .card__holo-bg,
.fc-card.is-pearl > .card__holo-bg {
  position: absolute; inset: 0;
  border-radius: var(--card-radius, 12px);
  background: radial-gradient(ellipse 120% 80% at 50% 50%,
    hsl(200, 80%, 75%) 0%,
    hsl(280, 70%, 78%) 25%,
    hsl(120, 70%, 76%) 50%,
    hsl(40,  85%, 72%) 75%,
    hsl(0,   80%, 75%) 100%);
  opacity: 0.18;  /* LM */
  z-index: 0;
  animation: card-pearl-holo-rotate 12s linear infinite;
  pointer-events: none;
}
html.dark .card.is-pearl > .card__holo-bg,
html.dark .recall-card.is-pearl > .card__holo-bg,
html.dark .saq-card-face.is-pearl > .card__holo-bg,
html.dark .axiom.is-pearl > .card__holo-bg,
html.dark .pharma-card.is-pearl > .card__holo-bg,
html.dark .fc-card.is-pearl > .card__holo-bg {
  opacity: 0.14;  /* DM — slightly less to keep text crisp */
}
.card.is-pearl:hover::before,
.card.is-pearl:hover > .card__holo-bg,
.recall-card.is-pearl:hover::before,
.recall-card.is-pearl:hover > .card__holo-bg,
.saq-card-face.is-pearl:hover::before,
.saq-card-face.is-pearl:hover > .card__holo-bg,
.axiom.is-pearl:hover::before,
.axiom.is-pearl:hover > .card__holo-bg,
.pharma-card.is-pearl:hover::before,
.pharma-card.is-pearl:hover > .card__holo-bg,
.fc-card.is-pearl:hover::before,
.fc-card.is-pearl:hover > .card__holo-bg {
  animation-play-state: paused;
}

/* PEARL POPOVER */
.card__pearl-popover {
  position: absolute;
  background: var(--surface-bright);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-size: 11.5px;
  color: var(--text);
  box-shadow: 0 6px 18px rgba(0,0,0,0.10), 0 2px 4px rgba(0,0,0,0.06);
  width: 240px;
  z-index: 50;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity 160ms ease, transform 160ms ease;
}
html.dark .card__pearl-popover { box-shadow: 0 6px 18px rgba(0,0,0,0.5), 0 2px 4px rgba(0,0,0,0.4); }
.card__pearl-popover.is-open { opacity: 1; pointer-events: auto; transform: translateY(0); }
.card__pearl-popover h4 {
  margin: 0 0 6px;
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--grade-honed); font-weight: 800;
}
.card__pearl-popover .pp-line { display: flex; gap: 6px; margin-bottom: 4px; line-height: 1.45; }
.card__pearl-popover .pp-line .k { color: var(--text-muted); font-size: 10.5px; min-width: 64px; text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; }
.card__pearl-popover .pp-line .v { color: var(--text); font-size: 11.5px; }
.card__pearl-popover .pp-strength { display: inline-flex; gap: 2px; align-items: center; }
.card__pearl-popover .pp-strength .pip { width: 5px; height: 5px; border-radius: 50%; background: color-mix(in srgb, var(--grade-honed) 30%, var(--border)); }
.card__pearl-popover .pp-strength .pip.lit { background: var(--grade-honed); }

/* DOT RAIL — default 5 dots, hover/tap chip, post-grade pulse, nemesis */
.card__rail .rr-dots {
  display: flex; align-items: center; gap: 4px;
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  transition: opacity var(--duration-md), transform var(--duration-md);
}
.card__rail .rr-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.card__rail .rr-dot.empty    { background: transparent; border: 1px solid var(--border); }
.card__rail .rr-dot.missed   { background: var(--grade-missed); }
.card__rail .rr-dot.honed    { background: var(--grade-honed); }
.card__rail .rr-dot.mastered { background: var(--grade-mastered); }

.card__rail .rr-chip {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  height: 22px; max-width: 96px;
  padding: 0 9px; border-radius: 11px;
  border: 1px solid var(--border);
  background: var(--surface);
  display: flex; align-items: center;
  white-space: nowrap; font-size: var(--font-size-2xs, 10px);
  color: var(--text-muted);
  opacity: 0; pointer-events: none;
  transition: opacity var(--duration-md);
}
.card__rail .rr-chip.overdue { border-color: var(--grade-missed); color: var(--grade-missed); }

@keyframes card-rr-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--card-accent, var(--type-recall)) 45%, transparent); }
  60%  { box-shadow: 0 0 0 6px color-mix(in srgb, var(--card-accent, var(--type-recall)) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--card-accent, var(--type-recall)) 0%, transparent); }
}
.card__rail .rr-chip.pulsing { animation: card-rr-pulse 1.5s ease-out; }

.card__rail.mode-chip .rr-dots { opacity: 0; pointer-events: none; }
.card__rail.mode-chip .rr-chip { opacity: 1; pointer-events: auto; }

/* NEMESIS — letters on fire (ember bloom — locked) */
.card__rail .rr-nemesis {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  width: 96px; height: 22px;
  display: flex; align-items: center; justify-content: center;
}
.card__rail .nem-text {
  font-size: 11px; font-weight: 800;
  letter-spacing: 0.18em; text-transform: uppercase;
  background: linear-gradient(180deg,
    var(--nemesis-gold)    0%,
    var(--nemesis-ember)  35%,
    var(--nemesis-crimson) 100%);
  background-size: 100% 200%;
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  position: relative;
  line-height: 1;
}
@keyframes card-nem-bloom {
  0%, 100% {
    text-shadow: 0 0 4px var(--nemesis-ember), 0 0 0 transparent;
    background-position: 0 100%;
  }
  50% {
    text-shadow:
      0 0 8px var(--nemesis-ember),
      0 0 18px color-mix(in srgb, var(--nemesis-ember) 60%, transparent),
      0 0 36px color-mix(in srgb, var(--nemesis-crimson) 25%, transparent);
    background-position: 0 50%;
  }
}
.card__rail .nem-text--bloom { animation: card-nem-bloom 3.2s ease-in-out infinite; }

/* STREAK BURST — per-dot ember→gold particles (5 dots × 3 particles) */
.card__rail .streak-burst-multi {
  position: absolute; right: 0; top: 50%;
  width: 96px; height: 22px;
  pointer-events: none;
  transform: translateY(-50%);
}
.card__rail .streak-burst-multi .dot-burst {
  position: absolute; top: 11px;
  width: 0; height: 0;
}
.card__rail .streak-burst-multi .particle {
  position: absolute; left: 0; top: 0;
  width: 3px; height: 3px; border-radius: 50%;
  background: var(--nemesis-ember);
  opacity: 0;
  transform: translate(-50%, -50%);
}
@keyframes card-streak-pop {
  0%   { transform: translate(-50%, -50%) scale(1); opacity: 1; background: var(--nemesis-ember); }
  55%  { background: var(--nemesis-gold); }
  100% { transform: translate(calc(-50% + var(--pdx, 10px)), calc(-50% + var(--pdy, -14px))) scale(0); opacity: 0; background: var(--grade-mastered); }
}
.card__rail .streak-burst-multi.is-bursting .dot-burst:nth-child(1) .particle { animation: card-streak-pop 750ms cubic-bezier(0.2,0.7,0.2,1)   0ms forwards; }
.card__rail .streak-burst-multi.is-bursting .dot-burst:nth-child(2) .particle { animation: card-streak-pop 750ms cubic-bezier(0.2,0.7,0.2,1)  60ms forwards; }
.card__rail .streak-burst-multi.is-bursting .dot-burst:nth-child(3) .particle { animation: card-streak-pop 750ms cubic-bezier(0.2,0.7,0.2,1) var(--duration-sm) forwards; }
.card__rail .streak-burst-multi.is-bursting .dot-burst:nth-child(4) .particle { animation: card-streak-pop 750ms cubic-bezier(0.2,0.7,0.2,1) 180ms forwards; }
.card__rail .streak-burst-multi.is-bursting .dot-burst:nth-child(5) .particle { animation: card-streak-pop 750ms cubic-bezier(0.2,0.7,0.2,1) 240ms forwards; }

/* REDUCED MOTION */
@media (prefers-reduced-motion: reduce) {
  .card.is-pearl::before,
  .card.is-pearl > .card__holo-bg,
  .recall-card.is-pearl::before,
  .recall-card.is-pearl > .card__holo-bg,
  .saq-card-face.is-pearl::before,
  .saq-card-face.is-pearl > .card__holo-bg,
  .axiom.is-pearl::before,
  .axiom.is-pearl > .card__holo-bg,
  .pharma-card.is-pearl::before,
  .pharma-card.is-pearl > .card__holo-bg,
  .fc-card.is-pearl::before,
  .fc-card.is-pearl > .card__holo-bg,
  .card__rail .nem-text--bloom,
  .card__rail .streak-burst-multi.is-bursting .particle {
    animation: none;
  }
}

/* ============================================================
   v3.1 LIVE-TEST FIXES (round 2) — conditional logo positioning,
   pre-reveal hide for all card types, plain-text type-chip,
   graded card interactability, rail spacing
   ============================================================ */

/* ============================================================
   UNIVERSAL HEADER POSITIONING — v3.1 final
   Absolute-positioned header anchored to the card's top edge.
   Works identically across today / focus / library / browse /
   preview / drug-stem because it's decoupled from card padding.
   ============================================================ */

/* Card surfaces become positioning contexts */
.recall-card, .recall-card--lib, .recall-card--browse,
.saq-card-face, .saq-card--lib, .saq-card--browse,
.axiom, .axiom--lib, .axiom--browse,
.pharma-card, .pharma-drug-card, .pharma-class-card,
.fc-card, .card[data-state] {
  position: relative;
}

/* Header — floats at top of card, edge-to-edge over the stripe and padding.
   left:0 positions inside the card's padding-box; the logo's flush border-radius
   sits naturally against the card's left-border stripe. */
.card__header {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 32px;
  display: flex;
  align-items: stretch;
  z-index: 5;
  margin: 0 !important;
  padding: 0;
}
.card__header-left {
  display: flex;
  align-items: stretch;
  flex: 1;
  min-width: 0;
  height: 100%;
  gap: 0;
}
.card__header-right {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  height: 100%;
  gap: 14px;
  padding-right: 6px;  /* breathing room from card's right edge */
}

/* Logo chip — flush with stripe + smoothed top-left corner that follows the
   card's outer radius (minus the stripe width). Bottom-left stays at 0 because
   the stripe continues straight downward beside the body. */
.card__header .card__logo {
  width: 32px;
  height: 32px;
  border-radius: calc(var(--card-radius, 12px) - var(--card-stripe-width, 4px)) 5px 5px 0;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Card body — padded below the absolute header so content doesn't sit underneath */
.recall-card,
.saq-card-face,
.axiom,
.pharma-card,
.card[data-state] {
  padding-top: calc(32px + 10px) !important;  /* header height + breathing space */
}

/* Library and browse — same padding behaviour */
.recall-card--lib, .recall-card--browse,
.saq-card--lib, .saq-card--browse,
.axiom--lib, .axiom--browse,
.pharma-card[data-mode="library"], .pharma-card[data-mode="browse"] {
  padding-top: calc(32px + 8px) !important;
}

/* Inactive (preview / drug-stem / drug-class) — compact header at 26px */
.fc-card--preview .card__header,
.pharma-card[data-mode="preview"] .card__header,
.pharma-drug-card .card__header,
.pharma-class-card .card__header,
.card[data-state="inactive"] .card__header {
  height: 26px;
}
.fc-card--preview .card__header .card__logo,
.pharma-card[data-mode="preview"] .card__header .card__logo,
.pharma-drug-card .card__header .card__logo,
.pharma-class-card .card__header .card__logo,
.card[data-state="inactive"] .card__header .card__logo {
  width: 26px;
  height: 26px;
}
.fc-card--preview,
.pharma-card[data-mode="preview"],
.pharma-drug-card,
.pharma-class-card,
.card[data-state="inactive"] {
  padding-top: calc(26px + 8px) !important;
}

/* Focus card — same absolute header; preserve cinema body */
.fc-card {
  padding-top: calc(32px + 12px) !important;
  padding-left: 22px;
  padding-right: 18px;
  padding-bottom: 18px;
}

/* Type-chip: a coloured pill extending from the logo's right edge.
   height:100% fills the absolute header naturally — no per-surface overrides needed. */
.card__type-chip,
.card__ctx-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 10px;
  font-size: var(--font-size-sm-plus, 13px);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: none;
  white-space: nowrap;
  background: color-mix(in srgb, var(--card-accent) 14%, var(--surface));
  color: var(--card-accent);
  border: 1px solid color-mix(in srgb, var(--card-accent) 35%, transparent);
  border-left: 0;
  border-radius: 0 5px 5px 0;
  margin-left: -1px; /* sit flush against logo */
  flex-shrink: 0;
  height: 100%;
  opacity: 1;
}

/* Compact header surfaces — smaller chip font + tighter padding */
.fc-card--preview .card__type-chip,
.fc-card--preview .card__ctx-chip,
.pharma-card[data-mode="preview"] .card__type-chip,
.pharma-card[data-mode="preview"] .card__ctx-chip,
.pharma-drug-card .card__type-chip,
.pharma-drug-card .card__ctx-chip,
.pharma-class-card .card__type-chip,
.pharma-class-card .card__ctx-chip,
.card[data-state="inactive"] .card__type-chip,
.card[data-state="inactive"] .card__ctx-chip {
  font-size: var(--font-size-sm, 12px);
  padding: 0 8px;
}

/* Header-left: breadcrumb breathing room */
.card__header-left > .card__breadcrumb {
  margin-left: 8px;
}

/* ── Breadcrumb: faded default, full opacity on hover/focus ── */
.card__breadcrumb,
.card__header .card__breadcrumb {
  opacity: 0.62;
  transition: opacity 140ms ease, text-decoration 140ms ease;
  cursor: pointer;
  /* Vertically align the breadcrumb's text mid-line with the chip + dot rail
     centre. inline-flex with align-items:center + height:100% + line-height:1
     keeps the cap height balanced across font metrics. */
  display: inline-flex;
  align-items: center;
  height: 100%;
  min-height: 24px; /* WCAG 2.5.8 SC — 24 px target-size minimum */
  line-height: 1;
}
.card__breadcrumb:hover,
.card__header .card__breadcrumb:hover {
  opacity: 1;
  text-decoration: underline;
}
.card__breadcrumb:focus-visible {
  opacity: 1;
  outline: 2px solid var(--card-accent, var(--accent));
  outline-offset: 2px;
  border-radius: 3px;
}

/* ── Rail: 5-dot history strip in the right slot ── */
.card__rail {
  width: 80px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-shrink: 0;
  position: relative;
}
.card__rail .rr-dots {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 4px;
}

/* ── ⋯ menu in header: circular, vertically centred; override floating position:absolute ── */
.card__menu,
.card__header-right .card-options-btn {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  /* Reset the global position:absolute from .card-options-btn */
  position: relative;
  top: auto;
  right: auto;
  margin: 2px 0;
}

/* ── Grade button text rendering ── */
.r-grade {
  font-size: var(--font-size-sm-plus, 13px);
  font-weight: 700;
  letter-spacing: 0.04em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ── Pre-reveal: hide grade row + miss-tag overlay for ALL card types ── */
/* Only recall + axiom had this rule; add focus/pharma/saq-card-face. */
.fc-card:not(.revealed) .post-reveal,
.fc-card:not(.revealed) .miss-tag-overlay,
.pharma-card:not(.revealed) .post-reveal,
.pharma-card:not(.revealed) .miss-tag-overlay,
.saq-card-face:not(.revealed) .post-reveal,
.saq-card-face:not(.revealed) .miss-tag-overlay,
.card[data-state="active"]:not(.revealed) .post-reveal,
.card[data-state="active"]:not(.revealed) .miss-tag-overlay {
  display: none;
}

/* ── Focus mode: ensure miss-tag overlay isn't clipped by card overflow ── */
.fc-card .recall-actions {
  position: relative;
  z-index: 5;
}
.fc-card.tag-open .miss-tag-overlay {
  position: relative;
  z-index: 6;
  overflow: visible;
}

/* v10 (2026-05-19) — .study-card--nemesis modifier.
   Nemesis card type uses a 3-stop vertical gradient stripe instead of a single
   border-left color. Visual loudness is intentional — signals "hunt this weak topic".
   Implementation: border-left:none + ::before pseudo with width 4px and the gradient.
   See DESIGN-SYSTEM.md §1 v10 + DEC-024 (Nemesis as 5th card-type identity). */
.study-card--nemesis{border-left:none;position:relative}
.study-card--nemesis::before{
  content:'';position:absolute;left:0;top:0;bottom:0;width:4px;
  background:linear-gradient(180deg,
    var(--nemesis-crimson) 0%,
    var(--nemesis-ember) 55%,
    var(--nemesis-gold) 100%);
  border-radius:var(--card-radius,12px) 0 0 var(--card-radius,12px);
}
.study-card--nemesis .study-card__type-label,
.study-card--nemesis .type-label{color:var(--nemesis-crimson)}

/* ── Graded cards (today): KEEP interactive — undo grade, click tabs/menu ── */
/* OVERRIDE the prior-session pointer-events:none lockout: cards remain fully clickable. */
.study-card[data-session-context="last"] {
  opacity: 1;
  pointer-events: auto;
}
/* Subtle visual distinction for resumed-from-prior-session graded cards */
.study-card[data-session-context="last"][data-graded] {
  opacity: 0.85;
}
.study-card[data-session-context="last"][data-graded]:hover {
  opacity: 1;
}
/* Ensure the undo-chip, options menu, and SAQ tabs are always clickable when graded */
.study-card[data-graded] .study-card__chip,
.study-card[data-graded] .card-options-btn,
.study-card[data-graded] .card__menu,
.study-card[data-graded] .saq-tab,
.study-card[data-graded] .saq-callout-tab,
.study-card[data-graded] .card__breadcrumb {
  pointer-events: auto !important;
}
@keyframes rr-dot-pop {
  0%   { transform: scale(0.4); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}
.card__rail .rr-dot.rr-dot--new {
  animation: rr-dot-pop 240ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

/* Focus-mode card chrome — content stays inside the card outline.
   Card may grow taller; nothing bleeds past the rounded rectangle.
   padding-top is set by the universal header block above (32px + 12px). */
.fc-card {
  overflow: hidden !important;  /* clip anything that tries to bleed past the outline */
  min-height: 460px;             /* allow space for header + body + inverted-T footer */
  display: flex;
  flex-direction: column;
}
/* Focus + browse cards (fc-card / fc-card--preview) use border-radius:var(--radius-lg)=16px,
   not --card-radius=12px. The chip's top-left curve must follow the card's actual outer
   curve, so we override the universal calc with the radius-lg value (16 - stripe-width). */
.fc-card > .card__header,
.fc-card--preview > .card__header {
  top: 0 !important;
}
.fc-card > .card__header .card__logo,
.fc-card--preview > .card__header .card__logo {
  border-top-left-radius: calc(var(--radius-lg, 16px) - var(--card-stripe-width, 4px));
}
/* Same for the menu corner alignment in focus + preview */
.fc-card > .card__header-right .card__menu,
.fc-card > .card__header-right .card-options-btn,
.fc-card--preview > .card__header-right .card__menu,
.fc-card--preview > .card__header-right .card-options-btn {
  /* Move menu inset slightly so its circle sits on the rounded corner curve */
  margin-right: 4px;
}
.fc-card .fc-body,
.fc-card .fc-prompt,
.fc-card .fc-answer {
  /* Body content respects card padding — no bleed */
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
.fc-card .recall-actions {
  margin-top: 16px;
  position: relative;
  z-index: 5;
  flex-shrink: 0;
}
/* Miss-tag overlay fits inside card; no overflow past the rounded outline */
.fc-card.tag-open .miss-tag-overlay,
.fc-card .miss-tag-overlay {
  position: relative;
  z-index: 6;
  width: 100%;
  max-width: 100%;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  overflow: hidden;
}
.fc-card .miss-tag-overlay .miss-tag-grid {
  width: 100%;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
.fc-card .miss-tag-overlay .miss-tag-btn {
  flex: 1 1 0;
  min-width: 0;
  box-sizing: border-box;
}

/* ── Miss-tag: hide keybinding number hints from visible labels ── */
/* The 1/2/3 shortcut indicators (shift-to-reveal policy) must never
   show in button text. Completely removed from the visual label. */
.miss-tag-btn .miss-tag-shortcut {
  display: none !important;
}

/* ── Miss-tag: coral colour coding preserved in focus mode ── */
.fc-card .miss-tag-btn,
.miss-tag-overlay--focus .miss-tag-btn {
  color: var(--grade-missed) !important;
  border-color: var(--grade-missed) !important;
  background: color-mix(in srgb, var(--grade-missed) 10%, transparent) !important;
}
.fc-card .miss-tag-btn:hover,
.miss-tag-overlay--focus .miss-tag-btn:hover {
  background: color-mix(in srgb, var(--grade-missed) 18%, transparent) !important;
}

@media(prefers-reduced-motion:reduce){.fc-card{transition:none!important;}}
/* PERF-SKEL-001: LCP skeleton painted at FCP time inside loading screen */
.ls-skeleton-card{margin:10px 16px 0;background:var(--card-bg);border-radius:var(--radius-sm);padding-block:14px;padding-inline:16px}
.ls-skeleton-card .recall-prompt{color:var(--text-dim)}
@keyframes skel-shimmer{0%,100%{opacity:.55}50%{opacity:1}}
@media(prefers-reduced-motion:no-preference){.ls-skeleton-card .recall-prompt{animation:skel-shimmer 1.6s ease-in-out infinite}}
/* PERF-CLS-001: contain layout + reserve height so async renderToday() re-renders don't CLS */
#recallGrid,#saqList,#axiomsList,#pharmaGrid{contain:layout;min-height:160px}

/* ============================================================================
   content-explainer.css — "How your content is made" trust surface
   ----------------------------------------------------------------------------
   A native in-app overlay opened by openContentExplainer() from both the
   Settings panel ("Account & data") and the onboarding Welcome step.
   Explains the SAQ-model-answer + recall-card pipelines to CICM candidates,
   framed transparently (AI drafts → system verifies → clinician reviews).

   Tokens only — no hardcoded colour/size literals (stylelint-enforced).
   Card-type stripes carry identity; surfaces stay neutral (v9.7 rule).
   z-index sits above the onboarding wizard (no explicit z) and other shells.
   ============================================================================ */

/* ── Overlay scrim + scroll container ───────────────────────────────────── */
.ce-overlay {
  position: fixed;
  inset: 0;
  z-index: 10001;                 /* above onboarding (no z) + focus-mode done (10000) */
  background: var(--backdrop-preview, rgba(8, 8, 16, 0.82));
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding:
    max(20px, env(safe-area-inset-top, 0))
    max(16px, env(safe-area-inset-right, 0))
    max(40px, env(safe-area-inset-bottom, 0))
    max(16px, env(safe-area-inset-left, 0));
  animation: ceFade var(--duration-md, var(--duration-md)) var(--ease-out, ease);
}
.ce-overlay[hidden] { display: none; }

@keyframes ceFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes ceRise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .ce-overlay, .ce-dialog { animation: none; }
}

/* ── Dialog shell ───────────────────────────────────────────────────────── */
.ce-dialog {
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg, 16px);
  box-shadow: var(--shadow-lg, 0 10px 30px rgba(0, 0, 0, 0.12));
  overflow: hidden;
  animation: ceRise var(--duration-lg, var(--duration-lg)) var(--ease-out, ease);
}

/* ── Sticky header ──────────────────────────────────────────────────────── */
.ce-head {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--border);
}
.ce-head-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-sans);
  font-size: var(--font-size-sm, 12px);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.ce-head-label .ce-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
}

/* ── Body padding wrapper ───────────────────────────────────────────────── */
.ce-body { padding: 4px 20px 28px; }
@media (max-width: 540px) { .ce-body { padding: 4px 14px 24px; } }

/* ── Hero ───────────────────────────────────────────────────────────────── */
.ce-hero { padding: 26px 0 8px; }
.ce-hero-eyebrow {
  font-size: var(--font-size-xs, 11px);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 8px;
}
.ce-hero-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(26px, 6vw, 36px);
  line-height: 1.12;
  color: var(--text);
  margin: 0 0 12px;
  letter-spacing: -0.01em;
}
.ce-hero-sub {
  font-size: var(--font-size-xl, 16px);
  line-height: 1.5;
  color: var(--text-muted);
  margin: 0;
  max-width: 56ch;
}
.ce-hero-sub b { color: var(--text); font-weight: 600; }

/* ── Trust pills (Drafted → Verified → Reviewed) ────────────────────────── */
.ce-pills {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 8px;
  margin: 22px 0 6px;
}
.ce-pill {
  flex: 1 1 0;
  min-width: 150px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: var(--card-stripe-width, 4px) solid var(--ce-accent, var(--accent));
  border-radius: var(--radius, 12px);
}
.ce-pill[data-step="draft"]  { --ce-accent: var(--type-pharma); }
.ce-pill[data-step="verify"] { --ce-accent: var(--accent); }
.ce-pill[data-step="review"] { --ce-accent: var(--type-saq); }
.ce-pill-num {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--ce-accent, var(--accent));
  color: var(--surface);
  font-size: var(--font-size-xs, 11px);
  font-weight: 700;
}
.ce-pill-meta { min-width: 0; display: flex; flex-direction: column; }
.ce-pill-title {
  display: block;
  font-size: var(--font-size-md, 13px);
  font-weight: 650;
  color: var(--text);
}
.ce-pill-desc {
  display: block;
  font-size: var(--font-size-sm, 12px);
  color: var(--text-faint);
  line-height: 1.4;
  margin-top: 2px;
}

/* ── Generic section ────────────────────────────────────────────────────── */
.ce-section { padding: 26px 0 4px; }
.ce-section-eyebrow {
  font-size: var(--font-size-2xs, 10px);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 6px;
}
.ce-section-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(20px, 4vw, 24px);
  line-height: 1.2;
  color: var(--text);
  margin: 0 0 6px;
}
.ce-section-lead {
  font-size: var(--font-size-md, 13px);
  line-height: 1.55;
  color: var(--text-muted);
  margin: 0 0 14px;
  max-width: 60ch;
}

/* ── The spine: numbered, expandable stages ─────────────────────────────── */
.ce-spine { display: flex; flex-direction: column; gap: 8px; }
.ce-stage {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: var(--card-stripe-width, 4px) solid var(--ce-accent, var(--accent));
  border-radius: var(--radius, 12px);
  overflow: hidden;
  --ce-accent: var(--accent);
}
.ce-stage[data-tone="source"]  { --ce-accent: var(--honey); }
.ce-stage[data-tone="pack"]    { --ce-accent: var(--sky); }
.ce-stage[data-tone="draft"]   { --ce-accent: var(--type-pharma); }
.ce-stage[data-tone="verify"]  { --ce-accent: var(--accent); }
.ce-stage[data-tone="review"]  { --ce-accent: var(--type-saq); }
.ce-stage[data-tone="publish"] { --ce-accent: var(--type-recall); }

.ce-stage > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 14px;
  -webkit-tap-highlight-color: transparent;
}
.ce-stage > summary::-webkit-details-marker { display: none; }
.ce-stage > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.ce-stage-num {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 7px;
  background: var(--ce-accent);
  color: var(--surface);
  font-size: var(--font-size-sm, 12px);
  font-weight: 700;
}
.ce-stage-headings { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.ce-stage-title {
  display: block;
  font-size: var(--font-size-lg, 14px);
  font-weight: 650;
  color: var(--text);
}
.ce-stage-one {
  display: block;
  font-size: var(--font-size-sm, 12px);
  color: var(--text-faint);
  line-height: 1.4;
  margin-top: 1px;
}
.ce-stage-chev {
  flex: 0 0 auto;
  width: 18px; height: 18px;
  color: var(--text-faint);
  transition: transform var(--duration-sm, var(--duration-sm)) var(--ease-out, ease);
}
.ce-stage[open] .ce-stage-chev { transform: rotate(90deg); }
.ce-stage-detail {
  padding: 2px 16px 15px 52px;
  font-size: var(--font-size-md, 13px);
  line-height: 1.55;
  color: var(--text-muted);
}
.ce-stage-detail b { color: var(--text); font-weight: 600; }
.ce-stage-detail ul { margin: 6px 0 0; padding-left: 18px; }
.ce-stage-detail li { margin: 4px 0; }
@media (max-width: 540px) {
  .ce-stage-detail { padding-left: 16px; }
}

/* ── Two outputs, same spine ────────────────────────────────────────────── */
.ce-outputs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
@media (max-width: 600px) { .ce-outputs { grid-template-columns: 1fr; } }
.ce-output {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: var(--card-stripe-width, 4px) solid var(--ce-accent, var(--accent));
  border-radius: var(--radius, 12px);
  padding: 14px;
}
.ce-output[data-type="recall"] { --ce-accent: var(--type-recall); }
.ce-output[data-type="saq"]    { --ce-accent: var(--type-saq); }
.ce-output-kicker {
  display: inline-block;
  font-size: var(--font-size-2xs, 10px);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ce-accent);
  margin-bottom: 4px;
}
.ce-output-title {
  font-size: var(--font-size-lg, 14px);
  font-weight: 650;
  color: var(--text);
  margin-bottom: 6px;
}
.ce-output-desc {
  font-size: var(--font-size-sm, 12px);
  line-height: 1.5;
  color: var(--text-muted);
}
.ce-output-desc b { color: var(--text); font-weight: 600; }

/* ── Worked example: card ↔ source anchor ───────────────────────────────── */
.ce-example { display: flex; flex-direction: column; gap: 10px; }
@media (min-width: 660px) {
  .ce-example { flex-direction: row; align-items: stretch; }
  .ce-example > * { flex: 1 1 0; }
}
.ce-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: var(--card-stripe-width, 4px) solid var(--type-recall);
  border-radius: var(--radius, 12px);
  padding: 14px;
  display: flex;
  flex-direction: column;
}
.ce-card-type {
  align-self: flex-start;
  font-size: var(--font-size-2xs, 10px);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--type-recall);
  background: var(--sky-fill, var(--accent-soft));
  padding: 2px 7px;
  border-radius: var(--radius-pill, 999px);
  margin-bottom: 8px;
}
.ce-card-prompt {
  font-size: var(--font-size-lg, 14px);
  font-weight: 650;
  color: var(--text);
  line-height: 1.35;
  margin-bottom: 8px;
}
.ce-card-divider {
  height: 1px; background: var(--border);
  margin: 2px 0 8px;
}
.ce-card-answer {
  font-size: var(--font-size-md, 13px);
  line-height: 1.5;
  color: var(--text-muted);
}
.ce-card-answer b { color: var(--text); font-weight: 600; }
.ce-card-answer ul { margin: 4px 0 0; padding-left: 18px; }
.ce-card-answer li { margin: 3px 0; }

.ce-anchor {
  background: var(--surface-elevated);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius, 12px);
  padding: 14px;
  display: flex;
  flex-direction: column;
}
.ce-anchor-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--font-size-2xs, 10px);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 8px;
}
.ce-anchor-ref {
  font-family: var(--font-mono);
  font-size: var(--font-size-sm, 12px);
  color: var(--text-muted-strong);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-tiny, 4px);
  padding: 5px 8px;
  margin-bottom: 10px;
  align-self: flex-start;
}
.ce-anchor-quote {
  font-size: var(--font-size-md, 13px);
  line-height: 1.55;
  color: var(--text-muted);
  font-style: italic;
  position: relative;
  padding-left: 12px;
  border-left: 2px solid var(--accent-soft);
}
.ce-anchor-quote mark {
  background: var(--honey-fill, var(--accent-soft));
  color: var(--text);
  font-style: normal;
  font-weight: 600;
  border-radius: var(--radius-tiny, 4px);
  padding: 0 2px;
}
.ce-anchor-note {
  margin-top: 10px;
  font-size: var(--font-size-sm, 12px);
  line-height: 1.45;
  color: var(--text-faint);
}

/* ── Named sources panel ────────────────────────────────────────────────── */
.ce-sources {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 8px;
}
.ce-source {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 8px);
}
.ce-source-name {
  font-size: var(--font-size-md, 13px);
  font-weight: 600;
  color: var(--text);
}
.ce-source-meta {
  font-size: var(--font-size-xs, 11px);
  color: var(--text-faint);
}
.ce-sources-foot {
  margin-top: 10px;
  font-size: var(--font-size-sm, 12px);
  color: var(--text-faint);
  line-height: 1.5;
}

/* ── Trust-stat band ────────────────────────────────────────────────────── */
.ce-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}
.ce-stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius, 12px);
  padding: 16px 14px;
  text-align: center;
}
.ce-stat-num {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(24px, 5vw, 30px);
  line-height: 1;
  color: var(--accent);
  letter-spacing: -0.01em;
}
.ce-stat-label {
  margin-top: 6px;
  font-size: var(--font-size-sm, 12px);
  line-height: 1.35;
  color: var(--text-muted);
}

/* ── "What we will not do" honesty panel ────────────────────────────────── */
.ce-wont {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius, 12px);
  padding: 6px 16px;
}
.ce-wont-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 0;
  border-bottom: 1px solid var(--border);
}
.ce-wont-row:last-child { border-bottom: none; }
.ce-wont-mark {
  flex: 0 0 auto;
  width: 18px; height: 18px; margin-top: 1px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  font-size: var(--font-size-xs, 11px);
  font-weight: 700;
}
.ce-wont-mark[data-kind="no"]  { color: var(--grade-missed); background: var(--grade-missed-glow, transparent); }
.ce-wont-mark[data-kind="yes"] { color: var(--grade-honed);  background: var(--grade-honed-glow, transparent); }
.ce-wont-text {
  font-size: var(--font-size-md, 13px);
  line-height: 1.45;
  color: var(--text-muted);
}
.ce-wont-text b { color: var(--text); font-weight: 600; }

/* ── Footer / version stamp ─────────────────────────────────────────────── */
.ce-foot {
  margin-top: 26px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: var(--font-size-xs, 11px);
  color: var(--text-faint);
}
.ce-foot-cta { margin-top: 18px; display: flex; justify-content: center; }

/* ── Onboarding teaser link (lives inside the wizard Welcome step) ──────── */
.ce-teaser-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 14px;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  font: inherit;
  font-size: var(--font-size-sm, 12px);
  font-weight: 600;
  color: var(--accent);
  text-align: left;
  line-height: 1.4;
}
.ce-teaser-link:hover { color: var(--accent-pressed, var(--accent)); }
.ce-teaser-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-tiny, 4px); }
.ce-teaser-line {
  margin-top: 14px;
  padding: 10px 12px;
  background: var(--surface-elevated);
  border-radius: var(--radius-sm, 8px);
  font-size: var(--font-size-sm, 12px);
  line-height: 1.5;
  color: var(--text-muted);
}
.ce-teaser-line b { color: var(--text); font-weight: 600; }

/* ════════════════════════════════════════════════════════════════════════
   v2 — objective technical rewrite: inputs, flow diagram, check tables,
   limitations, provenance. Declarative/system-level; no marketing voice.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Objective summary callouts ─────────────────────────────────────────── */
.ce-summary {
  margin-top: 16px;
  padding: 13px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: var(--card-stripe-width, 4px) solid var(--accent);
  border-radius: var(--radius, 12px);
  font-size: var(--font-size-md, 13px);
  line-height: 1.6;
  color: var(--text-muted);
}
.ce-summary b { color: var(--text); font-weight: 600; }
.ce-summary + .ce-summary { margin-top: 8px; }

/* ── Mechanism / model badges ───────────────────────────────────────────── */
.ce-meta {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: var(--font-size-2xs, 10px);
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 2px 7px;
  border-radius: var(--radius-pill, 999px);
  border: 1px solid var(--border-strong);
  color: var(--text-muted-strong);
  background: var(--bg);
  white-space: nowrap;
}
.ce-meta[data-t="llm"]   { color: var(--type-pharma); border-color: color-mix(in srgb, var(--type-pharma) 40%, transparent); }
.ce-meta[data-t="det"]   { color: var(--accent);      border-color: color-mix(in srgb, var(--accent) 40%, transparent); }
.ce-meta[data-t="human"] { color: var(--type-saq);    border-color: color-mix(in srgb, var(--type-saq) 40%, transparent); }

/* ── Inputs inventory ───────────────────────────────────────────────────── */
.ce-io {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 8px;
}
.ce-io-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: var(--card-stripe-width, 4px) solid var(--honey);
  border-radius: var(--radius, 12px);
  padding: 12px 14px;
}
.ce-io-count {
  font-family: var(--font-display);
  font-size: var(--font-size-2xl, 17px);
  color: var(--text);
  line-height: 1;
}
.ce-io-name { font-size: var(--font-size-md, 13px); font-weight: 650; color: var(--text); margin-top: 3px; }
.ce-io-yield { font-size: var(--font-size-sm, 12px); color: var(--text-faint); line-height: 1.45; margin-top: 5px; }

/* ── Legend ─────────────────────────────────────────────────────────────── */
.ce-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 0 0 14px; }
.ce-legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: var(--font-size-sm, 12px); color: var(--text-muted); }
.ce-legend-sw { width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto; }

/* ── Pipeline flow diagram ──────────────────────────────────────────────── */
.ce-flow { display: flex; flex-direction: column; align-items: stretch; }
.ce-fan { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin-bottom: 2px; }
.ce-fan-chip {
  font-size: var(--font-size-xs, 11px);
  color: var(--text-muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill, 999px);
  padding: 4px 10px;
}
.ce-conn { align-self: center; width: 2px; height: 20px; background: var(--border-strong); position: relative; }
.ce-conn::after {
  content: ""; position: absolute; left: -4px; bottom: 0;
  border: 5px solid transparent; border-top-color: var(--border-strong);
}
.ce-conn[data-loop]::before {
  content: "↺ on failure → step 3";
  position: absolute; left: 12px; top: 0; white-space: nowrap;
  font-size: var(--font-size-2xs, 10px); color: var(--text-faint);
}

.ce-fnode {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: var(--card-stripe-width, 4px) solid var(--ce-accent, var(--accent));
  border-radius: var(--radius, 12px);
  overflow: hidden;
  --ce-accent: var(--accent);
}
.ce-fnode[data-kind="input"]   { --ce-accent: var(--honey); }
.ce-fnode[data-kind="process"] { --ce-accent: var(--type-pharma); }
.ce-fnode[data-kind="gate"]    { --ce-accent: var(--accent); }
.ce-fnode[data-kind="human"]   { --ce-accent: var(--type-saq); }
.ce-fnode[data-kind="output"]  { --ce-accent: var(--type-recall); }

.ce-fnode > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; padding: 12px 14px; -webkit-tap-highlight-color: transparent; }
.ce-fnode > summary::-webkit-details-marker { display: none; }
.ce-fnode > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ce-fnum {
  flex: 0 0 auto; min-width: 26px; height: 24px; padding: 0 6px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 7px; background: var(--ce-accent); color: var(--surface);
  font-size: var(--font-size-sm, 12px); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.ce-fhead { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ce-ftag { font-size: var(--font-size-2xs, 10px); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ce-accent); }
.ce-ftitle { font-size: var(--font-size-lg, 14px); font-weight: 650; color: var(--text); }
.ce-fmech { font-size: var(--font-size-sm, 12px); color: var(--text-faint); line-height: 1.4; margin-top: 1px; }
.ce-fright { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
.ce-fchev { width: 16px; height: 16px; color: var(--text-faint); transition: transform var(--duration-sm, var(--duration-sm)) var(--ease-out, ease); }
.ce-fnode[open] .ce-fchev { transform: rotate(90deg); }
.ce-fdetail { padding: 2px 16px 14px 50px; font-size: var(--font-size-md, 13px); line-height: 1.55; color: var(--text-muted); }
.ce-fdetail b { color: var(--text); font-weight: 600; }
.ce-fdetail ul { margin: 6px 0 0; padding-left: 18px; }
.ce-fdetail li { margin: 4px 0; }
@media (max-width: 540px) {
  .ce-fdetail { padding-left: 16px; }
  .ce-fright .ce-meta { display: none; }
}

/* gate pass/fail branch row */
.ce-branch { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 14px 12px 50px; }
@media (max-width: 540px) { .ce-branch { padding-left: 16px; } }
.ce-br {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--font-size-xs, 11px);
  padding: 3px 9px; border-radius: var(--radius-pill, 999px);
  border: 1px solid var(--border); color: var(--text-muted);
}
/* Semantics carried by the tinted border (UI ≥3:1) + the label; text stays AA-safe in both themes. */
.ce-br[data-r="pass"] { border-color: color-mix(in srgb, var(--grade-honed) 55%, var(--border)); }
.ce-br[data-r="fail"] { border-color: color-mix(in srgb, var(--grade-missed) 55%, var(--border)); }

.ce-flow-note {
  margin-top: 12px;
  font-size: var(--font-size-sm, 12px);
  line-height: 1.5;
  color: var(--text-faint);
}
.ce-flow-note b { color: var(--text-muted-strong); font-weight: 600; }

/* ── Verification check cards ───────────────────────────────────────────── */
.ce-checks { display: flex; flex-direction: column; gap: 8px; }
.ce-check { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius, 12px); padding: 12px 14px; }
.ce-check-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 5px; }
.ce-check-name { font-size: var(--font-size-md, 13px); font-weight: 650; color: var(--text); }
.ce-check-asserts { font-size: var(--font-size-sm, 12px); line-height: 1.5; color: var(--text-muted); }
.ce-check-gap { font-size: var(--font-size-sm, 12px); line-height: 1.5; color: var(--text-muted); margin-top: 4px; }
.ce-check-gap b { color: var(--text); font-weight: 700; }

/* ── Known limitations ──────────────────────────────────────────────────── */
.ce-limits { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius, 12px); padding: 4px 16px; }
.ce-limit {
  display: flex; gap: 10px; padding: 11px 0;
  border-bottom: 1px solid var(--border);
  font-size: var(--font-size-md, 13px); line-height: 1.5; color: var(--text-muted);
}
.ce-limit:last-child { border-bottom: none; }
.ce-limit::before { content: "—"; color: var(--text-faint); flex: 0 0 auto; }
.ce-limit b { color: var(--text); font-weight: 600; }

/* ── Provenance code block ──────────────────────────────────────────────── */
.ce-code {
  font-family: var(--font-mono);
  font-size: var(--font-size-sm, 12px);
  line-height: 1.65;
  color: var(--text-muted-strong);
  background: var(--surface-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 8px);
  padding: 12px 14px;
  overflow-x: auto;
  white-space: pre;
}
.ce-code .k { color: var(--type-pharma); }
.ce-code .c { color: var(--text-faint); }

/* ── Pipeline switcher (CSS-only radio tabs) ────────────────────────────── */
.ce-pipe-radio { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.ce-pipe-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.ce-pipe-tab {
  display: inline-block;
  font-size: var(--font-size-sm, 12px);
  font-weight: 600;
  color: var(--text-muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill, 999px);
  padding: 6px 14px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ce-pipe-tab:hover { border-color: var(--border-strong); }
#cepipe-recall:checked ~ .ce-pipe-tabs label[for="cepipe-recall"],
#cepipe-saq:checked ~ .ce-pipe-tabs label[for="cepipe-saq"] {
  background: var(--accent); color: var(--accent-on, var(--bg)); border-color: var(--accent);
}
#cepipe-recall:focus-visible ~ .ce-pipe-tabs label[for="cepipe-recall"],
#cepipe-saq:focus-visible ~ .ce-pipe-tabs label[for="cepipe-saq"] {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.ce-flow[data-pipe] { display: none; }
#cepipe-recall:checked ~ .ce-pipe-panels .ce-flow[data-pipe="recall"] { display: flex; }
#cepipe-saq:checked    ~ .ce-pipe-panels .ce-flow[data-pipe="saq"]    { display: flex; }

/* ── Verifier rule grid ─────────────────────────────────────────────────── */
.ce-rules { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 6px; }
.ce-rule {
  display: flex; align-items: baseline; gap: 9px;
  padding: 8px 11px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm, 8px);
}
.ce-rule-id {
  flex: 0 0 auto; min-width: 28px;
  font-family: var(--font-mono); font-size: var(--font-size-2xs, 10px); font-weight: 700;
  color: var(--accent); letter-spacing: 0.02em;
}
.ce-rule-text { flex: 1 1 auto; font-size: var(--font-size-sm, 12px); line-height: 1.4; color: var(--text-muted); }
.ce-rule-tag {
  flex: 0 0 auto; align-self: center;
  font-size: var(--font-size-2xs, 10px); font-weight: 600;
  letter-spacing: 0.03em; text-transform: uppercase; white-space: nowrap;
  color: var(--text-faint);
}
.ce-rule-tag[data-x="resynth"] { color: var(--text-muted-strong); }
.ce-soft { margin-top: 8px; }
.ce-soft > summary {
  list-style: none; cursor: pointer;
  font-size: var(--font-size-sm, 12px); font-weight: 600; color: var(--accent);
  padding: 4px 0;
}
.ce-soft > summary::-webkit-details-marker { display: none; }
.ce-soft-body { margin-top: 6px; }

/* Textbook Library overlay — renders inside #textbookRoot (reuses .curriculum-overlay
   chrome for backdrop/sheet/grab/card). Tokens only; cover colours arrive as --bk/--bk2
   inline and are lightness-clamped via relative oklch so any cover hue stays legible. */

body.textbooks-overlay-open { overflow: hidden; }

.tl-hd { display: flex; align-items: center; gap: 10px; padding: 4px 18px 12px; border-bottom: 1px solid var(--border); }
.tl-title { font-size: var(--font-size-lg, 16px); margin: 0; flex: 1; display: flex; align-items: center; gap: 8px; font-weight: 600; }
.tl-title-ico { width: 18px; height: 18px; color: var(--accent); display: flex; }
.tl-title-ico svg { width: 18px; height: 18px; }
.tl-seg { display: inline-flex; background: var(--surface-elevated); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 2px; }
.tl-seg-btn { padding: 6px 13px; border-radius: var(--radius-pill); font-size: var(--font-size-md, 13px); color: var(--text-muted); border: 0; background: transparent; cursor: pointer; font-family: inherit; font-weight: 500; }
.tl-seg-btn.on { background: var(--accent); color: var(--accent-on, #fff); font-weight: 600; }
.tl-close { width: 32px; height: 32px; min-width: 32px; border: none; background: none; color: var(--text-muted); cursor: pointer; border-radius: var(--btn-radius); display: flex; align-items: center; justify-content: center; }
.tl-close svg { width: 18px; height: 18px; }
.tl-close:hover { background: var(--surface); color: var(--text); }
@media (pointer: coarse) { .tl-close { width: 44px; height: 44px; } }

.tl-search { padding: 10px 18px 12px; border-bottom: 1px solid var(--border); }
.tl-search-wrap { display: flex; align-items: center; gap: 8px; border: 1px solid var(--border); background: var(--surface-elevated); border-radius: var(--radius-pill); padding: 8px 13px; }
.tl-search-wrap:focus-within { border-color: var(--accent); }
.tl-search-ico { width: 16px; height: 16px; color: var(--text-faint); flex: 0 0 16px; display: flex; }
.tl-search-ico svg { width: 16px; height: 16px; }
.tl-search input { flex: 1; border: 0; background: transparent; color: var(--text); font: inherit; font-size: var(--font-size-md, 13px); outline: none; }

.tl-lock-banner { display: flex; align-items: center; gap: 8px; margin: 12px 18px 0; padding: 9px 13px; background: var(--honey-fill); border: 1px solid color-mix(in srgb, var(--honey-deep) 30%, transparent); border-radius: var(--radius); font-size: var(--font-size-sm, 12px); color: var(--honey-deep); }
.tl-lock-ico { flex: 0 0 15px; width: 15px; height: 15px; display: flex; }
.tl-lock-ico svg { width: 15px; height: 15px; }

.tl-content { padding-bottom: 24px; }

/* sort */
.tl-sort { display: flex; align-items: center; gap: 6px; padding: 13px 18px 2px; flex-wrap: wrap; }
.tl-sort-lbl { font-size: var(--font-size-2xs, 10px); text-transform: uppercase; letter-spacing: .05em; color: var(--text-faint); margin-right: 2px; }
.tl-sort-chip { font-size: var(--font-size-sm, 12px); padding: 5px 11px; border-radius: var(--radius-pill); border: 1px solid var(--border); background: var(--surface-elevated); color: var(--text-muted); cursor: pointer; font-family: inherit; min-height: 30px; }
.tl-sort-chip.on { background: var(--accent-soft); color: var(--accent); border-color: transparent; font-weight: 600; }

/* shelf */
.tl-shelf { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; padding: 16px 18px; }
.tl-book { display: flex; gap: 0; background: var(--surface-elevated); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; cursor: pointer; text-align: left; min-height: 104px; font-family: inherit; padding: 0;
  transition: background var(--duration-sm, var(--duration-sm)) var(--ease-out), color var(--duration-sm, var(--duration-sm)) var(--ease-out), border-color var(--duration-sm, var(--duration-sm)) var(--ease-out), box-shadow var(--duration-sm, var(--duration-sm)) var(--ease-out), transform var(--duration-sm, var(--duration-sm)) var(--ease-out), opacity var(--duration-sm, var(--duration-sm)) var(--ease-out); }
.tl-book:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.tl-spine { flex: 0 0 14px; background: var(--bk, var(--border-strong)); }
.tl-book-body { flex: 1; padding: 11px 12px; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.tl-book-title { font-size: var(--font-size-lg, 14px); font-weight: 500; line-height: 1.25; color: var(--text); }
.tl-book-subj { font-size: var(--font-size-xs, 11px); color: var(--text-faint); line-height: 1.3; flex: 1; }
.tl-book-meta { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 2px; }
.tl-chip-cited { font-size: var(--font-size-sm, 11.5px); font-weight: 700; color: var(--text-muted); }
.tl-chcount { font-size: var(--font-size-xs, 11px); color: var(--text-faint); }
.tl-chip-az { font-size: var(--font-size-2xs, 10px); font-weight: 700; letter-spacing: .02em; padding: 2px 7px; border-radius: var(--radius-pill); background: var(--honey-fill); color: var(--honey-deep); }
.tl-lockico { display: inline-flex; color: var(--text-faint); }
.tl-lockico svg { width: 12px; height: 12px; }

/* breadcrumb + detail title */
.tl-bc { display: flex; align-items: center; gap: 5px; padding: 12px 18px 2px; font-size: var(--font-size-xs, 11px); color: var(--text-muted); }
.tl-crumb { color: var(--accent); cursor: pointer; }
.tl-bc-sep { width: 13px; height: 13px; display: flex; color: var(--text-faint); }
.tl-bc-sep svg { width: 13px; height: 13px; }
.tl-detail-title { display: flex; align-items: center; gap: 10px; padding: 4px 18px 12px; border-bottom: 1px solid var(--border); }
.tl-detail-spine { width: 8px; height: 34px; border-radius: 3px; flex: 0 0 8px; }
.tl-detail-title h3 { margin: 0; font-size: var(--font-size-lg, 16px); font-weight: 600; }
.tl-detail-sub { font-size: var(--font-size-xs, 11.5px); color: var(--text-muted); }

/* chapter rows / result rows */
.tl-chrow { display: flex; align-items: center; gap: 11px; padding: 10px 18px; border: none; border-bottom: .5px solid var(--border); color: var(--text); background: transparent; width: 100%; text-align: left; font: inherit; cursor: pointer; min-height: 44px; }
.tl-chrow:hover { background: color-mix(in srgb, var(--accent) 4%, var(--surface-elevated)); }
.tl-chrow.is-locked { cursor: not-allowed; opacity: .6; }
.tl-chrow.is-locked:hover { background: transparent; }
.tl-chrow-num { flex: 0 0 34px; font-size: var(--font-size-xs, 11px); color: var(--text-faint); font-variant-numeric: tabular-nums; }
.tl-chrow-ico { flex: 0 0 16px; color: var(--text-faint); display: flex; }
.tl-chrow-ico svg { width: 16px; height: 16px; }
.tl-chrow-title { flex: 1; font-size: var(--font-size-md, 13px); }
.tl-chrow-cite { font-size: var(--font-size-xs, 11px); font-weight: 600; color: var(--text-muted); white-space: nowrap; flex: 0 0 auto; }
.tl-chrow-pg { font-size: var(--font-size-xs, 11px); color: var(--text-faint); white-space: nowrap; }
.tl-chrow-arr { font-size: 12px; color: var(--border-strong); flex: 0 0 auto; }
.tl-chrow-lk { display: inline-flex; color: var(--text-faint); }
.tl-chrow-lk svg { width: 14px; height: 14px; }

.tl-res-group { padding: 12px 18px 3px; font-size: var(--font-size-2xs, 10px); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--text-faint); }
.tl-empty { padding: 30px 18px; text-align: center; color: var(--text-faint); font-size: var(--font-size-md, 12.5px); }
.tl-note { font-size: var(--font-size-xs, 11px); color: var(--text-faint); padding: 12px 18px; margin: 0; line-height: 1.45; }

/* by topic */
.tl-sec { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; margin: 0 18px 8px; }
.tl-sec:first-of-type { margin-top: 14px; }
.tl-sec-hd { display: flex; align-items: center; gap: 10px; padding: 11px 13px; cursor: pointer; background: var(--surface-elevated); }
.tl-sec-dot { width: 10px; height: 10px; border-radius: 3px; background: var(--sx, var(--border-strong)); flex: 0 0 10px; }
.tl-sec-nm { flex: 1; font-size: var(--font-size-md, 13.5px); font-weight: 600; }
.tl-sec-cnt { font-size: var(--font-size-xs, 11px); color: var(--text-faint); }
.tl-sec-body { display: none; padding: 4px 13px 10px 33px; }
.tl-sec.open .tl-sec-body { display: block; }
.tl-ch-hd { font-size: var(--font-size-2xs, 10.5px); font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); padding: 9px 0 2px; }
.tl-tprow { padding: 7px 0 7px 12px; border-bottom: .5px solid var(--border); font-size: var(--font-size-md, 12.5px); }
.tl-tprow:last-child { border-bottom: none; }
.tl-tc { color: var(--text); font-weight: 500; }
.tl-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
.tl-tbk { display: inline-flex; align-items: center; gap: 5px; font-size: var(--font-size-xs, 11px); padding: 3px 9px; border-radius: var(--radius-pill); cursor: pointer; font-family: inherit;
  background: color-mix(in srgb, var(--bk2) 12%, var(--surface)); border: 1px solid color-mix(in srgb, var(--bk2) 28%, transparent);
  color: oklch(from var(--bk2) clamp(.30, l, .52) c h); }
.tl-tbk-ico { width: 11px; height: 11px; display: flex; }
.tl-tbk-ico svg { width: 11px; height: 11px; }

/* cover-colour chips: clamp text lightness so any real cover hue stays legible */
html.dark .tl-tbk { color: oklch(from var(--bk2) clamp(.66, l, .86) c h); }

/* knowledge-map.css
 * Styles for the #/map knowledge-graph overlay.
 *
 * Two layers:
 *   1. OVERLAY CHROME (unscoped) — the .map-overlay-sheet + body.map-overlay-open
 *      z-index management for nested modals (refs/flag/preview) opened from inside
 *      the map. Mirrors .curriculum-overlay / .textbooks-overlay.
 *   2. MAP INTERNALS (scoped under #mapRoot) — every rule from the former
 *      knowledge-map-view.html \3c style> block, mechanically prefixed with #mapRoot
 *      so it cannot leak into the host app (the map is now rendered in-document by
 *      pwa/knowledge-map.js, not an isolated iframe). :root→#mapRoot, html/body→
 *      #mapRoot, *→#mapRoot *. @keyframes stay global.
 */

/* #mapRoot fills the overlay sheet (replaces the old iframe's inline flex style). */
#mapRoot { flex: 1 1 auto; min-height: 0; width: 100%; }

.map-overlay-sheet {
  /* Full-bleed sheet — almost 100% viewport height (same as textbooks/curriculum 92dvh). */
  height: 92dvh;
  /* Override the card padding added by .curriculum-overlay-card — the iframe
     fills its own content area, so no inner padding needed at the sheet level. */
  overflow: hidden;
}

/* FIX 4: .map-overlay-header and .map-overlay-close removed — × button is gone.
   The grab handle (curriculum-overlay-grab) is the sole chrome between backdrop and iframe. */

/* Body-open scroll lock (mirrors textbooks-overlay-open). */
body.map-overlay-open {
  overflow: hidden;
}

/* Ensure elements that need to clear the map overlay (z-1000) sit above it
   when triggered from inside — same pattern as curriculum-overlay-open. */
body.map-overlay-open .ns-modal,
body.map-overlay-open .sheet-backdrop,
body.map-overlay-open .preview-overlay,
body.map-overlay-open .search-palette,
body.map-overlay-open .settings-backdrop,
body.map-overlay-open #curriculumPickerSheet,
body.map-overlay-open .overlay,
body.map-overlay-open #flagSheetOverlay,
body.map-overlay-open .refs-sheet,
body.map-overlay-open .refs-sheet-backdrop,
body.map-overlay-open .miss-tag-overlay,
body.map-overlay-open .focus-overlay {
  z-index: 1100;
}
body.map-overlay-open .lib-select-bar { z-index: 1110; }

/* ═══════════════════════════════════════════════════════════════════════
   MAP INTERNALS — scoped under #mapRoot (ported from knowledge-map-view.html)
   ═══════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════
   DESIGN TOKENS — moved to pwa/css/tokens.css (WS11, 2026-06-18). The #mapRoot
   dark-canvas palette + --scope-toggle-active-text / --km-hy-active now live in
   tokens.css (hex is permitted there); cascade unchanged (id specificity wins).
═══════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════
   RESET + BASE
═══════════════════════════════════════════════ */
/* The map's universal reset is scoped to EXCLUDE #km-ribbon-host and its subtree
   — that is where the native app ribbon (window.iatroCurriculum.renderNodeCards)
   is rendered into the detail panel. Its component CSS (ribbon.css/card.css) uses
   class selectors (0,1,0), which this reset's #mapRoot * (1,0,0) would otherwise
   clobber (zeroing card padding/margins). The :where() keeps the exclusion at the
   same (1,0,0) specificity so the rest of the map's reset is unchanged; excluded
   ribbon elements still get box-sizing:border-box from the app's global *{} rule. */
#mapRoot *:not(:where(#km-ribbon-host, #km-ribbon-host *)),
#mapRoot *:not(:where(#km-ribbon-host, #km-ribbon-host *))::before,
#mapRoot *:not(:where(#km-ribbon-host, #km-ribbon-host *))::after { box-sizing: border-box; margin: 0; padding: 0; }
/* FIX 1+2: iframe-aware sizing. html/body fill the iframe viewport exactly (100dvh / 100dvh).
   overflow:hidden on body keeps the document from ever being wider/taller than the iframe;
   all scrolling happens inside #canvas. */
#mapRoot { height: 100%; overflow: hidden; }
#mapRoot {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
  /* FIX 2: disable text selection across the whole map; prevents drag-to-select
     fighting press-and-hold gestures. Inputs/textareas override this below. */
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none; /* suppress iOS long-press callout */
}
/* Re-enable selection inside any search/text input that might be added */
#mapRoot input,
#mapRoot textarea { user-select: text; -webkit-user-select: text; }
#mapRoot button { font: inherit; cursor: pointer; border: none; background: none; color: inherit; }
#mapRoot a { color: inherit; text-decoration: none; }

/* ═══════════════════════════════════════════════
   LAYOUT SHELL
═══════════════════════════════════════════════ */
/* FIX 1: #app fills the iframe height exactly. flex column means #topbar takes
   its natural height and #main takes the remainder (flex:1 + min-height:0). */
#mapRoot { display: flex; flex-direction: column; height: 100%; min-height: 0; }

/* top bar */
#mapRoot #topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
  height: 52px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  gap: 12px;
  z-index: 30;
}
/* FIX 3: legend toggle button lives in topbar-left, before the title */
#mapRoot #legend-topbar-btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding-block: 5px;
  padding-inline: 10px; height: 30px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border2);
  background: transparent;
  color: var(--text-dim);
  font-size: 11px; font-weight: 600; letter-spacing: 0.04em;
  cursor: pointer; flex-shrink: 0;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
#mapRoot #legend-topbar-btn:hover { background: var(--surface2); color: var(--text-muted); border-color: var(--text-dim); }
#mapRoot #legend-topbar-btn.legend-open { background: var(--surface2); color: var(--text); border-color: var(--frontier-ring); }
/* Persistent study-scope toggle — switch between browse and select-scope modes. */
#mapRoot #scope-toggle-btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding-block: 5px;
  padding-inline: 10px; height: 30px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border2);
  background: transparent;
  color: var(--text-dim);
  font-size: 11px; font-weight: 600; letter-spacing: 0.04em;
  cursor: pointer; flex-shrink: 0;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
#mapRoot #scope-toggle-btn:hover { background: var(--surface2); color: var(--text-muted); border-color: var(--text-dim); }
#mapRoot #scope-toggle-btn[aria-pressed="true"] { background: rgba(56,189,248,0.14); color: var(--scope-toggle-active-text); border-color: var(--frontier-ring); }
#mapRoot #scope-toggle-btn:focus-visible { outline: 2px solid var(--frontier-ring); outline-offset: 2px; }
#mapRoot #topbar-left { display: flex; align-items: center; gap: 12px; min-width: 0; }
#mapRoot #topbar-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
#mapRoot #topbar-title { font-size: 15px; font-weight: 600; color: var(--text); white-space: nowrap; }
/* BUG 9: close button — clear, always-visible dismiss inside the iframe. */
#mapRoot #map-close-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; flex-shrink: 0;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border2);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
#mapRoot #map-close-btn:hover { background: var(--surface2); color: var(--text); border-color: var(--text-dim); }
#mapRoot #map-close-btn:focus-visible { outline: 2px solid var(--frontier-ring); outline-offset: 2px; }
#mapRoot #breadcrumb {
  display: flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--text-muted);
}
#mapRoot #breadcrumb .sep { color: var(--text-dim); }
#mapRoot #breadcrumb .crumb-active { color: var(--text); font-weight: 500; }
#mapRoot #breadcrumb .crumb-link { cursor: pointer; }
#mapRoot #breadcrumb .crumb-link:hover { color: var(--frontier-ring); }
#mapRoot #coverage-badge {
  display: flex; align-items: center; gap: 6px;
  padding-block: 4px;
  padding-inline: 10px;
  background: var(--surface2); border: 1px solid var(--border);
  border-radius: var(--radius-full);
  font-size: 11px; color: var(--text-muted);
  white-space: nowrap; flex-shrink: 0;
}
#mapRoot #coverage-badge .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent-c); flex-shrink: 0; }

/* FIX 1: #main takes remaining height after topbar. min-height:0 is critical for
   flex children — without it, a flex child refuses to shrink below its content height,
   so #canvas would never get a bounded height and scrollbars would never appear. */
#mapRoot #main { display: flex; flex: 1; min-height: 0; overflow: hidden; }

/* FIX 1: #canvas is the primary scroll container. min-height:0 ensures it respects
   the bounded height from #main. overscroll-behavior:contain stops scroll chaining
   so dragging the map never rubber-bands or scrolls the host PWA underneath. */
#mapRoot #canvas {
  flex: 1; min-height: 0;
  overflow-y: auto; overflow-x: visible;
  padding: 0; position: relative; scroll-behavior: smooth;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* detail panel */
#mapRoot #detail-panel {
  width: var(--detail-w);
  background: var(--surface);
  border-left: 1px solid var(--border);
  display: flex; flex-direction: column;
  flex-shrink: 0; overflow-y: auto;
  transition: transform 0.25s cubic-bezier(0.4,0,0.2,1);
  z-index: 20;
}
#mapRoot #detail-panel.hidden {
  transform: translateX(100%); width: 0;
  border-left: none; overflow: hidden;
}

/* ═══════════════════════════════════════════════
   OVERVIEW — SPINE
═══════════════════════════════════════════════ */
#mapRoot #overview { max-width: var(--spine-max); margin: 0 auto; padding-top: 32px; padding-inline: 24px; padding-bottom: 80px; }
#mapRoot #overview-header { margin-bottom: 32px; }
#mapRoot #overview-header h2 { font-size: 20px; font-weight: 700; margin-bottom: 4px; }
#mapRoot #overview-header p { font-size: 13px; color: var(--text-muted); }

#mapRoot .spine { position: relative; display: flex; flex-direction: column; gap: 0; }
#mapRoot .spine::before {
  content: ''; position: absolute; left: 28px; top: 20px; bottom: 20px;
  width: 2px; background: linear-gradient(to bottom, var(--border2) 0%, var(--border) 100%); z-index: 0;
}

#mapRoot .station { position: relative; display: flex; align-items: flex-start; gap: 16px; padding: 12px 0; z-index: 1; }
#mapRoot .station-dot { flex-shrink: 0; width: 58px; display: flex; flex-direction: column; align-items: center; gap: 4px; }
#mapRoot .station-circle {
  width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700;
  border: none; background: var(--surface2); color: var(--text-muted);
  position: relative; z-index: 1; transition: all 0.15s;
}
#mapRoot .station-circle::before {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: var(--station-ring-bg, var(--border2));
  z-index: -1;
}
#mapRoot .station-circle::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--surface2);
  z-index: -1;
}
#mapRoot .station.unmapped .station-circle::before { background: var(--border); }
#mapRoot .station.mapped .station-circle { background: var(--surface3); color: var(--text); }
#mapRoot .station[data-section="C"] .station-circle { color: var(--accent-c); background: rgba(56,189,248,0.08); }
#mapRoot .station[data-section="D"] .station-circle { color: var(--accent-d); background: rgba(129,140,248,0.08); }

#mapRoot .station-body {
  flex: 1; background: var(--surface2);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  padding-block: 12px;
  padding-inline: 14px; transition: all 0.15s; min-width: 0; margin-top: 6px;
}
#mapRoot .station.mapped .station-body { border-color: var(--border2); }
#mapRoot .station[data-section="C"] .station-body { border-color: rgba(56,189,248,0.25); }
#mapRoot .station[data-section="D"] .station-body { border-color: rgba(129,140,248,0.25); }
#mapRoot .station.mapped .station-body:hover {
  border-color: var(--frontier-ring); background: var(--surface3); cursor: pointer; transform: translateX(2px);
}
#mapRoot .station-name { font-size: 14px; font-weight: 600; color: var(--text); margin-bottom: 6px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
#mapRoot .station.unmapped .station-name { color: var(--text-dim); }
#mapRoot .station-name .tag { font-size: 10px; font-weight: 500; padding-block: 2px; padding-inline: 6px; border-radius: var(--radius-full); letter-spacing: 0.04em; }
#mapRoot .tag-mapped { background: rgba(56,189,248,0.12); color: var(--accent-c); border: 1px solid rgba(56,189,248,0.3); }
#mapRoot .tag-mapped-d { background: rgba(129,140,248,0.12); color: var(--accent-d); border: 1px solid rgba(129,140,248,0.3); }
#mapRoot .tag-soon { background: var(--surface3); color: var(--text-dim); border: 1px solid var(--border); }
#mapRoot .station-meta { font-size: 12px; color: var(--text-muted); display: flex; align-items: center; gap: 10px; margin-bottom: 8px; flex-wrap: wrap; }
#mapRoot .station.unmapped .station-meta { color: var(--text-dim); }
#mapRoot .meta-sep { color: var(--border2); }
#mapRoot .mastery-bar-wrap { margin-top: 6px; }
#mapRoot .mastery-bar-label { display: flex; justify-content: space-between; font-size: 11px; color: var(--text-dim); margin-bottom: 4px; }
#mapRoot .mastery-bar-track { height: 5px; background: var(--surface3); border-radius: var(--radius-full); overflow: hidden; display: flex; gap: 1px; }
#mapRoot .mastery-bar-seg { height: 100%; border-radius: var(--radius-full); transition: width 0.4s ease; }
#mapRoot .station.unmapped .mastery-bar-track { opacity: 0.35; }

/* ═══════════════════════════════════════════════
   SECTION DETAIL VIEW
═══════════════════════════════════════════════ */
#mapRoot #section-detail { display: none; }
#mapRoot #section-detail.active { display: block; }
#mapRoot #overview.hidden { display: none; }

#mapRoot .section-detail-inner { max-width: 960px; margin: 0 auto; padding-top: 24px; padding-inline: 24px; padding-bottom: 80px; }

#mapRoot .detail-header { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; flex-wrap: wrap; }
#mapRoot .back-btn {
  display: flex; align-items: center; gap: 6px;
  padding-block: 6px;
  padding-inline: 12px; background: var(--surface2);
  border: 1px solid var(--border2); border-radius: var(--radius-sm);
  font-size: 13px; color: var(--text-muted); transition: all 0.12s;
}
#mapRoot .back-btn:hover { border-color: var(--frontier-ring); color: var(--frontier-ring); }
#mapRoot .detail-section-name { font-size: 20px; font-weight: 700; }
#mapRoot .detail-section-sub { font-size: 13px; color: var(--text-muted); margin-top: 2px; }

/* ── UNIFIED MAP CHIP ROW ── */
#mapRoot .map-chips-row {
  display: flex; align-items: center; gap: 6px;
  margin-bottom: 16px; flex-wrap: nowrap;
  overflow: visible;
}

/* Shared chip style — all header toggles unified */
#mapRoot .map-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding-block: 6px;
  padding-inline: 14px;
  border-radius: var(--radius-sm);
  font-size: 12px; font-weight: 600;
  border: 1px solid var(--border2);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.12s;
  white-space: nowrap;
}
#mapRoot .map-chip:hover:not(.active) { border-color: var(--text-muted); color: var(--text); }

/* List chip active state */
#mapRoot #list-toggle.active {
  background: var(--surface3);
  border-color: var(--frontier-ring);
  color: var(--frontier-ring);
}
/* Yield chip active state */
#mapRoot #hy-toggle.active {
  background: rgba(239,68,68,0.1);
  border-color: rgba(239,68,68,0.4);
  color: var(--km-hy-active);
}
/* Integration chip active state */
#mapRoot #integration-toggle.active {
  background: var(--cool-cross-bg);
  border-color: var(--cool-cross-border);
  color: var(--cool-cross);
}
/* Cross-Links chip active state */
#mapRoot #crosslinks-toggle.active {
  background: var(--cool-cross-bg);
  border-color: var(--cool-cross-border);
  color: var(--cool-cross);
}

/* Drill Frontier chip — pushed to far right, sky accent */
#mapRoot #drill-frontier-btn {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 6px;
  padding-block: 6px;
  padding-inline: 14px;
  background: rgba(56,189,248,0.08);
  border: 1px solid rgba(56,189,248,0.3);
  border-radius: var(--radius-sm);
  font-size: 12px; font-weight: 600;
  color: var(--frontier-ring);
  cursor: pointer;
  transition: all 0.12s;
  white-space: nowrap;
}
#mapRoot #drill-frontier-btn:hover { background: rgba(56,189,248,0.18); border-color: var(--frontier-ring); }

/* Keep old class names in case referenced elsewhere, but use new sizing */
#mapRoot .section-actions-row { display: flex; align-items: center; gap: 6px; margin-bottom: 16px; flex-wrap: wrap; }
#mapRoot .view-toggle-row { display: flex; align-items: center; gap: 6px; margin-bottom: 16px; flex-wrap: wrap; }
#mapRoot .view-toggle-label { display: none; } /* removed from design */
#mapRoot .toggle-btn {
  padding-block: 6px;
  padding-inline: 14px; border-radius: var(--radius-sm);
  font-size: 12px; font-weight: 500;
  border: 1px solid var(--border2); background: transparent; color: var(--text-muted);
  transition: all 0.12s;
}
#mapRoot .toggle-btn.active { background: var(--surface3); border-color: var(--frontier-ring); color: var(--frontier-ring); }
#mapRoot .toggle-btn:hover:not(.active) { border-color: var(--text-muted); color: var(--text); }

/* Legacy individual button classes — kept for hy/integration id-based active styles above */
#mapRoot .hy-toggle-btn { padding-block: 6px; padding-inline: 14px; border-radius: var(--radius-sm); font-size: 12px; font-weight: 600; border: 1px solid var(--border2); background: transparent; color: var(--text-muted); transition: all 0.12s; display: inline-flex; align-items: center; gap: 5px; }
#mapRoot .integration-toggle-btn { padding-block: 6px; padding-inline: 14px; border-radius: var(--radius-sm); font-size: 12px; font-weight: 600; border: 1px solid var(--border2); background: transparent; color: var(--text-muted); transition: all 0.12s; display: inline-flex; align-items: center; gap: 5px; }
#mapRoot .drill-frontier-btn { } /* overridden by #drill-frontier-btn above */

/* cross-edge toggle — hidden; replaced by #crosslinks-toggle chip */
#mapRoot .cross-toggle-row { display: none; }
#mapRoot .cross-toggle-label { display: none; }
#mapRoot .cross-toggle-sep { display: none; }

/* path highlight controls */
#mapRoot .path-controls { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
#mapRoot .path-info { font-size: 12px; color: var(--text-muted); padding-block: 5px; padding-inline: 10px; background: rgba(56,189,248,0.08); border: 1px solid rgba(56,189,248,0.2); border-radius: var(--radius-sm); }
#mapRoot .clear-path-btn { padding-block: 5px; padding-inline: 12px; background: var(--surface2); border: 1px solid var(--border2); border-radius: var(--radius-sm); font-size: 12px; color: var(--text-muted); transition: all 0.12s; }
#mapRoot .clear-path-btn:hover { border-color: var(--text-muted); color: var(--text); }

/* ═══════════════════════════════════════════════
   NODE CARDS — 3-STATE MASTERY BORDER
   State is shown via border colour/style, not a 5-segment conic ring.
   Strong    = 3px solid var(--mastery-strong) with glow
   Developing= 3px solid var(--mastery-developing)
   Needs work= 3px solid var(--mastery-needs-work) faint
   No cards  = 2px dashed var(--mastery-no-cards) transparent fill
═══════════════════════════════════════════════ */
#mapRoot .node-card {
  position: relative;
  padding-block: 9px;
  padding-inline: 12px;
  border-radius: var(--radius-md);
  background: var(--surface2);
  cursor: pointer;
  transition: transform 0.15s, opacity 0.15s, border-color 0.15s;
  min-width: 140px;
  max-width: 240px;
  flex: 1 1 160px;
  border: 3px solid var(--mastery-needs-work);
}
#mapRoot .node-card.mastery-strong       { border-color: var(--mastery-strong); box-shadow: 0 0 0 1px rgba(159,114,248,0.25); }
#mapRoot .node-card.mastery-developing   { border-color: var(--mastery-developing); }
#mapRoot .node-card.mastery-needs-work   { border-color: var(--mastery-needs-work); }
#mapRoot .node-card.mastery-not-started  { border-color: var(--mastery-not-started); }
#mapRoot .node-card.no-cards {
  border: 2px dashed var(--mastery-no-cards);
  background: var(--surface2);
  box-shadow: none;
}
#mapRoot .node-card:hover { transform: translateY(-1px); }
#mapRoot .node-card.dimmed { opacity: 0.18; pointer-events: none; }
#mapRoot .node-card.highlighted { opacity: 1 !important; }
#mapRoot .node-card.frontier {
  filter: drop-shadow(0 0 8px rgba(56,189,248,0.55));
  border-color: var(--frontier-ring) !important;
  box-shadow: 0 0 0 2px rgba(56,189,248,0.3);
}

/* ── HIGH-YIELD overlay — FILL HEATMAP tint + small corner badge ── */
#mapRoot .hy-badge {
  display: none;
  position: absolute;
  top: 4px; right: 4px;
  width: 7px; height: 7px;
  border-radius: 50%;
  border: 1.5px solid var(--bg);
  z-index: 2;
}
/* When hy-active: tint the node FILL as heatmap (distinct from mastery border ring) */
#mapRoot .hy-active .node-card.hy-high { background: var(--hy-high-fill) !important; }
#mapRoot .hy-active .node-card.hy-med  { background: var(--hy-med-fill)  !important; }
#mapRoot .hy-active .node-card.hy-low  { background: var(--hy-low-fill)  !important; }
#mapRoot .hy-active .node-card.hy-none { background: var(--surface2); }
/* Small corner indicator badge */
#mapRoot .hy-active .node-card.hy-high .hy-badge { display: block; background: var(--hy-high-color); }
#mapRoot .hy-active .node-card.hy-med  .hy-badge { display: block; background: var(--hy-med-color); }
#mapRoot .hy-active .node-card.hy-low  .hy-badge { display: block; background: var(--hy-low-color); }

#mapRoot .node-card-code { font-size: 10px; font-weight: 700; color: var(--text-dim); letter-spacing: 0.06em; margin-bottom: 3px; }
#mapRoot .node-card-name { font-size: 12px; line-height: 1.35; color: var(--text); }
#mapRoot .node-card-count { font-size: 10px; color: var(--text-dim); margin-top: 4px; }
/* "What's next" per-node due/new badges (live FSRS, from _coverageByCode). */
#mapRoot .node-due-badge { display: inline-block; font-size: 9.5px; font-weight: 600; padding-block: 1px; padding-inline: 6px; border-radius: var(--radius-full); margin-left: 5px; vertical-align: 1px; }
#mapRoot .node-due-badge.due  { background: rgba(240,90,80,0.16);  color: var(--mastery-needs-work); }
#mapRoot .node-due-badge.newc { background: rgba(56,189,248,0.15); color: var(--frontier-ring); }
#mapRoot .ov-list-due { font-size: 10px; font-weight: 600; color: var(--mastery-needs-work); margin-left: 8px; }
#mapRoot .ov-list-new { font-size: 10px; font-weight: 600; color: var(--frontier-ring); margin-left: 8px; }
#mapRoot #overview-due-summary { font-size: 12px; color: var(--text-muted); margin-top: 6px; }
#mapRoot #overview-due-summary b { color: var(--mastery-needs-work); font-weight: 600; }

/* cross-stub indicator */
#mapRoot .node-card .cross-stub {
  position: absolute;
  top: 50%; right: -8px;
  transform: translateY(-50%);
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--cool-cross);
  border: 1px solid var(--bg);
  display: none;
}
#mapRoot .cross-mode-stubs .node-card.has-cross .cross-stub { display: block; }

/* ── DIRECTIONAL TREE CONNECTORS — hang off the node's OUTER side ── */
#mapRoot .cross-section-stubs-panel {
  display: none;           /* hidden by default; shown when cross-mode-stubs active */
  flex-direction: column; gap: 4px;
  position: absolute;
  top: 0;
  z-index: 10;
}
#mapRoot .cross-mode-stubs .cross-section-stubs-panel { display: flex; }

/* Left-column nodes: stub panel hangs into the LEFT gutter */
#mapRoot .stub-side-left .cross-section-stubs-panel {
  right: 100%;
  margin-right: 8px;
  align-items: flex-end;
  /* Expand toward the viewport left edge without forcing scroll */
  max-width: calc(50vw - 150px);
  min-width: 160px;
}
/* Right-column nodes: stub panel hangs into the RIGHT gutter */
#mapRoot .stub-side-right .cross-section-stubs-panel {
  left: 100%;
  margin-left: 8px;
  align-items: flex-start;
  /* Expand toward the viewport right edge without forcing scroll */
  max-width: calc(50vw - 150px);
  min-width: 160px;
}

/* Allow the stub panel to bleed outside leaf rows without clipping */
#mapRoot .branch-leaves-row { overflow: visible; }
#mapRoot .branch-leaves-left,
#mapRoot .branch-leaves-right { overflow: visible; }
#mapRoot .cross-stub-arrow { font-size: 11px; flex-shrink: 0; }
#mapRoot .cross-section-stub-item {
  display: flex;           /* always flex when panel is visible */
  align-items: center; gap: 5px;
  font-size: 10px; color: var(--cool-cross); font-weight: 600;
  cursor: pointer; white-space: normal; position: relative;
}
/* Direction prefix glyph */
#mapRoot .cross-section-stub-dir {
  display: inline-block;
  font-size: 11px; line-height: 1;
  color: var(--cool-cross);
  flex-shrink: 0;
}
#mapRoot .cross-section-stub-label {
  padding-block: 3px;
  padding-inline: 7px;
  background: var(--cool-cross-bg);
  border: 1px solid var(--cool-cross-border);
  border-radius: var(--radius-sm);
  border-style: dashed;
  transition: background 0.12s;
  display: inline-flex; align-items: flex-start; gap: 4px;
  font-size: 10px; color: var(--cool-cross);
  /* Allow full title to wrap — no truncation */
  white-space: normal;
  line-height: 1.35;
}
#mapRoot .cross-section-stub-label .stub-sec-badge {
  font-size: 9px; font-weight: 700;
  padding-block: 1px;
  padding-inline: 4px; border-radius: var(--radius-full);
  background: rgba(56,189,248,0.18); color: var(--cool-cross);
  flex-shrink: 0;
  margin-top: 1px; /* align badge with first line of text */
}
#mapRoot .cross-section-stub-item:hover .cross-section-stub-label {
  background: rgba(56,189,248,0.20);
  border-color: var(--cool-cross);
}

/* NARROW SCREENS: stubs stack in-flow under the node (stacked within node) */
@media (max-width: 1100px) {
  #mapRoot .cross-section-stubs-panel {
    position: static !important;
    margin: 6px 0 0 0 !important;
    right: auto !important; left: auto !important;
    align-items: flex-start !important;
    max-width: 200px !important;
    min-width: 0 !important;
  }
  #mapRoot .cross-section-stub-item {
    white-space: nowrap;
  }
  #mapRoot .cross-section-stub-label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 170px;
  }
}

/* Cross-link count badge on node card */
#mapRoot .node-cross-count {
  display: inline-block;
  margin-left: 4px;
  padding-block: 1px;
  padding-inline: 5px;
  border-radius: var(--radius-full);
  font-size: 9px; font-weight: 700;
  background: var(--cool-cross-bg);
  color: var(--cool-cross);
  border: 1px solid var(--cool-cross-border);
  vertical-align: middle;
}

/* Frontier pill — "Ready to introduce" (sky colour) */
#mapRoot .frontier-pill {
  display: inline-flex; align-items: center; gap: 4px;
  padding-block: 2px;
  padding-inline: 7px; border-radius: var(--radius-full);
  font-size: 9px; font-weight: 700; letter-spacing: 0.05em;
  background: rgba(56,189,248,0.12); color: var(--frontier-ring);
  border: 1px solid rgba(56,189,248,0.3);
  vertical-align: middle; margin-left: 5px;
}

/* ── PEER GROUP band ───────────────────────────────────
   Nodes sharing the same intro_rank shown in a subtle band
─────────────────────────────────────────────────────── */
#mapRoot .peer-group {
  background: rgba(255,255,255,0.02);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: var(--radius-md);
  padding-top: 10px;
  padding-inline: 10px;
  padding-bottom: 14px;
  position: relative;
  margin-bottom: 8px;
}
#mapRoot .peer-group-label {
  font-size: 10px; color: var(--text-dim);
  text-transform: uppercase; letter-spacing: 0.07em;
  margin-bottom: 8px; padding: 0 2px;
  display: flex; align-items: center; gap: 8px;
}
#mapRoot .peer-group-label::after { content: ''; flex: 1; height: 1px; background: rgba(255,255,255,0.06); }
#mapRoot .peer-group-badge {
  font-size: 9px; padding-block: 1px; padding-inline: 6px;
  background: var(--surface3); border: 1px solid var(--border);
  border-radius: var(--radius-full); color: var(--text-dim); margin-left: 6px;
}
#mapRoot .peer-group-nodes { display: flex; flex-wrap: wrap; gap: 10px; }

/* ═══════════════════════════════════════════════
   BRANCHED VIEW
═══════════════════════════════════════════════ */
#mapRoot .branch-spine-wrap { display: flex; flex-direction: column; align-items: center; position: relative; padding: 0 16px; }
#mapRoot .branch-spine-line { position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; background: linear-gradient(to bottom, var(--border2) 0%, var(--border) 100%); transform: translateX(-50%); z-index: 0; }
#mapRoot .branch-chapter-row { position: relative; width: 100%; display: flex; justify-content: center; align-items: center; margin-bottom: 8px; z-index: 2; }
#mapRoot .branch-chapter-node { background: var(--surface3); border: 2px solid var(--border2); border-radius: var(--radius-md); padding-block: 8px; padding-inline: 20px; text-align: center; font-size: 13px; font-weight: 600; color: var(--text); z-index: 2; position: relative; max-width: 220px; }
#mapRoot .branch-chapter-node .chapter-code { font-size: 10px; color: var(--text-muted); margin-bottom: 2px; letter-spacing: 0.05em; }
#mapRoot .branch-leaves-row { position: relative; width: 100%; display: grid; grid-template-columns: 1fr 56px 1fr; align-items: start; gap: 0; margin-bottom: 4px; z-index: 1; }
#mapRoot .branch-leaves-left { display: flex; flex-direction: column; gap: 10px; align-items: flex-end; padding-right: 40px; }
#mapRoot .branch-leaves-right { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; padding-left: 40px; }
#mapRoot .branch-spine-col {}

/* leaf node — same 3-state mastery border as node-card */
#mapRoot .leaf-node {
  position: relative; padding-block: 8px; padding-inline: 11px; border-radius: var(--radius-md);
  background: var(--surface2);
  cursor: pointer; transition: transform 0.15s, opacity 0.15s;
  max-width: 240px; width: 100%;
  border: 3px solid var(--mastery-needs-work);
}
#mapRoot .leaf-node.mastery-strong       { border-color: var(--mastery-strong); box-shadow: 0 0 0 1px rgba(159,114,248,0.25); }
#mapRoot .leaf-node.mastery-developing   { border-color: var(--mastery-developing); }
#mapRoot .leaf-node.mastery-needs-work   { border-color: var(--mastery-needs-work); }
#mapRoot .leaf-node.mastery-not-started  { border-color: var(--mastery-not-started); }
#mapRoot .leaf-node.no-cards {
  border: 2px dashed var(--mastery-no-cards);
  background: var(--surface2); box-shadow: none;
}
#mapRoot .leaf-node:hover { transform: translateY(-1px); }
#mapRoot .leaf-node.dimmed { opacity: 0.18; pointer-events: none; }
#mapRoot .leaf-node.highlighted { opacity: 1 !important; }
#mapRoot .leaf-node.frontier {
  filter: drop-shadow(0 0 8px rgba(56,189,248,0.55));
  border-color: var(--frontier-ring) !important;
  box-shadow: 0 0 0 2px rgba(56,189,248,0.3);
}
#mapRoot .leaf-node .node-card-code { font-size: 10px; font-weight: 700; color: var(--text-dim); letter-spacing: 0.06em; margin-bottom: 2px; }
#mapRoot .leaf-node .node-card-name { font-size: 12px; line-height: 1.3; color: var(--text); }
#mapRoot .leaf-node .node-card-count { font-size: 10px; color: var(--text-dim); margin-top: 3px; }
#mapRoot .leaf-node .cross-stub { position: absolute; top: 50%; right: -8px; transform: translateY(-50%); width: 7px; height: 7px; border-radius: 50%; background: var(--cool-cross); border: 1px solid var(--bg); display: none; }
#mapRoot .cross-mode-stubs .leaf-node.has-cross .cross-stub { display: block; }
/* cross-section-stub-item is always flex when its parent panel is visible (panel toggled above) */

/* High-yield heatmap fill + badge on leaf-node */
#mapRoot .leaf-node .hy-badge { display: none; position: absolute; top: 4px; right: 4px; width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid var(--bg); z-index: 2; }
#mapRoot .hy-active .leaf-node.hy-high { background: var(--hy-high-fill) !important; }
#mapRoot .hy-active .leaf-node.hy-med  { background: var(--hy-med-fill)  !important; }
#mapRoot .hy-active .leaf-node.hy-low  { background: var(--hy-low-fill)  !important; }
#mapRoot .hy-active .leaf-node.hy-none { background: var(--surface2); }
#mapRoot .hy-active .leaf-node.hy-high .hy-badge { display: block; background: var(--hy-high-color); }
#mapRoot .hy-active .leaf-node.hy-med  .hy-badge { display: block; background: var(--hy-med-color); }
#mapRoot .hy-active .leaf-node.hy-low  .hy-badge { display: block; background: var(--hy-low-color); }

#mapRoot .branch-svg-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; overflow: visible; }
#mapRoot .chapter-gap { height: 28px; z-index: 1; position: relative; }

/* ── INTEGRATION MODE — animated cluster regroup ── */
/* When integration OFF: normal branched layout */
/* When integration ON: an overlay cluster panel slides in above the tree */
#mapRoot #integration-clusters-overlay {
  display: none;
  margin-bottom: 20px;
  border: 1px solid var(--cool-cross-border);
  border-bottom: 2px solid var(--cool-cross);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: 0 4px 16px rgba(0,0,0,0.4);
  padding: 16px;
  overflow: hidden;
}
#mapRoot #integration-clusters-overlay.visible {
  display: block;
  animation: clusterSlideIn 0.35s cubic-bezier(0.4, 0, 0.2, 1) both;
}
@keyframes clusterSlideIn {
  from { opacity: 0; transform: translateY(-12px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
#mapRoot .cluster-overlay-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px; gap: 10px;
}
#mapRoot .cluster-overlay-title {
  font-size: 12px; font-weight: 700; color: var(--cool-cross);
  display: flex; align-items: center; gap: 6px;
  text-transform: uppercase; letter-spacing: 0.06em;
}
#mapRoot .cluster-overlay-note {
  font-size: 10px; color: var(--text-dim); font-style: italic;
}
#mapRoot .cluster-group {
  margin-bottom: 12px;
  padding-block: 10px;
  padding-inline: 12px;
  background: var(--surface3);
  border: 1px solid var(--cool-cross-border);
  border-radius: var(--radius-md);
  transition: opacity 0.2s, border-color 0.2s, box-shadow 0.2s;
}
/* Pinned cluster: elevated, bright border */
#mapRoot .cluster-group.pinned {
  border-color: var(--cool-cross);
  border-width: 2px;
  box-shadow: 0 0 0 3px rgba(56,189,248,0.15);
  background: rgba(56,189,248,0.06);
  position: relative;
  z-index: 2;
}
/* Dimmed siblings */
#mapRoot .cluster-group.dimmed {
  opacity: 0.35;
}
/* Pin-active: overlay collapses to a compact orientation strip (only the
   pinned cluster), pinned to the top of the map column so it follows the
   user down the tree. position:fixed (not sticky) because this mockup's
   nested overflow:auto #canvas breaks sticky; left/width/top are set inline
   at pin time from the overlay's in-flow box. The real /map build will use a
   clean scroll container where position:sticky suffices. */
#mapRoot #integration-clusters-overlay.pin-active {
  position: fixed;
  top: 56px;
  z-index: 15; /* above the map nodes, below the detail panel (z 20) */
  margin-bottom: 0;
}
#mapRoot #integration-clusters-overlay.pin-active .cluster-group.dimmed { display: none; }
#mapRoot #integration-clusters-overlay.pin-active .cluster-overlay-note { display: none; }
#mapRoot #integration-clusters-overlay.pin-active .cluster-group.pinned { margin-bottom: 0; }
#mapRoot #integration-clusters-overlay.pin-active .cluster-group.pinned .cluster-group-nodes {
  max-height: 168px; overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: var(--border2) transparent;
}
#mapRoot .cluster-unpin-btn {
  display: none;
  font-size: 10px; font-weight: 600; color: var(--cool-cross); cursor: pointer;
  background: var(--cool-cross-bg); border: 1px solid var(--cool-cross-border);
  border-radius: var(--radius-full); padding-block: 3px; padding-inline: 10px; white-space: nowrap;
  align-items: center; gap: 4px; transition: all 0.12s;
}
#mapRoot .cluster-unpin-btn:hover { border-color: var(--cool-cross); background: var(--surface3); }
#mapRoot #integration-clusters-overlay.pin-active .cluster-unpin-btn { display: inline-flex; }
#mapRoot .cluster-group-title {
  font-size: 11px; font-weight: 600; color: var(--cool-cross);
  margin-bottom: 8px; display: flex; align-items: center; gap: 6px;
}
#mapRoot .cluster-group-nodes {
  display: flex; flex-direction: column; gap: 5px;
}
#mapRoot .cluster-node-chip {
  display: flex; align-items: center; gap: 7px;
  width: 100%;
  padding-block: 6px;
  padding-inline: 10px; border-radius: var(--radius-sm);
  border: 1px solid var(--cool-cross-border);
  background: rgba(56,189,248,0.06);
  font-size: 11px; cursor: pointer; transition: all 0.12s;
  animation: chipMigrate 0.4s cubic-bezier(0.4,0,0.2,1) both;
  min-width: 0;
}
#mapRoot .cluster-node-chip:hover { background: rgba(56,189,248,0.14); border-color: var(--cool-cross); }
#mapRoot .cluster-node-chip.holding { background: rgba(56,189,248,0.22); border-color: var(--cool-cross); box-shadow: 0 0 0 2px rgba(56,189,248,0.25); transition: all 0.5s linear; }
@keyframes chipMigrate {
  from { opacity: 0; transform: scale(0.85) translateY(4px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
#mapRoot .cluster-node-chip-code { font-weight: 700; color: var(--cool-cross); font-size: 10px; flex-shrink: 0; }
#mapRoot .cluster-node-chip-name { color: var(--text); flex: 1; min-width: 0; }
#mapRoot .cluster-conn-arrow {
  font-size: 12px; color: var(--cool-cross); opacity: 0.6; align-self: center;
}

/* When integration-active: dim the main tree slightly to cue the overlay is primary */
#mapRoot .integration-active #branched-view .leaf-node:not(.has-cross-section) {
  opacity: 0.55;
  transition: opacity 0.3s;
}
#mapRoot .integration-active #branched-view .leaf-node.has-cross-section {
  box-shadow: 0 0 0 2px var(--cool-cross), 0 0 12px rgba(56,189,248,0.3);
  opacity: 1;
}

/* ═══════════════════════════════════════════════
   DETAIL PANEL
═══════════════════════════════════════════════ */
#mapRoot .detail-close-btn {
  position: absolute; top: 14px; right: 14px;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--surface2); border: 1px solid var(--border2);
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; color: var(--text-muted); transition: all 0.12s; z-index: 1; flex-shrink: 0;
}
#mapRoot .detail-close-btn:hover { background: var(--surface3); color: var(--text); border-color: var(--text-muted); }
#mapRoot .detail-inner { padding: 20px; position: relative; flex: 1; }

/* ── FULLSCREEN TOGGLE — pull-tab on left-middle edge ── */
#mapRoot .fullscreen-toggle {
  position: absolute;
  left: -14px;
  top: 50%;
  transform: translateY(-50%);
  width: 28px; height: 48px;
  background: var(--surface2);
  border: 1px solid var(--border2);
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.15s;
  z-index: 25;
  font-size: 14px;
  line-height: 1;
  user-select: none;
}
#mapRoot .fullscreen-toggle:hover { background: var(--surface3); color: var(--text); border-color: var(--frontier-ring); }
#mapRoot .fullscreen-toggle:focus-visible { outline: 2px solid var(--frontier-ring); outline-offset: 2px; }

/* Fullscreen state */
#mapRoot #detail-panel.fullscreen {
  position: fixed;
  inset: 0;
  width: 100vw !important;
  max-width: 100vw !important;
  height: 100vh;
  border-radius: 0;
  border-left: none;
  z-index: 100;
  transform: none !important;
}
#mapRoot #detail-panel.fullscreen .fullscreen-toggle {
  left: 8px;
  top: 50%;
  transform: translateY(-50%);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border2);
}

/* ═══════════════════════════════════════════════
   NAV MAP — focused connections visualisation
   The selected node shown centrally, neighbours grouped directionally.
   Single-click → highlight on main map ONLY (no panel change).
   Hold (~500ms) or click node in main map → switch focused node.
═══════════════════════════════════════════════ */
#mapRoot #conn-list-wrap {
  margin-bottom: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border);
}
#mapRoot #conn-list-title {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-dim);
  margin-bottom: 8px; display: flex; align-items: center; gap: 6px;
}
/* ═══════════════════════════════════════════════
   NAV MAP — 4-zone directional compass
   Layout (top→bottom):
     Zone: ↑ Needs (prerequisites)
     Centre node
     Zone: ↓ Unlocks (things this enables)
     Zone: ↔ Related (co-reqs / cross-section)
   All zones are flex columns. If many chips, cap height + scroll.
═══════════════════════════════════════════════ */
#mapRoot .nav-map {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: 4px 0;
}
/* Zone wrapper: label + scrollable chip list */
#mapRoot .nav-map-zone {
  display: flex;
  flex-direction: column;
  gap: 0;
  min-width: 0;
}
#mapRoot .nav-map-zone-label {
  font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--text-dim);
  padding-top: 5px;
  padding-inline: 8px;
  padding-bottom: 3px;
  display: flex; align-items: center; gap: 6px;
}
#mapRoot .nav-map-zone-label::after {
  content: ''; flex: 1; height: 1px;
  background: var(--border);
}
/* Chip list within each zone — grows naturally, extras hidden until expanded */
#mapRoot .nav-map-chip-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-top: 4px;
  padding-inline: 8px;
  padding-bottom: 6px;
}
/* Hidden chips (index >= 4) revealed when zone has .expanded class */
#mapRoot .nav-map-chip-list .nav-conn-chip.nav-chip-hidden {
  display: none;
}
#mapRoot .nav-map-zone.expanded .nav-conn-chip.nav-chip-hidden {
  display: flex;
}
/* "+N more" / "Show less" toggle button */
#mapRoot .nav-map-more {
  display: inline-flex; align-items: center;
  padding-block: 3px;
  padding-inline: 8px; margin-top: 2px;
  border-radius: var(--radius-full);
  border: 1px dashed var(--border2);
  background: transparent;
  font-size: 10px; color: var(--text-dim);
  cursor: pointer; user-select: none;
  transition: background 0.12s, color 0.12s;
  width: fit-content;
}
#mapRoot .nav-map-more:hover { background: var(--surface3); color: var(--text-muted); }

/* The selected node in the centre */
#mapRoot .nav-map-centre-wrap {
  display: flex;
  justify-content: center;
  padding-block: 6px;
  padding-inline: 8px;
}
#mapRoot .nav-map-centre {
  padding-block: 7px;
  padding-inline: 14px;
  background: var(--surface3);
  border: 2px solid var(--frontier-ring);
  border-radius: var(--radius-md);
  font-size: 12px; font-weight: 700; color: var(--text);
  text-align: center; min-width: 80px; max-width: 200px;
  box-shadow: 0 0 0 3px rgba(56,189,248,0.18);
}
#mapRoot .nav-map-centre .nav-map-centre-code { font-size: 10px; color: var(--cool-cross); margin-bottom: 2px; }

/* Dividers between zones and centre */
#mapRoot .nav-map-divider {
  height: 1px;
  background: var(--border);
  margin: 2px 0;
}
/* Arrow connectors: small centred glyph between zones and the centre node */
#mapRoot .nav-map-connector {
  text-align: center;
  font-size: 12px; color: var(--text-dim);
  line-height: 1; padding: 1px 0;
}

/* Connector node chips in the nav map */
#mapRoot .nav-conn-chip {
  display: flex; align-items: center; gap: 6px;
  padding-block: 5px;
  padding-inline: 8px; border-radius: var(--radius-sm);
  border: 1px solid var(--border2); background: var(--surface2);
  font-size: 11px; cursor: pointer; transition: all 0.12s;
  white-space: nowrap; overflow: hidden;
  min-height: 28px;
  user-select: none;
  position: relative;
}
#mapRoot .nav-conn-chip:hover { border-color: var(--frontier-ring); background: var(--surface3); }
#mapRoot .nav-conn-chip.nav-conn-cross { border-color: var(--cool-cross-border); }
#mapRoot .nav-conn-chip.nav-conn-cross:hover { border-color: var(--cool-cross); background: var(--cool-cross-bg); }
#mapRoot .nav-conn-chip-code { font-weight: 700; color: var(--text-muted); font-size: 10px; flex-shrink: 0; }
#mapRoot .nav-conn-chip-name { color: var(--text); overflow: hidden; text-overflow: ellipsis; font-size: 10px; flex: 1; min-width: 0; }
#mapRoot .nav-conn-chip-dot  { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
/* Hold-progress underline */
#mapRoot .nav-conn-chip::after {
  content: '';
  position: absolute; bottom: 0; left: 0; height: 2px;
  background: var(--frontier-ring);
  width: 0%; border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  transition: width 0s;
}
#mapRoot .nav-conn-chip.holding::after {
  width: 100%;
  transition: width 500ms linear;
}
/* Directional arrows between centre and zones */
#mapRoot .nav-map-arrow {
  font-size: 11px; color: var(--text-dim); text-align: center;
  line-height: 1; flex-shrink: 0;
}
#mapRoot .nav-conn-empty { font-size: 10px; color: var(--text-dim); font-style: italic; padding-block: 4px; padding-inline: 8px; }

/* Old conn-row / conn-group — kept for backwards-compat fallback only, hidden */
#mapRoot .conn-group { display: none; }
#mapRoot .conn-row { display: none; }
#mapRoot .conn-empty { font-size: 11px; color: var(--text-dim); font-style: italic; padding: 2px 0; }

/* Node nav breadcrumb trail */
#mapRoot #nav-trail-wrap {
  padding-block: 8px;
  padding-inline: 12px;
  background: var(--surface2);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 0;
  flex-wrap: wrap; min-height: 34px;
  font-size: 11px; color: var(--text-muted);
}
#mapRoot #nav-trail-wrap.empty { display: none; }
#mapRoot .nav-trail-item { display: flex; align-items: center; gap: 0; }
#mapRoot .nav-trail-crumb {
  padding-block: 2px;
  padding-inline: 6px; border-radius: var(--radius-sm);
  cursor: pointer; color: var(--text-muted); transition: color 0.12s; font-weight: 500;
}
#mapRoot .nav-trail-crumb:hover { color: var(--frontier-ring); }
#mapRoot .nav-trail-crumb.current { color: var(--text); cursor: default; }
#mapRoot .nav-trail-sep { color: var(--text-dim); margin: 0 2px; font-size: 10px; }

#mapRoot .detail-hero { padding-bottom: 16px; border-bottom: 1px solid var(--border); margin-bottom: 16px; padding-right: 36px; }
#mapRoot .detail-code-badge { display: inline-block; padding-block: 3px; padding-inline: 8px; border-radius: var(--radius-sm); font-size: 11px; font-weight: 700; letter-spacing: 0.06em; background: var(--surface3); border: 1px solid var(--border2); color: var(--text-muted); margin-bottom: 8px; }
#mapRoot .detail-node-name { font-size: 17px; font-weight: 700; line-height: 1.3; margin-bottom: 10px; }
#mapRoot .detail-badges { display: flex; flex-wrap: wrap; gap: 6px; }

#mapRoot .mastery-badge { padding-block: 3px; padding-inline: 9px; border-radius: var(--radius-full); font-size: 11px; font-weight: 600; }
#mapRoot .mastery-badge.strong       { background: rgba(159,114,248,0.15); color: var(--mastery-strong); border: 1px solid rgba(159,114,248,0.3); }
#mapRoot .mastery-badge.developing   { background: rgba(224,162,58,0.15); color: var(--mastery-developing); border: 1px solid rgba(224,162,58,0.3); }
#mapRoot .mastery-badge.needs-work   { background: var(--surface3); color: var(--text-muted); border: 1px solid var(--border2); }
#mapRoot .mastery-badge.not-started  { background: rgba(56,189,248,0.12); color: var(--mastery-not-started); border: 1px solid rgba(56,189,248,0.3); }
#mapRoot .mastery-badge.no-cards     { background: var(--surface2); color: var(--text-dim); border: 1px dashed var(--mastery-no-cards); }
#mapRoot .frontier-badge { padding-block: 3px; padding-inline: 9px; border-radius: var(--radius-full); font-size: 11px; font-weight: 600; background: rgba(56,189,248,0.1); color: var(--frontier-ring); border: 1px solid rgba(56,189,248,0.3); }

#mapRoot .detail-section { margin-bottom: 16px; }
#mapRoot .detail-section-title { font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-dim); margin-bottom: 8px; }
#mapRoot .detail-breadcrumb { font-size: 12px; color: var(--text-muted); display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
#mapRoot .detail-breadcrumb .sep { color: var(--text-dim); }
#mapRoot .detail-stat-row { display: flex; gap: 16px; flex-wrap: wrap; }
#mapRoot .detail-stat { font-size: 12px; color: var(--text-muted); display: flex; align-items: center; gap: 5px; }
#mapRoot .detail-stat .val { color: var(--text); font-weight: 600; }

/* ── GRADE DISTRIBUTION BAR (detail panel) ─── */
#mapRoot .grade-dist-bar-wrap { margin: 4px 0 2px; }
#mapRoot .grade-dist-bar { height: 8px; border-radius: var(--radius-full); overflow: hidden; display: flex; gap: 1px; margin-bottom: 4px; }
#mapRoot .grade-dist-seg { height: 100%; border-radius: var(--radius-full); transition: width 0.4s ease; }
#mapRoot .grade-dist-labels { display: flex; gap: 8px; flex-wrap: wrap; }
#mapRoot .grade-dist-label { display: flex; align-items: center; gap: 4px; font-size: 10px; color: var(--text-dim); }
#mapRoot .grade-dist-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }

/* ── CARD RIBBON — vertical stack ─── */
#mapRoot .card-ribbon-wrap {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
/* Each card row: a head (tier dot + prompt + caret) + a click-to-reveal answer. */
#mapRoot .card-row {
  display: block;
  padding-block: 6px;
  padding-inline: 10px; border-radius: var(--radius-sm);
  border: 1px solid var(--border2); background: var(--surface3);
  font-size: 11px; color: var(--text-muted);
  width: 100%; min-width: 0;
}
#mapRoot .card-row-head { display: flex; align-items: center; gap: 7px; min-width: 0; }
#mapRoot .card-row-revealable { cursor: pointer; transition: background 0.12s, border-color 0.12s; }
#mapRoot .card-row-revealable:hover { background: var(--surface2); border-color: var(--border); }
#mapRoot .card-row-prompt {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#mapRoot .card-row.revealed .card-row-prompt { white-space: normal; }
#mapRoot .card-row-caret { flex-shrink: 0; color: var(--text-dim); font-size: 9px; transition: transform 0.12s; }
#mapRoot .card-row.revealed .card-row-caret { transform: rotate(180deg); }
#mapRoot .card-row-answer {
  display: none; margin-top: 6px; padding-top: 6px;
  border-top: 1px solid var(--border);
  font-size: 11.5px; line-height: 1.5; color: var(--text);
  white-space: pre-wrap; word-break: break-word;
  max-height: 280px; overflow-y: auto;
}
#mapRoot .card-row.revealed .card-row-answer { display: block; }
/* Hidden card rows revealed when group has .expanded class */
#mapRoot .card-row.card-row-hidden { display: none; }
#mapRoot .card-type-group.expanded .card-row.card-row-hidden { display: block; }
/* Keep old card-chip for any residual references */
#mapRoot .card-chip {
  display: flex; align-items: center; gap: 5px;
  padding-block: 5px;
  padding-inline: 9px; border-radius: var(--radius-sm);
  border: 1px solid var(--border2); background: var(--surface3);
  font-size: 11px; color: var(--text-muted);
  white-space: nowrap; flex-shrink: 0;
  max-width: 200px; overflow: hidden; text-overflow: ellipsis;
}
#mapRoot .card-chip-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
/* "+N more" toggle for card groups */
#mapRoot .card-more {
  display: inline-flex; align-items: center;
  padding-block: 3px;
  padding-inline: 8px; margin-top: 2px;
  border-radius: var(--radius-full);
  border: 1px dashed var(--border);
  background: transparent;
  font-size: 10px; color: var(--text-dim);
  cursor: pointer; user-select: none;
  transition: background 0.12s, color 0.12s;
  width: fit-content;
}
#mapRoot .card-more:hover { background: var(--surface3); color: var(--text-muted); }
#mapRoot .card-ribbon-more { display: none; /* legacy, replaced by .card-more */ }

/* ── EXAM FREQ / HIGH-YIELD in detail ─── */
#mapRoot .hy-detail-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
#mapRoot .hy-detail-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding-block: 3px;
  padding-inline: 8px; border-radius: var(--radius-full);
  font-size: 11px; font-weight: 700;
}
#mapRoot .hy-detail-badge.hy-high { background: var(--hy-high-bg); color: var(--hy-high-color); border: 1px solid var(--hy-high-border); }
#mapRoot .hy-detail-badge.hy-med  { background: var(--hy-med-bg); color: var(--hy-med-color); border: 1px solid var(--hy-med-border); }
#mapRoot .hy-detail-badge.hy-low  { background: var(--hy-low-bg); color: var(--hy-low-color); border: 1px solid var(--hy-low-border); }
#mapRoot .hy-detail-badge.hy-none { background: var(--surface3); color: var(--text-dim); border: 1px solid var(--border); }

/* ── STUDY CTA ─── */
#mapRoot .study-cta-btn {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px;
  padding-block: 10px;
  padding-inline: 16px;
  background: linear-gradient(135deg, rgba(159,114,248,0.15), rgba(56,189,248,0.10));
  border: 1px solid rgba(159,114,248,0.35);
  border-radius: var(--radius-md);
  width: 100%; cursor: pointer;
  transition: all 0.15s;
  margin-bottom: 8px;
}
#mapRoot .study-cta-btn:hover { background: linear-gradient(135deg, rgba(159,114,248,0.25), rgba(56,189,248,0.18)); border-color: var(--mastery-strong); }
#mapRoot .study-cta-btn-main { font-size: 14px; font-weight: 700; color: var(--text); }
#mapRoot .study-cta-btn-sub  { font-size: 11px; color: var(--text-muted); }

#mapRoot .chip-list { display: flex; flex-wrap: wrap; gap: 6px; }
#mapRoot .chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding-block: 4px;
  padding-inline: 9px; border-radius: var(--radius-full);
  font-size: 11px; border: 1px solid var(--border2);
  background: var(--surface2); color: var(--text-muted);
  cursor: pointer; transition: all 0.12s;
  max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#mapRoot .chip:hover { border-color: var(--frontier-ring); color: var(--frontier-ring); background: rgba(56,189,248,0.08); }
#mapRoot .chip.chip-cross { border-color: var(--cool-cross-border); }
#mapRoot .chip.chip-cross:hover { border-color: var(--cool-cross); color: var(--cool-cross); background: var(--cool-cross-bg); }
#mapRoot .chip-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }

#mapRoot .path-btn { display: flex; align-items: center; gap: 7px; padding-block: 8px; padding-inline: 14px; border-radius: var(--radius-sm); background: rgba(56,189,248,0.08); border: 1px solid rgba(56,189,248,0.25); color: var(--frontier-ring); font-size: 13px; font-weight: 500; transition: all 0.12s; width: 100%; justify-content: center; margin-bottom: 8px; }
#mapRoot .path-btn:hover { background: rgba(56,189,248,0.15); border-color: var(--frontier-ring); }
#mapRoot .detail-empty { font-size: 12px; color: var(--text-dim); font-style: italic; }

/* ═══════════════════════════════════════════════
   LIST VIEW
═══════════════════════════════════════════════ */
#mapRoot .list-view {
  display: flex;
  flex-direction: column;
  gap: 0;
}
#mapRoot .list-chapter {
  margin-bottom: 4px;
}
#mapRoot .list-section-header {
  display: flex; align-items: baseline; gap: 10px;
  padding-block: 11px;
  padding-inline: 14px;
  margin-top: 10px;
  background: linear-gradient(90deg, var(--surface3), var(--surface2));
  border-top: 2px solid var(--frontier-ring);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 6;
}
#mapRoot .list-section-code {
  font-size: 14px; font-weight: 800; color: var(--frontier-ring);
  letter-spacing: 0.06em; flex-shrink: 0;
}
#mapRoot .list-section-name {
  font-size: 15px; font-weight: 700; color: var(--text);
  text-transform: uppercase; letter-spacing: 0.03em;
}
#mapRoot .list-chapter-header {
  display: flex; align-items: center; gap: 8px;
  padding-block: 8px;
  padding-inline: 12px;
  background: var(--surface3);
  border-top: 1px solid var(--border2);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 42px;
  z-index: 5;
}
#mapRoot .list-chapter-code {
  font-size: 10px; font-weight: 700; color: var(--text-muted);
  letter-spacing: 0.07em;
  flex-shrink: 0;
}
#mapRoot .list-chapter-name {
  font-size: 13px; font-weight: 600; color: var(--text);
}
#mapRoot .list-leaves {
  display: flex;
  flex-direction: column;
  gap: 0;
}
#mapRoot .list-rank-group-label {
  font-size: 9px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--text-dim);
  padding-top: 6px;
  padding-inline: 12px;
  padding-bottom: 2px;
  display: flex; align-items: center; gap: 8px;
}
#mapRoot .list-rank-group-label::after {
  content: ''; flex: 1; height: 1px; background: var(--border);
}
#mapRoot .list-leaf-row {
  display: flex; align-items: center; gap: 10px;
  padding-block: 9px;
  padding-inline: 12px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.1s;
  position: relative;
}
#mapRoot .list-leaf-row:hover { background: var(--surface2); }
#mapRoot .list-leaf-row:focus { outline: 2px solid var(--frontier-ring); outline-offset: -2px; }
/* Left mastery bar */
#mapRoot .list-mastery-bar {
  width: 3px;
  align-self: stretch;
  border-radius: 2px;
  flex-shrink: 0;
  min-height: 20px;
}
#mapRoot .list-leaf-row.mastery-strong      .list-mastery-bar { background: var(--mastery-strong); box-shadow: 0 0 4px rgba(159,114,248,0.4); }
#mapRoot .list-leaf-row.mastery-developing  .list-mastery-bar { background: var(--mastery-developing); }
#mapRoot .list-leaf-row.mastery-needs-work  .list-mastery-bar { background: var(--mastery-needs-work); }
#mapRoot .list-leaf-row.mastery-not-started .list-mastery-bar { background: var(--mastery-not-started); }
#mapRoot .list-leaf-row.no-cards            .list-mastery-bar { background: var(--mastery-no-cards); border: 1px dashed var(--mastery-no-cards); background: transparent; }
/* frontier glow on list row */
#mapRoot .list-leaf-row.frontier {
  box-shadow: inset 3px 0 0 var(--frontier-ring);
}
#mapRoot .list-leaf-row.frontier .list-mastery-bar { background: var(--frontier-ring); box-shadow: 0 0 6px rgba(56,189,248,0.5); }
#mapRoot .list-leaf-main {
  flex: 1; min-width: 0;
}
#mapRoot .list-leaf-code {
  font-size: 10px; font-weight: 700; color: var(--text-dim);
  letter-spacing: 0.06em; font-family: ui-monospace, 'Cascadia Code', monospace;
  flex-shrink: 0; margin-right: 2px;
}
#mapRoot .list-leaf-name {
  font-size: 13px; font-weight: 500; color: var(--text);
  line-height: 1.3;
}
#mapRoot .list-leaf-meta {
  display: flex; align-items: center; gap: 6px; margin-top: 2px;
  flex-wrap: wrap;
}
#mapRoot .list-leaf-count {
  font-size: 11px; color: var(--text-dim);
}
#mapRoot .list-leaf-frontier-pill {
  display: inline-flex; align-items: center; gap: 3px;
  padding-block: 1px;
  padding-inline: 6px; border-radius: var(--radius-full);
  font-size: 9px; font-weight: 700; letter-spacing: 0.04em;
  background: rgba(56,189,248,0.12); color: var(--frontier-ring);
  border: 1px solid rgba(56,189,248,0.3);
}
#mapRoot .list-leaf-hy-dot {
  width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
}
/* Section-scoped list: topic rows indented under chapter header */
#mapRoot .list-leaf-row.indented {
  padding-left: 28px;
}

/* ═══════════════════════════════════════════════
   LEGEND  (FIX 3)
   Repositioned: a popover anchored below the topbar legend-toggle button
   (top-left of the map view). No longer overlaps content on open — it starts
   hidden (collapsed) and appears only when the user toggles it.
   The old #legend-toggle / #legend-chevron / #legend-body structure is kept so
   the existing JS toggle logic still works; the topbar button calls the same handler.
═══════════════════════════════════════════════ */
#mapRoot #legend {
  position: fixed;
  /* Sit just below the 52px topbar, anchored to the left edge of the topbar */
  top: 60px; left: 16px;
  background: var(--surface); border: 1px solid var(--border2);
  border-radius: var(--radius-md); padding-block: 12px; padding-inline: 14px;
  z-index: 50; min-width: 230px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.5);
  /* FIX 3: hidden by default — toggled via topbar button */
  display: none;
}
#mapRoot #legend.legend-visible { display: block; }
/* The old internal toggle row is hidden — the topbar button drives open/close now */
#mapRoot #legend-toggle { display: none; }
#mapRoot #legend-body { margin-top: 0; display: flex; flex-direction: column; gap: 5px; }
#mapRoot #legend-body.collapsed { display: none; }
#mapRoot .legend-row { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--text-muted); }
/* mastery border swatches */
#mapRoot .legend-border-strong   { width: 16px; height: 16px; border-radius: 4px; background: var(--surface2); border: 3px solid var(--mastery-strong); flex-shrink: 0; }
#mapRoot .legend-border-developing { width: 16px; height: 16px; border-radius: 4px; background: var(--surface2); border: 3px solid var(--mastery-developing); flex-shrink: 0; }
#mapRoot .legend-border-needs-work { width: 16px; height: 16px; border-radius: 4px; background: var(--surface2); border: 3px solid var(--mastery-needs-work); flex-shrink: 0; }
#mapRoot .legend-border-no-cards   { width: 16px; height: 16px; border-radius: 4px; background: transparent; border: 2px dashed var(--mastery-no-cards); flex-shrink: 0; }
#mapRoot .legend-swatch { width: 16px; height: 16px; border-radius: 4px; flex-shrink: 0; }
/* Frontier ring is sky (#38BDF8), distinct from cross-link sky dashed edges via solid ring + glow */
#mapRoot .legend-swatch.frontier { background: var(--surface2); border: 3px solid var(--frontier-ring); box-shadow: 0 0 0 2px rgba(56,189,248,0.25), 0 0 8px rgba(56,189,248,0.3); border-radius: 50%; }
#mapRoot .legend-line { width: 24px; height: 2px; flex-shrink: 0; }
#mapRoot .legend-line.prereq { background: var(--edge-prereq); }
#mapRoot .legend-line.coreq { border-top: 2px dashed var(--edge-coreq); height: 0; }
#mapRoot .legend-line.cross-edge { border-top: 2px dashed var(--cool-cross); height: 0; }
#mapRoot .legend-sep { height: 1px; background: var(--border); margin: 3px 0; }
/* high-yield dots for legend */
#mapRoot .legend-hy-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }

/* ═══════════════════════════════════════════════
   CHAPTER LAYER — dashboard strip + chapter graph
═══════════════════════════════════════════════ */

/* Dashboard strip at top of chapter layer */
#mapRoot .chapter-dashboard {
  background: var(--surface2);
  border: 1px solid var(--border2);
  border-radius: var(--radius-lg);
  padding-block: 16px;
  padding-inline: 20px;
  margin-bottom: 24px;
}
#mapRoot .chapter-dashboard-title {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 14px;
}
#mapRoot .chapter-dashboard-code {
  font-size: 11px; font-weight: 700; color: var(--text-muted);
  letter-spacing: 0.07em;
  padding-block: 2px;
  padding-inline: 7px;
  background: var(--surface3); border: 1px solid var(--border2);
  border-radius: var(--radius-full);
}
#mapRoot .chapter-dashboard-name {
  font-size: 16px; font-weight: 700; color: var(--text);
  flex: 1;
}
#mapRoot .chapter-dashboard-metrics {
  display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-start;
  margin-bottom: 14px;
}
#mapRoot .chapter-metric {
  display: flex; flex-direction: column; gap: 4px;
  min-width: 100px;
  background: var(--surface3); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding-block: 8px; padding-inline: 12px;
  flex: 1;
}
#mapRoot .chapter-metric-label {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-dim); white-space: nowrap;
}
#mapRoot .chapter-metric-value {
  font-size: 14px; font-weight: 700; color: var(--text);
}
#mapRoot .chapter-metric-sub {
  font-size: 10px; color: var(--text-muted);
}
/* Mastery rollup segmented bar within dashboard */
#mapRoot .chapter-mastery-bar {
  display: flex; height: 6px; border-radius: var(--radius-full); overflow: hidden; gap: 1px;
  margin: 4px 0 2px;
  min-width: 80px;
}
#mapRoot .chapter-mastery-seg {
  height: 100%; border-radius: var(--radius-full);
}
#mapRoot .chapter-mastery-chips {
  display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px;
}
#mapRoot .chapter-mastery-chip {
  display: inline-flex; align-items: center; gap: 3px;
  padding-block: 1px;
  padding-inline: 6px; border-radius: var(--radius-full);
  font-size: 9px; font-weight: 600;
  border: 1px solid transparent;
}
#mapRoot .chapter-mastery-chip.strong   { background: rgba(159,114,248,0.12); color: var(--mastery-strong);    border-color: rgba(159,114,248,0.3); }
#mapRoot .chapter-mastery-chip.developing { background: rgba(224,162,58,0.12); color: var(--mastery-developing); border-color: rgba(224,162,58,0.3); }
#mapRoot .chapter-mastery-chip.needs-work { background: var(--surface3); color: var(--text-muted); border-color: var(--border2); }
#mapRoot .chapter-mastery-chip.not-started { background: rgba(56,189,248,0.10); color: var(--mastery-not-started); border-color: rgba(56,189,248,0.25); }
#mapRoot .chapter-mastery-chip.no-cards { background: var(--surface2); color: var(--text-dim); border-color: var(--border); }
/* Ready pill */
#mapRoot .chapter-ready-pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding-block: 3px;
  padding-inline: 10px; border-radius: var(--radius-full);
  background: rgba(56,189,248,0.10); color: var(--frontier-ring);
  border: 1px solid rgba(56,189,248,0.28);
  font-size: 12px; font-weight: 700;
}
/* Study CTA in dashboard */
#mapRoot .chapter-study-cta {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; padding-block: 10px; padding-inline: 16px;
  background: linear-gradient(135deg, rgba(56,189,248,0.12), rgba(159,114,248,0.10));
  border: 1px solid rgba(56,189,248,0.3);
  border-radius: var(--radius-md);
  cursor: pointer; transition: all 0.15s;
  width: 100%; margin-top: 8px;
}
#mapRoot .chapter-study-cta:hover {
  background: linear-gradient(135deg, rgba(56,189,248,0.22), rgba(159,114,248,0.18));
  border-color: var(--frontier-ring);
}
#mapRoot .chapter-study-cta-main { font-size: 14px; font-weight: 700; color: var(--text); }
#mapRoot .chapter-study-cta-sub  { font-size: 11px; color: var(--text-muted); }

/* Chapter graph — vertical spine of topics */
#mapRoot .chapter-graph-wrap {
  display: flex; flex-direction: column; align-items: center;
  position: relative; padding: 0 16px;
}
/* Vertical spine line for chapter graph */
#mapRoot .chapter-graph-spine-line {
  position: absolute; left: 50%; top: 16px; bottom: 16px;
  width: 2px; background: linear-gradient(to bottom, var(--border2) 0%, var(--border) 100%);
  transform: translateX(-50%); z-index: 0; border-radius: 1px;
}
/* Peer rank group within chapter graph */
#mapRoot .chapter-rank-group {
  width: 100%; position: relative; z-index: 1;
  margin-bottom: 20px;
}
#mapRoot .chapter-rank-label {
  font-size: 10px; color: var(--text-dim); text-transform: uppercase;
  letter-spacing: 0.07em; text-align: center; padding: 4px 0 8px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
#mapRoot .chapter-rank-label::before,
#mapRoot .chapter-rank-label::after {
  content: ''; flex: 1; height: 1px;
  background: rgba(255,255,255,0.07); max-width: 80px;
}
/* Peer-group band in chapter graph */
#mapRoot .chapter-peer-band {
  background: rgba(255,255,255,0.02);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: var(--radius-md); padding-top: 8px; padding-inline: 8px; padding-bottom: 12px;
}
#mapRoot .chapter-peer-band-label {
  font-size: 9px; color: var(--text-dim); text-transform: uppercase;
  letter-spacing: 0.07em; margin-bottom: 8px; padding: 0 2px;
  display: flex; align-items: center; gap: 8px;
}
#mapRoot .chapter-peer-band-label::after { content: ''; flex: 1; height: 1px; background: rgba(255,255,255,0.06); }
#mapRoot .chapter-peer-nodes {
  display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;
}
/* Topic row — topic placed left or right of spine */
#mapRoot .chapter-topic-row {
  position: relative; width: 100%;
  display: grid; grid-template-columns: 1fr 56px 1fr;
  align-items: start; gap: 0; margin-bottom: 6px; z-index: 1;
}
#mapRoot .chapter-topic-left  { display: flex; flex-direction: column; align-items: flex-end; padding-right: 40px; }
#mapRoot .chapter-topic-right { display: flex; flex-direction: column; align-items: flex-start; padding-left: 40px; }
#mapRoot .chapter-topic-spine-col {}

/* Prereq connector caption */
#mapRoot .prereq-caption {
  display: flex; align-items: center; gap: 4px;
  font-size: 9px; color: var(--text-dim); margin-top: 4px;
  font-style: italic;
}
#mapRoot .prereq-caption-arrow {
  color: var(--edge-prereq); font-size: 10px;
}

/* Chapter leaf tile — same visual as section leaf-node but used in chapter graph */
#mapRoot .chapter-leaf-tile {
  position: relative; padding-block: 8px; padding-inline: 11px; border-radius: var(--radius-md);
  background: var(--surface2);
  cursor: pointer; transition: transform 0.15s, opacity 0.15s;
  max-width: 240px; width: 100%;
  border: 3px solid var(--mastery-needs-work);
}
#mapRoot .chapter-leaf-tile.mastery-strong       { border-color: var(--mastery-strong); box-shadow: 0 0 0 1px rgba(159,114,248,0.25); }
#mapRoot .chapter-leaf-tile.mastery-developing   { border-color: var(--mastery-developing); }
#mapRoot .chapter-leaf-tile.mastery-needs-work   { border-color: var(--mastery-needs-work); }
#mapRoot .chapter-leaf-tile.mastery-not-started  { border-color: var(--mastery-not-started); }
#mapRoot .chapter-leaf-tile.no-cards {
  border: 2px dashed var(--mastery-no-cards); background: var(--surface2); box-shadow: none;
}
#mapRoot .chapter-leaf-tile:hover { transform: translateY(-1px); }
#mapRoot .chapter-leaf-tile.frontier {
  filter: drop-shadow(0 0 8px rgba(56,189,248,0.55));
  border-color: var(--frontier-ring) !important;
  box-shadow: 0 0 0 2px rgba(56,189,248,0.3);
}
#mapRoot .chapter-leaf-tile.focused-tile {
  outline: 2px solid var(--frontier-ring);
  outline-offset: 2px;
}
/* High-yield tint on chapter-leaf-tile */
#mapRoot .hy-active .chapter-leaf-tile.hy-high { background: var(--hy-high-fill) !important; }
#mapRoot .hy-active .chapter-leaf-tile.hy-med  { background: var(--hy-med-fill)  !important; }
#mapRoot .hy-active .chapter-leaf-tile.hy-low  { background: var(--hy-low-fill)  !important; }
#mapRoot .hy-active .chapter-leaf-tile.hy-none { background: var(--surface2); }
#mapRoot .hy-active .chapter-leaf-tile.hy-high .hy-badge { display: block; background: var(--hy-high-color); }
#mapRoot .hy-active .chapter-leaf-tile.hy-med  .hy-badge { display: block; background: var(--hy-med-color); }
#mapRoot .hy-active .chapter-leaf-tile.hy-low  .hy-badge { display: block; background: var(--hy-low-color); }

/* ═══════════════════════════════════════════════
   OVERVIEW LIST VIEW — full curriculum outline
═══════════════════════════════════════════════ */
#mapRoot #overview-list-view {
  margin-top: 8px;
}
#mapRoot .ov-list-section-row {
  display: flex; align-items: center; gap: 10px;
  padding-block: 11px;
  padding-inline: 14px;
  margin-top: 12px;
  background: linear-gradient(90deg, var(--surface3), var(--surface2));
  border-top: 2px solid var(--frontier-ring);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 6;
  cursor: pointer;
  transition: background 0.1s;
}
#mapRoot .ov-list-section-row:hover { background: linear-gradient(90deg, var(--surface3), var(--surface3)); }
#mapRoot .ov-list-section-code {
  font-size: 14px; font-weight: 800; color: var(--frontier-ring);
  letter-spacing: 0.06em; flex-shrink: 0;
}
#mapRoot .ov-list-section-name {
  font-size: 15px; font-weight: 700; color: var(--text);
  text-transform: uppercase; letter-spacing: 0.03em; flex: 1;
}
#mapRoot .ov-list-section-meta {
  font-size: 11px; color: var(--text-dim); white-space: nowrap;
}
#mapRoot .ov-list-chapter-row {
  display: flex; align-items: center; gap: 10px;
  padding-top: 8px;
  padding-right: 12px;
  padding-bottom: 8px;
  padding-left: 28px;
  background: var(--surface3);
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.1s;
}
#mapRoot .ov-list-chapter-row:hover { background: var(--surface2); }
#mapRoot .ov-list-chapter-mastery-bar {
  width: 3px; align-self: stretch; border-radius: 2px; flex-shrink: 0; min-height: 16px;
  background: var(--border2);
}
#mapRoot .ov-list-chapter-code {
  font-size: 10px; font-weight: 700; color: var(--text-muted);
  letter-spacing: 0.07em; flex-shrink: 0;
}
#mapRoot .ov-list-chapter-name {
  font-size: 13px; font-weight: 600; color: var(--text); flex: 1;
}
#mapRoot .ov-list-chapter-meta {
  font-size: 11px; color: var(--text-dim); white-space: nowrap;
}
#mapRoot .ov-list-topic-row {
  display: flex; align-items: center; gap: 10px;
  padding-top: 8px;
  padding-right: 12px;
  padding-bottom: 8px;
  padding-left: 52px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.1s;
}
#mapRoot .ov-list-topic-row:hover { background: var(--surface2); }
#mapRoot .ov-list-topic-row.mastery-strong      .list-mastery-bar { background: var(--mastery-strong); box-shadow: 0 0 4px rgba(159,114,248,0.4); }
#mapRoot .ov-list-topic-row.mastery-developing  .list-mastery-bar { background: var(--mastery-developing); }
#mapRoot .ov-list-topic-row.mastery-needs-work  .list-mastery-bar { background: var(--mastery-needs-work); }
#mapRoot .ov-list-topic-row.mastery-not-started .list-mastery-bar { background: var(--mastery-not-started); }
#mapRoot .ov-list-topic-row.no-cards            .list-mastery-bar { background: transparent; border: 1px dashed var(--mastery-no-cards); }
#mapRoot .ov-list-topic-row.frontier { box-shadow: inset 3px 0 0 var(--frontier-ring); }
#mapRoot .ov-list-topic-row.frontier .list-mastery-bar { background: var(--frontier-ring); box-shadow: 0 0 6px rgba(56,189,248,0.5); }

/* ═══════════════════════════════════════════════
   ACCESSIBILITY
═══════════════════════════════════════════════ */
#mapRoot .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

/* ═══════════════════════════════════════════════
   RESPONSIVE — MOBILE
═══════════════════════════════════════════════ */
@media (max-width: 680px) {
  #mapRoot { --detail-w: 100vw; }
  /* Top bar is cramped on phones — drop the redundant title + coverage badge,
     tighten gaps, and let the breadcrumb truncate so nothing overlaps/overflows. */
  #mapRoot #topbar { padding: 0 10px; gap: 8px; }
  #mapRoot #topbar-title { display: none; }
  #mapRoot #coverage-badge { display: none; }
  #mapRoot #topbar-left { gap: 8px; flex: 1 1 auto; min-width: 0; overflow: hidden; }
  #mapRoot #topbar-right { gap: 6px; }
  #mapRoot #legend-topbar-btn,
#mapRoot #scope-toggle-btn { padding-block: 5px; padding-inline: 8px; }
  #mapRoot #breadcrumb { min-width: 0; overflow: hidden; flex-wrap: nowrap; }
  #mapRoot #breadcrumb .crumb,
#mapRoot #breadcrumb .crumb-active,
#mapRoot #breadcrumb .crumb-link {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 38vw;
  }
  #mapRoot #overview { padding-top: 20px; padding-inline: 12px; padding-bottom: 80px; }
  #mapRoot .section-detail-inner { padding-top: 16px; padding-inline: 12px; padding-bottom: 80px; }
  #mapRoot #detail-panel {
    position: fixed; bottom: 0; left: 0; right: 0;
    width: 100%; height: 70vh; border-left: none;
    border-top: 1px solid var(--border);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    transform: translateY(0); transition: transform 0.25s cubic-bezier(0.4,0,0.2,1);
  }
  #mapRoot #detail-panel.hidden { transform: translateY(100%); width: 100%; height: 70vh; border: none; overflow: hidden; }
  /* FIX 1: Keep #main overflow:hidden on mobile too — the detail panel slides in as a fixed
     overlay, so #canvas doesn't need to grow. Removing overflow:visible preserves the
     bounded-scroller contract so the spine/list views scroll inside the iframe. */
  #mapRoot #main { overflow: hidden; }
  #mapRoot #canvas { padding-bottom: 72vh; }
  #mapRoot .branch-leaves-left { padding-right: 24px; }
  #mapRoot .branch-leaves-right { padding-left: 24px; }
  #mapRoot .leaf-node { max-width: 170px; }
  #mapRoot #legend { top: 60px; left: 8px; }
}

/*
 * session-preview.css — pre-cinema session preview / confirmation modal.
 * Presenter: pwa/session-preview.js. The expanded queue rows are REAL ribbon
 * cards (window.buildRibbonCard → .ribbon-wrap, styled by ribbon.css); this
 * file only styles the modal chrome + the swipe/aside wrapper around them.
 */

.sp-overlay{
  position:fixed; inset:0; z-index:var(--z-preview,270);
  background:var(--backdrop-preview, rgba(8,8,16,0.82));
  display:flex; align-items:center; justify-content:center; padding:18px;
  animation:spFade .15s ease; backdrop-filter:blur(3px);
}
@keyframes spFade{from{opacity:0}to{opacity:1}}
@keyframes spIn{from{transform:translateY(16px) scale(.98);opacity:0}to{transform:none;opacity:1}}
@keyframes spSlideUp{from{transform:translateY(100%)}to{transform:translateY(0)}}

.sp-card{
  position:relative; width:100%; max-width:432px; max-height:92dvh;
  overflow-y:auto; overscroll-behavior:contain;
  background:var(--surface-elevated); border:1px solid var(--border);
  border-radius:var(--radius-lg); box-shadow:var(--shadow-lg);
  animation:spIn var(--duration-md,200ms) var(--ease-out,cubic-bezier(.4,.05,.2,1));
}
.sp-handle{display:none}
@media(max-width:560px){
  .sp-overlay{padding:0; align-items:flex-end}
  .sp-card{max-width:none; border-radius:var(--radius-lg) var(--radius-lg) 0 0; border-bottom:none;
    animation:spSlideUp var(--duration-md,200ms) var(--ease-out);
    padding-bottom:calc(8px + env(safe-area-inset-bottom,0px))}
  .sp-handle{display:block; width:38px; height:4px; border-radius:var(--radius-2xs,2px);
    background:var(--border-strong); opacity:.55; margin:9px auto 2px}
}

/* header */
.sp-head{padding-top:18px;padding-inline:20px;padding-bottom:14px; border-bottom:1px solid var(--border)}
.sp-kicker{display:flex; align-items:center; gap:7px; font-size:var(--font-size-2xs,10px); font-weight:600;
  letter-spacing:.08em; text-transform:uppercase; color:var(--text-faint); margin-bottom:7px}
.sp-kicker .dot{width:6px; height:6px; border-radius:50%; background:var(--accent)}
.sp-kicker.remedial .dot{background:var(--grade-missed)}
.sp-title{font-size:var(--font-size-3xl,22px); font-weight:600; line-height:1.15; color:var(--text); letter-spacing:-.01em}
.sp-sub{margin-top:5px; font-size:var(--font-size-md,13px); color:var(--text-muted); line-height:1.45}
.sp-chips{display:flex; flex-wrap:wrap; gap:6px; margin-top:12px}
.sp-chip{display:inline-flex; align-items:center; gap:5px; font-size:var(--font-size-xs,11px); font-weight:500;
  padding-block:4px;
  padding-inline:9px; border-radius:var(--radius-pill,999px); background:var(--surface); border:1px solid var(--border); color:var(--text-muted)}
.sp-chip svg{width:12px; height:12px; opacity:.8}
.sp-chip.accent{background:var(--accent-soft); color:var(--accent-text); border-color:transparent}

/* count + est */
.sp-count{display:flex; align-items:baseline; gap:10px; padding-top:16px; padding-inline:20px; padding-bottom:4px}
.sp-count .big{font-size:44px; font-weight:600; line-height:1; letter-spacing:-.02em; color:var(--text); font-variant-numeric:tabular-nums}
.sp-count .unit{font-size:var(--font-size-lg,14px); color:var(--text-muted); font-weight:500}
.sp-count .time{margin-left:auto; text-align:right; font-size:var(--font-size-md,13px); color:var(--text-muted); font-weight:500}
.sp-count .time b{display:block; font-size:var(--font-size-xl,16px); color:var(--text); font-weight:600; font-variant-numeric:tabular-nums}

/* remedial miss-tag breakdown */
.sp-remedial{padding-top:4px;padding-inline:20px;padding-bottom:8px}
.sp-remedial .rrow{display:flex; align-items:center; gap:10px; padding:9px 0; border-top:1px solid var(--border)}
.sp-remedial .rrow:first-child{border-top:none}
.sp-remedial .rdot{width:8px; height:8px; border-radius:50%; background:var(--grade-missed); flex:none}
.sp-remedial .rlbl{font-size:var(--font-size-md,13px); color:var(--text); flex:1}
.sp-remedial .rn{font-size:var(--font-size-md,13px); font-weight:600; color:var(--text-muted); font-variant-numeric:tabular-nums}

/* bucket segmented */
.sp-bucket{padding-top:6px;padding-inline:20px;padding-bottom:8px}
.sp-bucket .lab{font-size:var(--font-size-2xs,10px); font-weight:600; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted); margin-bottom:8px}
.sp-seg{display:flex; gap:4px; padding:4px; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-md,10px)}
.sp-seg button{flex:1; font-family:inherit; font-size:var(--font-size-sm,12px); font-weight:560; padding-block:8px; padding-inline:6px; border:0;
  border-radius:var(--radius-sm,8px); background:transparent; color:var(--text-muted); cursor:pointer; transition:background .12s,color .12s; min-height:36px}
.sp-seg button.on{background:var(--surface-elevated); color:var(--text); box-shadow:var(--shadow-sm)}

/* adjust collapsible */
.sp-adjust{padding:0 20px}
.sp-adjust-head{display:flex; align-items:center; gap:8px; cursor:pointer; padding:12px 0; user-select:none; border-top:1px solid var(--border); min-height:44px}
.sp-adjust-head .ttl{font-size:var(--font-size-sm,12px); font-weight:600; letter-spacing:.04em; text-transform:uppercase; color:var(--text-muted)}
.sp-adjust-head .sum{font-size:var(--font-size-sm,12px); color:var(--text-faint)}
.sp-adjust-head .chev{margin-left:auto; display:flex; color:var(--text-faint); transition:transform var(--duration-md,200ms) var(--ease-out)}
.sp-adjust.open .sp-adjust-head .chev{transform:rotate(180deg)}
.sp-adjust-body{max-height:0; overflow:hidden; transition:max-height var(--duration-lg,280ms) var(--ease-out)}
.sp-adjust.open .sp-adjust-body{max-height:360px; padding-bottom:8px}
.sp-field{padding:11px 0}
.sp-field+.sp-field{border-top:1px solid var(--border)}
.sp-field-lab{display:flex; align-items:center; justify-content:space-between; font-size:var(--font-size-md,13px); font-weight:500; color:var(--text); margin-bottom:10px}
.sp-field-lab .val{font-size:var(--font-size-md,13px); font-weight:700; color:var(--accent-text); font-variant-numeric:tabular-nums}
.sp-range{width:100%; accent-color:var(--accent); height:24px; cursor:pointer}
.sp-mix{display:flex; gap:7px; flex-wrap:wrap}
.sp-mix button{font-family:inherit; display:inline-flex; align-items:center; gap:6px; font-size:var(--font-size-sm,12px); font-weight:500;
  padding-block:8px;
  padding-inline:12px; border-radius:var(--radius-pill,999px); border:1px solid var(--border-strong); background:var(--surface); color:var(--text-muted); cursor:pointer; min-height:36px}
.sp-mix button .sw{width:9px; height:9px; border-radius:3px}
.sp-mix button.on{background:var(--accent-soft); color:var(--accent-text); border-color:transparent}
.sp-mix button.off{opacity:.5; text-decoration:line-through}
.sp-order{display:flex; gap:5px; flex-wrap:wrap}
.sp-order button{font-family:inherit; font-size:var(--font-size-sm,12px); font-weight:500; padding-block:8px; padding-inline:12px; border-radius:var(--radius-pill,999px);
  border:1px solid var(--border-strong); background:var(--surface); color:var(--text-muted); cursor:pointer; min-height:36px}
.sp-order button.on{background:var(--accent); color:var(--accent-on); border-color:transparent}

/* queue ribbon (filmstrip = the breakdown bar) + expandable list */
.sp-queue{padding-top:2px;padding-inline:20px;padding-bottom:14px}
.sp-queue-head{display:flex; align-items:center; gap:8px; cursor:pointer; padding:11px 0; user-select:none; min-height:44px}
.sp-queue-head .ttl{font-size:var(--font-size-sm,12px); font-weight:600; letter-spacing:.04em; text-transform:uppercase; color:var(--text-muted)}
.sp-queue-head .cnt{font-size:var(--font-size-sm,12px); color:var(--text-faint)}
.sp-queue-head .chev{margin-left:auto; display:flex; color:var(--text-faint); transition:transform var(--duration-md,200ms) var(--ease-out)}
.sp-queue.open .sp-queue-head .chev{transform:rotate(180deg)}
.sp-ribbon{display:flex; gap:2px; align-items:stretch; height:22px; cursor:pointer}
.sp-ribbon i{flex:1 1 0; min-width:3px; opacity:.92}
.sp-ribbon i.t-recall{background:var(--type-recall)} .sp-ribbon i.t-saq{background:var(--type-saq)}
.sp-ribbon i.t-pharma{background:var(--type-pharma)} .sp-ribbon i.t-axiom{background:var(--type-axiom)}
.sp-legend{display:flex; flex-wrap:wrap; gap:13px; margin-top:12px}
.sp-leg{display:flex; align-items:center; gap:7px; font-size:var(--font-size-sm,12px)}
.sp-leg .sw{width:9px; height:9px; border-radius:3px}
.sp-leg .lbl{color:var(--text-muted)} .sp-leg .n{font-weight:600; color:var(--text); font-variant-numeric:tabular-nums}
.sp-leg .sw.t-recall{background:var(--type-recall)} .sp-leg .sw.t-saq{background:var(--type-saq)}
.sp-leg .sw.t-pharma{background:var(--type-pharma)} .sp-leg .sw.t-axiom{background:var(--type-axiom)}
.sp-qlist{max-height:0; overflow:hidden; transition:max-height var(--duration-lg,280ms) var(--ease-out)}
.sp-queue.open .sp-qlist{max-height:248px; overflow-y:auto; overscroll-behavior:contain; margin-top:10px}
.sp-qlist .ribbon-list{display:flex; flex-direction:column; gap:4px}

/* swipe-to-set-aside wrapper around each real ribbon card + keyboard × */
.rbn-swipe{position:relative; overflow:hidden; border-radius:8px}
.rbn-swipe-bg{position:absolute; inset:0; background:var(--grade-missed); display:flex; align-items:center; justify-content:flex-end;
  padding-right:16px; color:var(--white); font-size:var(--font-size-sm,12px); font-weight:600; letter-spacing:.02em}
.rbn-swipe .ribbon-wrap{position:relative; touch-action:pan-y; will-change:transform}
.rbn-swipe .rbn-band{padding-right:34px}
.rbn-aside-btn{position:absolute; top:0; right:0; width:34px; height:34px; display:flex; align-items:center; justify-content:center;
  background:transparent; border:0; cursor:pointer; z-index:2; border-radius:0 8px 0 8px;
  color:color-mix(in srgb, var(--rbn-tint-color, var(--border-strong)) 60%, var(--text-faint))}
.rbn-aside-btn:hover{color:var(--grade-missed)}
.rbn-aside-btn:focus-visible{outline:2px solid var(--accent); outline-offset:-2px}
.rbn-aside-btn svg{width:15px; height:15px}

/* set-aside (collapsible) */
.sp-aside{padding:0 20px}
.sp-aside-wrap{border-top:1px solid var(--border)}
.sp-aside-head{font-size:var(--font-size-2xs,10px); font-weight:600; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted);
  display:flex; align-items:center; gap:8px; padding:11px 0; cursor:pointer; user-select:none; min-height:44px}
.sp-aside-head .chev{margin-left:auto; display:flex; color:var(--text-faint); transition:transform var(--duration-md,200ms) var(--ease-out)}
.sp-aside-wrap.open .sp-aside-head .chev{transform:rotate(180deg)}
.sp-aside-head .pill{background:var(--grade-missed); color:var(--white); border-radius:var(--radius-pill,999px); padding-block:1px; padding-inline:7px; font-size:9px; font-weight:700}
.sp-aside-body{max-height:0; overflow:hidden; transition:max-height var(--duration-lg,280ms) var(--ease-out)}
.sp-aside-wrap.open .sp-aside-body{max-height:260px; overflow-y:auto; overscroll-behavior:contain; padding-bottom:10px}
.aside-row{display:flex; align-items:center; gap:10px; padding-block:8px; padding-inline:11px; border:1px dashed var(--border-strong); border-radius:var(--radius-sm,8px); margin-bottom:6px; background:var(--surface)}
.aside-row .at{width:17px; height:17px; border-radius:4px; display:flex; align-items:center; justify-content:center; font-size:9px; font-weight:700; color:var(--white); flex:none}
.aside-row .att{flex:1; font-size:var(--font-size-md,13px); color:var(--text-muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.aside-row .areq{font-family:inherit; font-size:var(--font-size-xs,11px); font-weight:600; color:var(--accent-text); background:transparent;
  border:1px solid var(--border-strong); border-radius:var(--radius-pill,999px); padding-block:6px; padding-inline:11px; cursor:pointer; white-space:nowrap; min-height:32px}

/* footer */
.sp-foot{padding:14px 20px calc(18px + env(safe-area-inset-bottom,0px)); border-top:1px solid var(--border); background:var(--surface-elevated); position:sticky; bottom:0}
.sp-empty{font-size:var(--font-size-sm,12px); color:var(--grade-missed-label, var(--grade-missed)); text-align:center; padding:2px 0 10px; font-weight:500}
.sp-actions{display:flex; gap:10px}
.sp-btn{flex:1; font-family:inherit; font-size:var(--font-size-lg,14px); font-weight:560; padding-block:13px; padding-inline:16px; border-radius:var(--radius-md,10px);
  cursor:pointer; border:1px solid transparent; transition:transform .08s var(--ease-out), background .12s; min-height:46px}
.sp-btn:active{transform:scale(.97)}
.sp-btn--cancel{flex:0 0 auto; min-width:96px; background:transparent; color:var(--text-muted); border-color:var(--border-strong)}
.sp-btn--go{background:var(--accent); color:var(--accent-on)}
.sp-btn--go.remedial{background:var(--grade-missed); color:var(--white)}
.sp-btn--go:disabled{opacity:.5; cursor:not-allowed}

/* skeleton (covers async fetch latency) */
.sp-skel{padding-top:18px;padding-inline:20px;padding-bottom:8px}
@keyframes spShimmer{0%{opacity:.45}50%{opacity:.85}100%{opacity:.45}}
.sp-sk{background:var(--surface); border-radius:7px; animation:spShimmer 1.3s ease-in-out infinite}
.sp-sk.k-kicker{height:11px; width:120px; margin-bottom:11px}
.sp-sk.k-title{height:26px; width:74%; margin-bottom:9px}
.sp-sk.k-sub{height:13px; width:54%; margin-bottom:18px}
.sp-sk.k-big{height:44px; width:150px; margin-bottom:16px}
.sp-sk.k-bar{height:9px; width:100%; margin-bottom:14px}
.sp-sk.k-leg{height:13px; width:40%; margin-bottom:9px}
.sp-skel-note{display:flex; align-items:center; gap:9px; padding-top:6px; padding-inline:20px; padding-bottom:16px; color:var(--text-faint); font-size:var(--font-size-sm,12px)}
.sp-spin{width:15px; height:15px; border:2px solid var(--border-strong); border-top-color:var(--accent); border-radius:50%; animation:spSpin .7s linear infinite}
@keyframes spSpin{to{transform:rotate(360deg)}}

@media (prefers-reduced-motion: reduce){
  .sp-overlay,.sp-card{animation:none !important}
  .sp-adjust-body,.sp-qlist,.sp-aside-body,.sp-queue-head .chev,.sp-adjust-head .chev,.sp-aside-head .chev{transition-duration:.01ms !important}
  .sp-sk,.sp-spin{animation:none !important}
}

/* =====================================================================
   the-open.css — "The Open" in-flow front-door (in-flow section + carousel).
   Reworked from a modal bottom-sheet to an in-flow section inserted before
   #stageHero in #tabpanel-today. Design source: MOCKUPS/the-open-inflow.html.

   Theming: The Open is a deliberately calm, dark "front door" regardless of
   the app's light/dark theme — scoped palette is on #theOpenSection (.the-open).
   All selectors are namespaced under .the-open / #theOpenSection so nothing
   leaks to the rest of the app.
   ===================================================================== */

/* ── Scoped palette + spacing tokens ────────────────────────────────────────
   NO hex literals below this block — use rgb() or var() exclusively.
   --to-headerH / --to-tabbarH are set on :root by JS at mount time.          */
#theOpenSection,
.the-open {
  --to-accent:rgb(21 117 112); --to-accent-pressed:rgb(41 137 133); --to-accent-soft:rgb(25 62 60); --to-accent-bright:rgb(57 163 156);
  --to-bg:rgb(13 13 19); --to-surface:rgb(24 24 32); --to-surface-2:rgb(32 32 44); --to-surface-3:rgb(38 38 51);
  --to-border:rgb(39 39 51); --to-border-strong:rgb(57 57 74);
  --to-honey:var(--nemesis-gold, rgb(245 194 107)); --to-crimson:rgb(198 72 91);
  --to-fsrs-learn:var(--to-honey); --to-fsrs-mature:rgb(93 217 140); --to-fsrs-new:rgb(230 210 74); --to-fsrs-over:var(--fc-badge-missed, rgb(240 90 80));
  --to-text:rgb(238 240 248); --to-text-muted:rgb(184 185 200); --to-text-faint:rgb(126 126 162); --to-text-dim:rgb(150 150 180);
  --to-teal:rgb(127 227 221); --to-ink:rgb(21 21 29);
  --to-strip-pad:11px 13px; --to-strip-margin:12px 0 14px; --to-aside-pad:20px 22px 18px;
  --to-ohead-pad:4px 2px 14px; --to-page-pad:2px 2px 6px; --to-ccdone-pad:11px 6px;
  --to-serif: var(--font-display, ui-serif,"Iowan Old Style",Palatino,Georgia,serif);
  --to-sans: var(--font-sans, -apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",system-ui,sans-serif);
  --to-fs-2xs:10px; --to-fs-xs:11px; --to-fs-sm:12px; --to-fs-md:13px; --to-fs-lg:14px; --to-fs-xl:16px;
  --to-r:14px;
  /* fallback heights if JS hasn't fired yet */
  --to-headerH: 56px;
  --to-tabbarH: 72px;
}
#theOpenSection *,
.the-open * { box-sizing:border-box; }

/* ── Root: Y-snap (Today tab, expanded only) ────────────────────────────────
   body.to-snap is added/removed by JS: only while expanded AND Today is active.
   scroll-padding-top clears the fixed header.                                 */
body.to-snap {
  scroll-snap-type: y mandatory;
  scroll-padding-top: var(--to-headerH);
}
/* Hero gets snap-align only while snap mode is active (CSS-only; hero DOM untouched). */
body.to-snap #stageHero {
  scroll-snap-align: start;
}

/* ── Section root ────────────────────────────────────────────────────────────
   The section is always in the DOM when Today is rendered (flag on). In
   collapsed state it is just the strip (height:auto). In expanded state it
   becomes a full snap-page.                                                   */
#theOpenSection {
  padding: 0 18px;
  font-family: var(--to-sans);
  color: var(--to-text);
  scroll-snap-align: start;
  /* diurnal ::before wash — gradient only, no rendered art */
  position: relative;
}
/* Diurnal light wash */
#theOpenSection::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  transition: background 1.4s ease;
  z-index: 0;
}
#theOpenSection.dawn::before { background: radial-gradient(130% 48% at 50% 0%, rgba(245,194,107,.12), transparent 56%); }
#theOpenSection.day::before  { background: radial-gradient(130% 48% at 50% 0%, rgba(127,227,221,.05), transparent 56%); }
#theOpenSection.dusk::before { background: radial-gradient(130% 55% at 50% 0%, rgba(101,104,214,.14), transparent 60%); }
#theOpenSection > * { position: relative; z-index: 1; }

/* Expanded: full snap-page height so the section fills one viewport slot.
   SOLID dark panel (only when expanded — the collapsed strip stays a contained
   pill on the page bg) so all section-level text has a dark backdrop in BOTH
   light and dark mode (WCAG 1.4.3). The bottom edge fades to transparent so the
   panel dissolves into the Today surface below during the snap: invisible in
   dark mode (reveals near-identical dark page), a soft dark→cream blend in light
   mode. The fade sits in the bottom padding — content (dots) clears it.        */
#theOpenSection.to-expanded {
  min-height: calc(100dvh - var(--to-headerH) - var(--to-tabbarH));
  display: flex;
  flex-direction: column;
  padding-top: 12px;
  padding-bottom: 48px;
  background: linear-gradient(180deg, var(--to-bg), var(--to-bg) calc(100% - 52px), transparent);
}

/* ── Collapsed strip ─────────────────────────────────────────────────────────
   Visible when NOT expanded. Hidden when expanded.                            */
.the-open .to-strip {
  margin: var(--to-strip-margin);
  display: flex;
  align-items: center;
  gap: 11px;
  padding: var(--to-strip-pad);
  cursor: pointer;
  border: 1px solid var(--to-border);
  border-radius: 13px;
  position: relative;
  overflow: hidden;
  background: linear-gradient(180deg, rgb(27 27 37), rgb(20 16 25));
  transition: border-color .2s, transform .15s;
  -webkit-tap-highlight-color: transparent;
}
.the-open .to-strip::after {
  content: "";
  position: absolute;
  top: -50%; right: -10%;
  width: 45%; height: 200%;
  background: radial-gradient(closest-side, rgba(245,194,107,.14), transparent 70%);
  filter: blur(6px);
  animation: to-breathe-strip 9s ease-in-out infinite;
  pointer-events: none;
}
.the-open .to-strip:hover { border-color: var(--to-border-strong); }
.the-open .to-strip:active { transform: scale(.992); }

.the-open .to-strip .to-ph { display: flex; align-items: center; gap: 6px; font: 600 var(--to-fs-sm)/1 var(--to-sans); white-space: nowrap; }
.the-open .to-strip .to-ph .sp { color: var(--to-crimson); }
.the-open .to-strip .to-ph .sub { color: var(--to-text-faint); font-weight: 400; font-size: var(--to-fs-xs); }
.the-open .to-strip .to-sep { width: 1px; height: 16px; background: var(--to-border); }
.the-open .to-strip .to-minibar { display: flex; gap: 2px; }
.the-open .to-strip .to-minibar i { width: 13px; height: 5px; border-radius: 3px; }
.the-open .to-strip .to-due { font: 600 var(--to-fs-xs)/1 var(--to-sans); color: var(--to-text-muted); }
.the-open .to-strip .to-as { margin-left: auto; display: flex; align-items: center; gap: 6px; font: 600 var(--to-fs-xs)/1 var(--to-sans); color: var(--to-honey); white-space: nowrap; position: relative; z-index: 1; }
.the-open .to-strip .to-as .twinkle { animation: to-twinkle 4s ease-in-out infinite; filter: drop-shadow(0 0 6px var(--to-honey)); }
.the-open .to-strip .to-chev { color: var(--to-text-dim); font-size: 12px; }

/* Hide strip when expanded */
.the-open.to-expanded .to-strip { display: none; }

/* ── Expanded body ────────────────────────────────────────────────────────────
   Hidden when collapsed; shown (flex) when expanded.                          */
.the-open .to-open-full {
  display: none;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
.the-open.to-expanded .to-open-full {
  display: flex;
  animation: to-rise .5s cubic-bezier(.22,1,.36,1);
}

/* ── Orientation header ────────────────────────────────────────────────────── */
.the-open .to-ohead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: var(--to-ohead-pad);
}
.the-open .to-ohead .to-orient { flex: 1; min-width: 0; }
.the-open .to-node { font: 300 23px/1.2 var(--to-serif); color: rgb(255 255 255); }
.the-open .to-meta { font: 500 var(--to-fs-xs)/1 var(--to-sans); color: var(--to-text-faint); margin-top: 7px; }

.the-open .to-collapse {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1px solid var(--to-border);
  background: var(--to-surface-2);
  color: var(--to-text-faint);
  cursor: pointer;
  display: grid;
  place-items: center;
  font-family: inherit;
}
.the-open .to-collapse:hover { color: var(--to-text); }

/* ── Progress bar ──────────────────────────────────────────────────────────── */
.the-open .to-prog {
  height: 3px;
  border-radius: 2px;
  background: var(--to-surface-3);
  margin: 0 2px 12px;
  overflow: hidden;
}
.the-open .to-prog i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--to-accent), var(--to-accent-bright));
  transition: width 1s cubic-bezier(.22,1,.36,1);
}

/* ── Carousel (horizontal snap) ────────────────────────────────────────────── */
.the-open .to-carousel {
  flex: 1;
  min-height: 0;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  gap: 0;
}
.the-open .to-carousel::-webkit-scrollbar { height: 0; }

.the-open .to-page {
  flex: 0 0 100%;
  scroll-snap-align: start;
  overflow-y: auto;
  padding: var(--to-page-pad);
  display: flex;
  flex-direction: column;
  gap: 13px;
}
.the-open .to-page::-webkit-scrollbar { width: 0; }

/* ── Dots ──────────────────────────────────────────────────────────────────── */
.the-open .to-dots {
  display: flex;
  gap: 7px;
  justify-content: center;
  padding: 12px 0 4px;
}
/* Dots are real buttons (WCAG 2.5.7 non-drag paging + 2.5.8 24px target). The
   visual dot is the inner <i>; the button provides the hit area. */
.the-open .to-dots button {
  width: 24px; height: 24px;
  display: grid;
  place-items: center;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.the-open .to-dots button i {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--to-surface-3);
  transition: background .25s, width .25s;
  pointer-events: none;
}
.the-open .to-dots button.on i {
  background: var(--to-honey);
  width: 18px;
  border-radius: 3px;
}

/* ── Aside ─────────────────────────────────────────────────────────────────── */
.the-open .to-aside {
  position: relative;
  border: 1px solid var(--to-border);
  border-radius: 18px;
  padding: var(--to-aside-pad);
  overflow: hidden;
  cursor: pointer;
  background: linear-gradient(180deg, rgb(30 27 22), rgb(23 21 28));
}
/* slow breathing glow — calm, reflective; more prominent per mockup */
.the-open .to-aside::before {
  content: "";
  position: absolute;
  top: -65%; right: -26%;
  width: 88%; height: 215%;
  background: radial-gradient(closest-side, rgba(245,194,107,.26), transparent 72%);
  animation: to-breathe-aside 8.5s ease-in-out infinite;
  pointer-events: none;
}
.the-open .to-aside::after {
  content: "";
  position: absolute;
  bottom: -55%; left: -22%;
  width: 70%; height: 180%;
  background: radial-gradient(closest-side, rgba(245,194,107,.13), transparent 70%);
  animation: to-breathe-aside 11s ease-in-out infinite reverse;
  pointer-events: none;
}
.the-open .to-aside > * { position: relative; z-index: 1; }

.the-open .to-aside .to-k {
  display: flex;
  align-items: center;
  gap: 8px;
  font: 600 var(--to-fs-2xs)/1 var(--to-sans);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--to-honey);
  margin-bottom: 12px;
}
.the-open .to-aside .to-k .dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--to-honey);
  box-shadow: 0 0 10px var(--to-honey);
}
.the-open .to-aside .to-k .sec { color: var(--to-text-faint); }

.the-open .to-aside .to-body {
  position: relative;
  font: 300 19px/1.45 var(--to-serif);
  color: rgb(243 244 251);
  /* Reserve median aside height so synchronous first-paint inject (flag_open_no_anim)
     doesn't shift layout (CLS). ~4 lines at 1.45 line-height. */
  min-height: 5.8em;
  transition: opacity .4s, transform .4s;
}
.the-open .to-aside .to-body b { font-weight: 600; color: rgb(255 255 255); }

.the-open .to-aside .to-why {
  position: relative;
  font: 400 var(--to-fs-md)/1.6 var(--to-sans);
  color: var(--to-text-muted);
  max-height: 0; opacity: 0; overflow: hidden;
  transition: max-height .55s, opacity .4s, margin .4s;
}
.the-open .to-aside.open .to-why { max-height: 900px; opacity: 1; margin-top: 13px; }
.the-open .to-aside .to-why .cite { display: block; margin-top: 9px; color: var(--to-text-faint); font-style: italic; font-size: var(--to-fs-xs); }

.the-open .to-aside .to-prov {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  font: 500 var(--to-fs-2xs)/1.3 var(--to-sans);
  letter-spacing: .04em;
  color: var(--to-text-faint);
  max-height: 0; opacity: 0; overflow: hidden;
  transition: max-height .55s, opacity .4s, margin .4s;
}
.the-open .to-aside.open .to-prov { max-height: 40px; opacity: 1; margin-top: 12px; }
.the-open .to-aside .to-prov .spk { color: var(--to-honey); font-size: 11px; }

.the-open .to-aside.empty { cursor: default; }
.the-open .to-aside.empty .to-body { color: var(--to-text-muted); font-size: 17px; }

/* ── Begin button (fresh) ──────────────────────────────────────────────────── */
.the-open .to-begin {
  width: 100%;
  border: none;
  border-radius: 15px;
  padding: 16px;
  cursor: pointer;
  color: rgb(4 32 29);
  text-align: left;
  font: 700 16px/1.2 var(--to-sans);
  /* bottom stop lightened (rgb(50 155 147)) so the dark ink clears 4.5:1 across
     the whole gradient — WCAG 1.4.3 (was var(--to-accent), only 3.1:1 at the dark end). */
  background: linear-gradient(180deg, var(--to-accent-bright), rgb(50 155 147));
  box-shadow: 0 12px 30px -10px rgba(21,117,112,.7);
  font-family: inherit;
}
.the-open .to-begin .s {
  display: block;
  font: 500 var(--to-fs-xs)/1.3 var(--to-sans);
  color: rgba(4,32,29,.78);
  margin-top: 5px;
}

/* Hide begin when post-session; show closecard */
.the-open .to-begin { /* shown by default */ }
.the-open.is-post .to-begin { display: none; }
.the-open .to-closecard { display: none; }
.the-open.is-post .to-closecard { display: flex; }

/* ── Close card (post-session) ─────────────────────────────────────────────── */
.the-open .to-closecard {
  flex-direction: column;
  gap: 12px;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--to-border);
  border-radius: 16px;
  padding: 18px;
  background: linear-gradient(180deg, rgb(26 30 27), rgb(21 21 28));
}
.the-open .to-closecard::before {
  content: "";
  position: absolute;
  top: -50%; right: -20%;
  width: 55%; height: 180%;
  background: radial-gradient(closest-side, rgba(93,217,140,.13), transparent 70%);
  pointer-events: none;
}
.the-open .to-cc-top {
  display: flex;
  align-items: center;
  gap: 14px;
  position: relative;
}
.the-open .to-cc-textcol {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  position: relative;
}
.the-open .to-cc-check {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  position: relative;
  color: var(--to-fsrs-mature);
  background: radial-gradient(circle at 38% 32%, rgba(93,217,140,.30), rgba(93,217,140,.06));
  box-shadow: 0 0 0 1px rgba(93,217,140,.22), 0 0 24px -4px rgba(93,217,140,.5);
}
.the-open .to-cc-h {
  position: relative;
  font: 300 18px/1.35 var(--to-serif);
  color: rgb(243 244 251);
}
.the-open .to-cc-facts {
  position: relative;
  font: 500 var(--to-fs-md)/1.5 var(--to-sans);
  color: var(--to-text-muted);
}
.the-open .to-cc-facts b { color: var(--to-fsrs-mature); font-weight: 700; }
.the-open .to-cc-cta {
  position: relative;
  display: flex;
  gap: 9px;
  align-items: center;
}
/* Keep going = primary (right); Done for now = quiet text (left) */
.the-open .to-cc-keep {
  flex: 1;
  border: none;
  border-radius: 11px;
  padding: 13px;
  font: 700 14px/1 var(--to-sans);
  color: rgb(4 32 29);
  cursor: pointer;
  background: linear-gradient(180deg, var(--to-accent-bright), rgb(50 155 147));
  box-shadow: 0 10px 24px -10px rgba(21,117,112,.7);
  font-family: inherit;
}
.the-open .to-cc-done {
  flex: 0 0 auto;
  border: none;
  background: none;
  padding: var(--to-ccdone-pad);
  font: 600 var(--to-fs-sm)/1 var(--to-sans);
  color: var(--to-text-dim);
  cursor: pointer;
  font-family: inherit;
}
.the-open .to-cc-done:hover { color: var(--to-text-faint); }

/* ── Episode (podcast) ─────────────────────────────────────────────────────── */
.the-open .to-ep {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--to-border);
  border-radius: var(--to-r);
  padding: 12px;
  background: var(--to-surface);
}
.the-open .to-ep .art {
  width: 42px; height: 42px;
  border-radius: 9px;
  flex: 0 0 auto;
  background: radial-gradient(circle at 35% 30%, var(--to-crimson), rgb(60 18 26));
  position: relative;
  overflow: hidden;
}
.the-open .to-ep .art .c {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font: 700 13px/1 var(--to-serif);
  color: rgba(255,255,255,.9);
}
.the-open .to-ep .m { flex: 1; min-width: 0; }
.the-open .to-ep .m .t { font: 600 var(--to-fs-md)/1.3 var(--to-sans); color: var(--to-text); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.the-open .to-ep .m .s { font: 400 var(--to-fs-xs)/1 var(--to-sans); color: var(--to-text-dim); margin-top: 4px; }
.the-open .to-ep .pl {
  width: 30px; height: 30px;
  border-radius: 50%;
  border: none;
  background: var(--to-accent-soft);
  color: var(--to-teal);
  display: grid;
  place-items: center;
  cursor: pointer;
  font-family: inherit;
  font-size: 12px;
  padding-left: 2px;
}

/* ── Page 2: FSRS shape grid ───────────────────────────────────────────────── */
.the-open .to-grid2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 9px;
}
.the-open .to-tile {
  border: 1px solid var(--to-border);
  border-radius: 12px;
  padding: 13px;
  background: var(--to-surface);
}
.the-open .to-tile .n { font: 700 22px/1 var(--to-serif); }
.the-open .to-tile .l { font: 600 var(--to-fs-2xs)/1 var(--to-sans); letter-spacing: .04em; text-transform: uppercase; color: var(--to-text-dim); margin-top: 6px; }
.the-open .to-tile-new .n  { color: var(--to-fsrs-new); }
.the-open .to-tile-learn .n { color: var(--to-fsrs-learn); }
.the-open .to-tile-mat .n  { color: var(--to-fsrs-mature); }
.the-open .to-tile-over .n { color: var(--to-fsrs-over); }

/* ── Retention panel ───────────────────────────────────────────────────────── */
.the-open .to-ret {
  border: 1px solid var(--to-border);
  border-radius: var(--to-r);
  background: var(--to-surface);
  padding: 15px;
}
.the-open .to-ret .rh {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 11px;
}
.the-open .to-ret .rh .l {
  font: 600 var(--to-fs-2xs)/1 var(--to-sans);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--to-text-dim);
}
.the-open .to-ret .bar {
  display: flex;
  height: 28px;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--to-border);
}
.the-open .to-ret .bar i { height: 100%; width: 0; transition: width 1.1s cubic-bezier(.22,1,.36,1); }
.the-open .to-ret .s-ms { background: var(--to-fsrs-mature); }
.the-open .to-ret .s-hn { background: rgb(58 143 115); }
.the-open .to-ret .s-hz { background: var(--to-fsrs-learn); }
.the-open .to-ret .s-nw { background: rgba(240,90,80,.5); }
.the-open .to-ret .s-unt { background: var(--to-surface-3); }
.the-open .to-ret .rtrend { font: 600 var(--to-fs-xs)/1.3 var(--to-sans); color: var(--to-fsrs-mature); margin-top: 10px; }
.the-open .to-ret .cap { font: 400 var(--to-fs-xs)/1.5 var(--to-sans); color: var(--to-text-faint); margin-top: 7px; }
.the-open .to-ret .cap b { color: var(--to-fsrs-mature); }
.the-open .to-ret .ret-cont { font: 600 var(--to-fs-xs)/1.4 var(--to-sans); color: var(--to-text-faint); margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--to-border); }
.the-open .to-ret .ret-cont span { color: var(--to-fsrs-mature); }

/* ── Nudge (highest-yield / lowest-coverage) ───────────────────────────────── */
.the-open .to-nudge {
  display: flex;
  gap: 11px;
  align-items: center;
  border: 1px solid var(--to-border);
  border-radius: var(--to-r);
  padding: 13px;
  background: var(--to-surface);
}
.the-open .to-nudge .orb {
  width: 30px; height: 30px;
  border-radius: 50%;
  flex: 0 0 auto;
  background: radial-gradient(circle at 35% 30%, rgb(58 111 107), rgb(20 48 46));
  box-shadow: 0 0 16px -4px rgba(21,117,112,.6);
}
.the-open .to-nudge .t { font: 500 var(--to-fs-md)/1.3 var(--to-sans); color: var(--to-text); }
.the-open .to-nudge .t b { font-weight: 700; }
.the-open .to-nudge .s { font: 400 var(--to-fs-xs)/1.3 var(--to-sans); color: var(--to-text-faint); margin-top: 3px; }
.the-open .to-nudge .tx { flex: 1; min-width: 0; }

/* ── Keyframes ─────────────────────────────────────────────────────────────── */
@keyframes to-twinkle { 0%,100%{ opacity:.55; } 50%{ opacity:1; } }
@keyframes to-breathe-strip { 0%,100%{ opacity:.5; transform:translateY(0); } 50%{ opacity:1; transform:translateY(-8px); } }
@keyframes to-breathe-aside { 0%,100%{ opacity:.55; transform:scale(.94); } 50%{ opacity:1; transform:scale(1.16); } }
@keyframes to-rise { from{ opacity:0; transform:translateY(10px); } to{ opacity:1; transform:none; } }

/* ── Press micro-interactions (match the app's action buttons) ─────────────── */
.the-open .to-begin,
.the-open .to-cc-keep {
  transition: transform var(--duration-sm, .15s), filter var(--duration-sm, .15s), box-shadow var(--duration-sm, .15s);
}
.the-open .to-begin:hover,
.the-open .to-cc-keep:hover { filter: brightness(1.05); }
.the-open .to-begin:active,
.the-open .to-cc-keep:active { transform: scale(.98); }
.the-open .to-collapse,
.the-open .to-cc-done,
.the-open .to-ep .pl,
.the-open .to-dots button {
  transition: transform var(--duration-sm, .15s), color var(--duration-sm, .15s), background var(--duration-sm, .15s), border-color var(--duration-sm, .15s);
}
.the-open .to-collapse:active,
.the-open .to-cc-done:active,
.the-open .to-ep .pl:active,
.the-open .to-dots button:active { transform: scale(.92); }

/* ── Focus visibility (WCAG 2.4.7) ─────────────────────────────────────────── */
.the-open .to-strip:focus-visible,
.the-open .to-collapse:focus-visible,
.the-open .to-aside:focus-visible,
.the-open .to-begin:focus-visible,
.the-open .to-cc-keep:focus-visible,
.the-open .to-cc-done:focus-visible,
.the-open .to-ep .pl:focus-visible,
.the-open .to-dots button:focus-visible {
  outline: 2px solid var(--to-teal);
  outline-offset: 2px;
}

/* ── Reduced motion ────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .the-open.to-expanded .to-open-full { animation: none; }
  .the-open .to-aside::before,
  .the-open .to-aside::after,
  .the-open .to-strip::after,
  .the-open .to-strip .to-as .twinkle { animation: none; }
  .the-open .to-prog i,
  .the-open .to-ret .bar i { transition: none; }
}

/* pwa/podcast/podcast.css — in-app podcast player (DEC-030).
 * Dusk tokens only (stylelint color-no-hex). Loaded before motion.css in _manifest.js. */

.podc-root { --podc-dock-bottom: 64px; }
/* Fully clear the bar when dismissed. translateY(160%) only moved it ~96px, but on a notched
   phone the bar sits var(--podc-dock-bottom)+safe-area up and is 60px tall, so most of it stayed
   visible as a "ghost" over the nav. opacity:0 + pointer-events:none guarantee it is invisible
   and untappable regardless of the slide distance. */
.podc-root--hidden .podc-mini { transform: translateY(140%); opacity: 0; pointer-events: none; }

/* generative artwork host */
.podc-art { position: relative; overflow: hidden; background: var(--bg-sunken); border-radius: var(--radius); isolation: isolate; }
.podc-art canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.podc-art-code { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-weight: 900; letter-spacing: -.04em; color: rgba(255,255,255,.92); mix-blend-mode: overlay; z-index: 2; font-size: 30px; }
.podc-art-glyph { position: absolute; bottom: 8%; right: 7%; font-size: 11px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: rgba(255,255,255,.55); z-index: 2; }
.podc-hero-art .podc-art-code { font-size: 60px; }

/* tier pills */
.podc-tier { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: var(--radius-pill); }
.podc-tier-red { background: color-mix(in srgb, var(--red) 18%, transparent); color: var(--grade-missed-label); }
.podc-tier-amber { background: color-mix(in srgb, var(--amber) 20%, transparent); color: var(--amber); }
.podc-tier-green { background: color-mix(in srgb, var(--green) 18%, transparent); color: var(--grade-honed-label); }
.podc-node { font-size: 11px; font-weight: 700; padding: 3px 8px; border-radius: var(--radius-sm); background: var(--surface-bright); color: var(--text-muted); }

/* ---------------- docked mini-player ---------------- */
.podc-mini { position: fixed; left: 8px; right: 8px; bottom: calc(var(--podc-dock-bottom) + env(safe-area-inset-bottom, 0px)); height: 60px; z-index: 1400;
  background: color-mix(in srgb, var(--surface-elevated) 92%, transparent); backdrop-filter: blur(20px) saturate(1.4); -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border: 1px solid var(--border-strong); border-radius: 14px; box-shadow: 0 8px 28px -8px rgba(0,0,0,.6);
  display: flex; align-items: center; gap: 11px; padding: 0 8px; cursor: pointer; transform: translateY(0); transition: transform .34s var(--ease-spring), opacity .25s var(--ease-out); }
.podc-m-art { width: 44px; height: 44px; border-radius: 9px; flex: none; }
.podc-m-body { flex: 1; min-width: 0; min-height: 24px; background: transparent; border: 0; padding: 0; margin: 0; font: inherit; text-align: left; color: inherit; cursor: pointer; } /* WCAG 2.5.8: empty spans → 0px without this */
.podc-m-title { display: block; font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.podc-m-sub { display: block; font-size: 11px; color: var(--text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
.podc-m-btn { flex: none; width: 40px; height: 40px; border: 0; background: transparent; color: var(--text); display: grid; place-items: center; cursor: pointer; }
.podc-m-btn svg { width: 22px; height: 22px; fill: currentColor; }
.podc-m-progress { position: absolute; left: 10px; right: 10px; top: 0; height: 2px; background: var(--border); border-radius: 2px; overflow: hidden; }
.podc-m-progress i { display: block; height: 100%; width: 0; background: var(--accent); }

/* ---------------- full-screen hero ---------------- */
.podc-hero { position: fixed; inset: 0; z-index: 1500; background: var(--bg); display: flex; flex-direction: column; overflow: hidden;
  transform: translateY(100%); transition: transform .4s var(--ease-spring); }
.podc-hero.podc-show { transform: translateY(0); }
.podc-hero-bg { position: absolute; inset: 0; z-index: 0; opacity: .5; filter: blur(48px) saturate(1.3); transform: scale(1.4); border-radius: 0; }
.podc-hero-scroll { position: relative; z-index: 1; flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 0 22px calc(40px + env(safe-area-inset-bottom, 0px)); -webkit-overflow-scrolling: touch; }
.podc-hero-top { position: sticky; top: 0; z-index: 3; display: flex; align-items: center; justify-content: space-between; padding: calc(10px + env(safe-area-inset-top, 0px)) 0 10px; background: linear-gradient(var(--bg), color-mix(in srgb, var(--bg) 10%, transparent)); }
.podc-icn { width: 38px; height: 38px; border: 0; background: color-mix(in srgb, var(--surface) 60%, transparent); border-radius: 50%; display: grid; place-items: center; color: var(--text); cursor: pointer; }
.podc-icn svg { width: 20px; height: 20px; }
.podc-label { text-align: center; flex: 1; }
.podc-label b { font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--text-muted); display: block; }
.podc-label span { font-size: 11px; color: var(--text-faint); }
.podc-hero-art { width: min(78%, 300px); aspect-ratio: 1; margin: 8px auto 22px; border-radius: var(--radius-lg); box-shadow: 0 24px 60px -16px rgba(0,0,0,.7); will-change: transform; }
.podc-hero-meta { margin-bottom: 18px; }
.podc-ht { font-size: 21px; font-weight: 800; letter-spacing: -.02em; line-height: 1.22; color: var(--text); }
.podc-hmrow { display: flex; gap: 8px; align-items: center; margin-top: 11px; flex-wrap: wrap; }
.podc-htype { font-size: 12px; color: var(--text-muted); font-weight: 600; }

/* scrubber */
.podc-scrub-track { position: relative; height: 24px; display: flex; align-items: center; cursor: pointer; touch-action: none; }
.podc-scrub-rail, .podc-scrub-buf, .podc-scrub-fill { position: absolute; left: 0; height: 5px; border-radius: 3px; }
.podc-scrub-rail { right: 0; background: var(--surface-bright); }
.podc-scrub-buf { background: var(--border-strong); width: 0; }
.podc-scrub-fill { background: var(--accent); width: 0; }
.podc-scrub-thumb { position: absolute; width: 15px; height: 15px; border-radius: 50%; background: var(--text); box-shadow: 0 2px 8px rgba(0,0,0,.5); left: 0; transform: translateX(-50%); transition: transform .12s; }
.podc-scrub-track:active .podc-scrub-thumb { transform: translateX(-50%) scale(1.35); }
.podc-scrub-mark { position: absolute; width: 2px; height: 11px; background: color-mix(in srgb, var(--text) 55%, transparent); border-radius: 2px; transform: translateX(-50%); pointer-events: none; }
/* drag bubble — timecode + chapter you'd seek into; positioned by inline left:% */
.podc-scrub-bubble { position: absolute; bottom: calc(100% + 8px); left: 0; transform: translate(-50%, 4px); max-width: 240px; display: flex; flex-direction: column; align-items: center; gap: 1px; padding: 6px 12px; background: var(--surface-floating); border: 1px solid var(--border-strong); border-radius: 12px; box-shadow: 0 10px 30px -10px rgba(0,0,0,.7); pointer-events: none; opacity: 0; transition: opacity .12s var(--ease-out), transform .12s var(--ease-out); z-index: 6; }
.podc-scrub-bubble.show { opacity: 1; transform: translate(-50%, 0); }
.podc-scrub-bubble .podc-sb-t { font-size: 12px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.podc-scrub-bubble .podc-sb-l { font-size: 11px; font-weight: 600; color: var(--text-muted); text-align: center; line-height: 1.25; max-width: 216px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.podc-times { display: flex; justify-content: space-between; font-size: 11px; color: var(--text-faint); font-variant-numeric: tabular-nums; margin-top: 5px; }

/* transport */
.podc-transport { display: flex; align-items: center; justify-content: space-between; margin: 20px 0 14px; padding: 0 4px; }
.podc-t { border: 0; background: transparent; color: var(--text); cursor: pointer; display: grid; place-items: center; position: relative; }
.podc-t svg { fill: currentColor; }
.podc-t.skip svg { width: 30px; height: 30px; }
.podc-t.skip span { position: absolute; inset: 0; display: grid; place-items: center; font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums; padding-top: 2px; }
.podc-t.chap { color: var(--text-muted); } .podc-t.chap svg { width: 26px; height: 26px; }
.podc-tplay { width: 68px; height: 68px; border-radius: 50%; background: var(--text); color: var(--bg); box-shadow: 0 8px 24px -6px rgba(0,0,0,.6); }
.podc-tplay svg { width: 30px; height: 30px; }

/* secondary controls */
.podc-sec-row { display: flex; align-items: center; justify-content: space-between; gap: 4px; padding: 6px 2px 4px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.podc-sec { flex: 1; border: 0; background: transparent; color: var(--text-muted); font: inherit; font-size: 11px; font-weight: 600; padding: 11px 2px; display: flex; flex-direction: column; align-items: center; gap: 5px; cursor: pointer; }
.podc-sec svg { width: 19px; height: 19px; }
.podc-sec.podc-active { color: var(--accent-text); }
.podc-sec b { font-weight: 700; }

/* karaoke */
.podc-karaoke { margin: 20px 0 6px; min-height: 62px; text-align: center; padding: 0 6px; }
.podc-kq { font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--text-disabled); margin-bottom: 9px; }
.podc-kline { font-size: 16px; font-weight: 600; line-height: 1.45; color: var(--text); transition: color .3s; min-height: 22px; }
.podc-kprev { font-size: 13px; color: var(--text-disabled); line-height: 1.4; }

/* hero sections */
.podc-hsec { margin-top: 26px; }
.podc-hsh { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.podc-hsh b { font-size: 13px; font-weight: 700; color: var(--text); }
.podc-more { font-size: 11px; color: var(--text-faint); }
.podc-empty { font-size: 12px; color: var(--text-faint); padding: 8px 2px; }

.podc-chap { display: flex; align-items: center; gap: 12px; padding: 11px 10px; border-radius: var(--radius); cursor: pointer; transition: background .15s var(--ease-out); }
.podc-chap.cur { background: var(--accent-soft); }
.podc-ci-t { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--text-faint); width: 42px; font-weight: 600; }
.podc-chap.cur .podc-ci-t { color: var(--accent-text); }
.podc-ci-l { flex: 1; font-size: 13.5px; font-weight: 500; color: var(--text); }
.podc-chap.cur .podc-ci-l { font-weight: 700; }

.podc-qtoggle { display: flex; align-items: center; gap: 9px; font-size: 12px; color: var(--text-muted); background: var(--surface); border: 1px solid var(--border); padding: 9px 12px; border-radius: var(--radius); margin-bottom: 12px; }
.podc-switch { margin-left: auto; width: 44px; height: 24px; border-radius: var(--radius-pill); background: var(--accent); position: relative; flex: none; cursor: pointer; }
.podc-switch::after { content: ""; position: absolute; top: 2px; right: 2px; width: 20px; height: 20px; border-radius: 50%; background: var(--surface-bright); transition: right .2s var(--ease-out); }
.podc-switch[data-on="false"] { background: var(--surface-bright); } .podc-switch[data-on="false"]::after { right: 22px; }
.podc-q-item { display: flex; align-items: center; gap: 12px; padding: 9px 6px; cursor: pointer; }
.podc-q-art { width: 46px; height: 46px; border-radius: 9px; flex: none; }
.podc-q-b { flex: 1; min-width: 0; }
.podc-q-t { font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--text); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.podc-q-s { font-size: 11px; color: var(--text-faint); margin-top: 3px; }
.podc-q-grouplabel { font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--text-faint); margin: 14px 2px 4px; }
.podc-q-grouplabel:first-child { margin-top: 2px; }
.podc-q-rm { flex: none; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border: none; background: none; color: var(--text-faint); cursor: pointer; border-radius: 50%; }
.podc-q-rm svg { width: 16px; height: 16px; }
.podc-q-rm:hover { color: var(--text); background: var(--surface); }

.podc-exam { background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--red); border-radius: var(--radius); padding: 13px 15px; }
.podc-ec-h { margin-bottom: 8px; }
.podc-ec-pass { font-size: 11px; font-weight: 800; color: var(--grade-missed-label); background: color-mix(in srgb, var(--red) 16%, transparent); padding: 3px 8px; border-radius: var(--radius-sm); }
.podc-ec-q { font-size: 13px; line-height: 1.45; color: var(--text); }

.podc-transcript { font-size: 13.5px; line-height: 1.7; color: var(--text-muted); }
.podc-transcript p { margin: 0 0 14px; cursor: pointer; padding: 4px 6px; border-radius: var(--radius-sm); transition: background .15s var(--ease-out); }
.podc-transcript p.cur { background: var(--accent-soft); color: var(--text); }
.podc-transcript p time { display: inline-block; font-size: 10.5px; font-variant-numeric: tabular-nums; color: var(--text-disabled); margin-right: 9px; font-weight: 600; }
.podc-collapsed { max-height: 150px; overflow: hidden; -webkit-mask-image: linear-gradient(var(--text), transparent); mask-image: linear-gradient(rgba(0,0,0,1), transparent); }
.podc-show-transcript { text-align: center; font-size: 12px; font-weight: 600; color: var(--accent-text); padding: 10px; cursor: pointer; }

/* sheet */
.podc-scrim { position: fixed; inset: 0; z-index: 1590; background: rgba(0,0,0,.55); opacity: 0; pointer-events: none; transition: opacity .25s var(--ease-out); }
.podc-scrim.podc-show { opacity: 1; pointer-events: auto; }
.podc-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 1600; background: var(--surface-floating); border-radius: 24px 24px 0 0; padding: 10px 22px calc(28px + env(safe-area-inset-bottom, 0px)); transform: translateY(100%); transition: transform .34s var(--ease-spring); box-shadow: 0 -10px 40px -10px rgba(0,0,0,.6); }
.podc-sheet.podc-show { transform: translateY(0); }
.podc-grab { width: 38px; height: 5px; border-radius: 3px; background: var(--border-strong); margin: 0 auto 18px; }
.podc-sheet h3 { font-size: 14px; font-weight: 700; margin: 0 0 14px; color: var(--text); }
.podc-sheet h3:not(:first-of-type) { margin-top: 24px; }
.podc-speed-seg { display: flex; gap: 6px; }
.podc-speed-seg button { flex: 1; border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); font: inherit; font-size: 13px; font-weight: 700; padding: 13px 4px; border-radius: var(--radius); cursor: pointer; transition: background .15s var(--ease-out); }
.podc-speed-seg button.on { background: var(--accent); color: var(--accent-on); border-color: transparent; }
.podc-sleep-opt { display: flex; align-items: center; gap: 12px; padding: 13px 6px; cursor: pointer; border-bottom: 1px solid var(--border); }
.podc-sleep-opt:last-child { border-bottom: 0; }
.podc-sleep-opt span:first-child { flex: 1; font-size: 14px; color: var(--text-muted); }
.podc-sleep-opt .podc-tick { color: var(--accent-text); opacity: 0; }
.podc-sleep-opt.on .podc-tick { opacity: 1; } .podc-sleep-opt.on span:first-child { color: var(--text); font-weight: 600; }

/* up-next + toast */
.podc-upnext { position: fixed; left: 12px; right: 12px; bottom: calc(var(--podc-dock-bottom) + 76px + env(safe-area-inset-bottom, 0px)); z-index: 1450; background: var(--surface-floating); border: 1px solid var(--border-strong); border-radius: 14px; padding: 12px 14px; display: flex; align-items: center; gap: 12px; box-shadow: 0 8px 28px -8px rgba(0,0,0,.6); transform: translateY(20px); opacity: 0; pointer-events: none; transition: transform .3s var(--ease-spring), opacity .3s; }
.podc-upnext.podc-show { transform: translateY(0); opacity: 1; pointer-events: auto; }
.podc-un-art { width: 40px; height: 40px; border-radius: var(--radius-sm); flex: none; }
.podc-un-b { flex: 1; min-width: 0; }
.podc-un-k { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--accent-text); }
.podc-un-t { font-size: 12.5px; font-weight: 600; margin-top: 2px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.podc-un-cancel { border: 1px solid var(--border-strong); background: transparent; color: var(--text-muted); font: inherit; font-size: 11px; font-weight: 600; padding: 7px 12px; border-radius: var(--radius-pill); cursor: pointer; flex: none; }
.podc-toast { position: fixed; left: 50%; bottom: calc(var(--podc-dock-bottom) + 84px + env(safe-area-inset-bottom, 0px)); z-index: 1610; transform: translate(-50%, 20px); background: var(--surface-floating); border: 1px solid var(--border-strong); color: var(--text); font-size: 12.5px; font-weight: 600; padding: 11px 18px; border-radius: var(--radius-pill); box-shadow: 0 8px 28px -8px rgba(0,0,0,.6); opacity: 0; pointer-events: none; transition: transform .25s var(--ease-out), opacity .25s; white-space: nowrap; }
.podc-toast.podc-show { opacity: 1; transform: translate(-50%, 0); }

/* ---------------- Today launch surface (#podcastHeroSection) ---------------- */
.podc-today { margin: 18px 0 8px; }
.podc-today-h, .podc-today-sub { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint); margin: 0 2px 11px; }
.podc-today-sub { margin-top: 22px; }
.podc-cont-card { position: relative; border-radius: var(--radius-lg); overflow: hidden; border: 1px solid var(--border); background: var(--surface); cursor: pointer; transition: transform .2s var(--ease-out); }
.podc-cont-card:active { transform: scale(.985); }
.podc-cont-art { height: 124px; border-radius: 0; }
.podc-cont-body { padding: 13px 15px 15px; display: flex; align-items: center; gap: 13px; }
.podc-cont-kick { font-size: 11px; font-weight: 700; color: var(--accent-text); letter-spacing: .04em; text-transform: uppercase; margin-bottom: 3px; }
.podc-cont-title { font-size: 15px; font-weight: 700; line-height: 1.25; color: var(--text); }
.podc-cont-sub { font-size: 12px; color: var(--text-faint); margin-top: 4px; }
.podc-cont-card .podc-cont-body > div:first-child { flex: 1; min-width: 0; }
.podc-cont-fab { flex: none; width: 48px; height: 48px; border-radius: 50%; border: 0; background: var(--accent); color: var(--accent-on); cursor: pointer; display: grid; place-items: center; }
.podc-cont-fab svg { width: 22px; height: 22px; fill: currentColor; }
.podc-cont-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: rgba(0,0,0,.4); }
.podc-cont-bar i { display: block; height: 100%; background: var(--accent); }
.podc-ep-row { display: flex; gap: 11px; overflow-x: auto; padding: 2px 2px 8px; margin: 0 -2px; scroll-snap-type: x mandatory; }
.podc-ep-row::-webkit-scrollbar { height: 0; }
.podc-ep-card { flex: none; width: 148px; scroll-snap-align: start; cursor: pointer; }
.podc-ep-art { height: 148px; border-radius: var(--radius); margin-bottom: 9px; }
.podc-ep-t { font-size: 12.5px; font-weight: 600; line-height: 1.3; color: var(--text); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.podc-ep-s { font-size: 11px; color: var(--text-faint); margin-top: 4px; }

/* ---------------- Podcasts tab inside the Textbook Library modal ---------------- */
.tl-pod-filters { display: flex; flex-direction: column; gap: 9px; margin-bottom: 12px; }
.tl-pod-cg { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.tl-pod-cg-lbl { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--text-faint); min-width: 52px; }
.tl-pod-chip { border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); font: inherit; font-size: 12px; font-weight: 600; padding: 6px 12px; border-radius: var(--radius-pill); cursor: pointer; transition: background .15s var(--ease-out), color .15s; }
.tl-pod-chip.on { background: var(--accent); color: var(--accent-on); border-color: transparent; }
.tl-pod-count { font-size: 11px; color: var(--text-faint); margin: 4px 2px 10px; }
.tl-pod-grid { display: flex; flex-direction: column; gap: 8px; }
.tl-pod-row { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 10px 12px; cursor: pointer; transition: background .15s var(--ease-out); }
.tl-pod-row:hover { background: var(--surface-elevated); }
.tl-pod-art { width: 52px; height: 52px; border-radius: var(--radius-sm); flex: none; }
.tl-pod-body { flex: 1; min-width: 0; }
.tl-pod-title { font-size: 14px; font-weight: 600; color: var(--text); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.tl-pod-meta { display: flex; align-items: center; gap: 8px; margin-top: 4px; font-size: 11.5px; color: var(--text-faint); flex-wrap: wrap; }
.tl-pod-node { font-weight: 700; color: var(--text-muted); }
.tl-pod-tier { font-size: 12px; }
.tl-pod-play { flex: none; width: 34px; height: 34px; border-radius: 50%; background: var(--accent-soft); color: var(--accent-text); display: grid; place-items: center; }
.tl-pod-play svg { width: 16px; height: 16px; }

/* ================= v2 WS1 — Today podcast rail ================= */
.podc-today-h { display: flex; align-items: center; gap: 8px; }
.podc-today-h .podc-rail-hint { margin-left: auto; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--text-disabled); font-size: 10.5px; }
/* v3 — iOS album-style rail: square crest + text section (code · title · status·remaining·duration) */
/* Left edge ~aligned with the Today hero; right keeps the bleed-to-screen-edge
   scroll affordance. (overflow-x flex rows ignore the container's left padding
   for the first item, so inset the first tile via its own margin instead so its
   shadow isn't clipped — flush looked cut off.) */
.podc-rail { display: flex; gap: 14px; overflow-x: auto; padding: 2px 16px 12px 0; margin: 0 -16px 0 0; scroll-snap-type: x proximity; scroll-padding-left: 8px; -webkit-overflow-scrolling: touch; min-height: 210px; }
/* first-tile inset (so its shadow isn't clipped); scroll-padding-left stops snap
   from scrolling the inset away. */
.podc-rail > :first-child { margin-left: 8px; }
.podc-rail::-webkit-scrollbar { height: 0; }
.podc-rtile { flex: none; width: 158px; scroll-snap-align: start; cursor: pointer; }
/* Skeleton tiles reserve the rail's height while the deferred (idle) fetch runs,
   so the real tiles replacing them don't shift content (flag_podcast_rail_idle). */
.podc-rtile-skel { pointer-events: none; }
.podc-rtile-skel .podc-rt-art { background: var(--surface); }
.podc-rtile-skel .podc-rt-body { height: 34px; }
.podc-rt-art { position: relative; aspect-ratio: 1; border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 9px; transition: transform .18s var(--ease-out); }
.podc-rtile:active .podc-rt-art { transform: scale(.97); }
.podc-rt-crest { position: absolute; inset: 0; border-radius: var(--radius-lg); }
.podc-rtile.lead .podc-rt-art { box-shadow: 0 0 0 2px var(--accent); }
.podc-rt-fab { position: absolute; right: 9px; bottom: 9px; width: 40px; height: 40px; border-radius: 50%; background: var(--accent); color: var(--accent-on); display: grid; place-items: center; box-shadow: 0 6px 16px -4px rgba(0,0,0,.5); z-index: 3; }
.podc-rt-fab svg { width: 18px; height: 18px; fill: currentColor; }
.podc-rt-kebab { position: absolute; top: 8px; right: 8px; width: 30px; height: 30px; border: 0; border-radius: 50%; background: rgba(8,8,14,.55); backdrop-filter: blur(6px); color: rgba(255,255,255,.95); display: grid; place-items: center; cursor: pointer; z-index: 3; }
.podc-rt-kebab svg { width: 16px; height: 16px; }
.podc-rt-prog { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: rgba(0,0,0,.45); z-index: 2; }
.podc-rt-prog i { display: block; height: 100%; background: var(--accent); }
.podc-rt-body { padding: 0 2px; }
.podc-rt-code { font-size: 11px; font-weight: 700; color: var(--text-muted); letter-spacing: .01em; font-variant-numeric: tabular-nums; }
.podc-rt-t { font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--text); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.podc-rt-s { font-size: 11px; color: var(--text-faint); margin-top: 4px; font-variant-numeric: tabular-nums; }
.podc-rtile.more { width: 132px; }
.podc-rtile.more .podc-rt-art { display: flex; align-items: center; justify-content: center; background: var(--surface); border: 1px solid var(--border); }
.podc-rtile.more .podc-mr { display: flex; flex-direction: column; align-items: center; gap: 8px; color: var(--text-muted); }
.podc-rtile.more .podc-mr svg { width: 26px; height: 26px; stroke: currentColor; stroke-width: 1.8; fill: none; }
.podc-rtile.more .podc-mr b { font-size: 12.5px; font-weight: 700; color: var(--text); }
.podc-rtile.more .podc-mr span { font-size: 10.5px; color: var(--text-faint); }

/* ================= v2 WS2 — episode context menu ================= */
.podc-menu-scrim { position: fixed; inset: 0; z-index: 1690; background: rgba(0,0,0,.5); opacity: 0; pointer-events: none; transition: opacity .2s var(--ease-out); }
.podc-menu-scrim.podc-show { opacity: 1; pointer-events: auto; }
.podc-menu { position: fixed; z-index: 1700; background: var(--surface-floating); border: 1px solid var(--border-strong); box-shadow: 0 12px 40px -10px rgba(0,0,0,.7); overflow: hidden; }
.podc-menu--sheet { left: 8px; right: 8px; bottom: calc(8px + env(safe-area-inset-bottom, 0px)); border-radius: 20px; padding: 8px; transform: translateY(16px); opacity: 0; transition: transform .26s var(--ease-spring), opacity .2s; }
.podc-menu--sheet.podc-show { transform: translateY(0); opacity: 1; }
.podc-menu--popover { width: 232px; border-radius: 14px; padding: 6px; transform: scale(.96); opacity: 0; transform-origin: top left; transition: transform .16s var(--ease-out), opacity .16s; }
.podc-menu--popover.podc-show { transform: scale(1); opacity: 1; }
.podc-menu.podc-noanim { transition: none !important; }
.podc-mn-head { display: flex; align-items: center; gap: 11px; padding: 9px 10px 12px; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.podc-menu--popover .podc-mn-head { padding: 6px 8px 9px; }
.podc-mn-art { width: 40px; height: 40px; border-radius: 9px; flex: none; }
.podc-menu--popover .podc-mn-art { width: 30px; height: 30px; }
.podc-mn-hb { flex: 1; min-width: 0; }
.podc-mn-t { font-size: 13px; font-weight: 700; color: var(--text); line-height: 1.25; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.podc-menu--popover .podc-mn-t { -webkit-line-clamp: 1; }
.podc-mn-s { font-size: 10.5px; color: var(--text-faint); margin-top: 3px; }
.podc-mn-item { display: flex; align-items: center; gap: 13px; width: 100%; text-align: left; border: 0; background: transparent; padding: 13px 12px; border-radius: 11px; cursor: pointer; color: var(--text); font: inherit; font-size: 14px; font-weight: 500; }
.podc-menu--popover .podc-mn-item { padding: 9px 10px; gap: 10px; font-size: 13px; }
.podc-mn-item:hover, .podc-mn-item:focus-visible { background: color-mix(in srgb, var(--text) 9%, transparent); outline: none; }
.podc-mn-ic { display: grid; place-items: center; color: var(--text-muted); }
.podc-mn-ic svg { width: 19px; height: 19px; }
.podc-menu--popover .podc-mn-ic svg { width: 16px; height: 16px; }
.podc-mn-item.podc-mn-on, .podc-mn-item.podc-mn-on .podc-mn-ic { color: var(--accent-text); }

/* ================= v2 WS3 — textbook modal header (wordmark removed, centred tabs) ===== */
.tl-hd--tabs { justify-content: space-between; align-items: center; }
.tl-hd-spacer { width: 34px; flex: none; }
.tl-seg.tl-seg--center { display: flex; flex: 1 1 auto; justify-content: center; }
.tl-seg.tl-seg--center .tl-seg-btn { flex: 0 1 auto; min-width: 88px; }

/* ================= v2 WS3 — podcast chip in the All (by-topic) list ================= */
.tl-pod-chip-inline { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; padding: 4px 9px 4px 5px; border-radius: var(--radius-pill); cursor: pointer;
  background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent); color: var(--accent-text); }
.tl-pod-chip-inline .tl-pc-art { width: 17px; height: 17px; border-radius: 5px; flex: none; }
.tl-pod-chip-inline svg { width: 12px; height: 12px; stroke: currentColor; stroke-width: 2; fill: none; }
.tl-pod-chip-inline .tl-pc-tag { font-size: 9px; font-weight: 800; letter-spacing: .04em; }
.tl-pod-chip-inline .tl-pc-d { font-weight: 600; font-variant-numeric: tabular-nums; opacity: .85; }
.tl-sec-cnt .tl-pc-count { color: var(--accent-text); }
.tl-pod-done { color: var(--accent-text); font-weight: 700; }

/* ================= v2 WS4 — hero card-stack ================= */
.podc-hero-scroll.podc-stack { padding: 0; scroll-snap-type: y mandatory; }
.podc-hcard { min-height: 100%; scroll-snap-align: start; position: relative; padding: 0 22px calc(20px + env(safe-area-inset-bottom, 0px)); display: flex; flex-direction: column; }
/* card headers: full-bleed solid bar (content stays inset) so the background isn't cut off each side */
.podc-hero-top, .podc-hcard-hd { margin-left: -22px; margin-right: -22px; padding-left: 22px; padding-right: 22px; background: var(--bg); }
/* hero now-playing title + tags centred */
.podc-hero-meta { text-align: center; }
.podc-hmrow { justify-content: center; }
/* scrubber must capture touch drags (beats the global [tabindex] touch-action:manipulation) */
.podc-scrub-track { touch-action: none !important; }
.podc-hdots { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); z-index: 5; display: flex; flex-direction: column; gap: 8px; pointer-events: none; }
.podc-hdots i { width: 6px; height: 6px; border-radius: 50%; background: var(--border-strong); transition: height .2s var(--ease-out), background .2s; }
.podc-hdots i.on { background: var(--accent); height: 18px; border-radius: 3px; }
.podc-pull { margin-top: auto; padding: 14px 0 8px; display: flex; flex-direction: column; align-items: center; gap: 3px; color: var(--text-faint); cursor: pointer; background: 0; border: 0; font: inherit; }
.podc-pull svg { width: 20px; height: 20px; stroke: currentColor; stroke-width: 2; fill: none; animation: podcBob 1.8s var(--ease-out) infinite; }
.podc-pull b { font-size: 11px; font-weight: 700; color: var(--text-muted); }
.podc-pull span { font-size: 10px; color: var(--text-disabled); }
@keyframes podcBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(4px); } }
.podc-hcard-hd { position: sticky; top: 0; z-index: 3; padding: calc(14px + env(safe-area-inset-top, 0px)) 0 12px; background: linear-gradient(var(--bg) 72%, transparent); display: flex; align-items: baseline; gap: 9px; }
.podc-hcard-hd b { font-size: 15px; font-weight: 800; letter-spacing: -.01em; color: var(--text); }
.podc-hcard-hd span { font-size: 11px; color: var(--text-faint); }
.podc-hcard-back { margin-left: auto; border: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: 11px; font-weight: 700; cursor: pointer; }
/* karaoke is now a toggleable, closable panel on card 1 */
.podc-karaoke { position: relative; margin: 14px 0 4px; padding: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); text-align: center; }
.podc-karaoke[hidden] { display: none; }
.podc-kclose { position: absolute; top: 7px; right: 8px; width: 24px; height: 24px; border: 0; border-radius: 50%; background: transparent; color: var(--text-faint); cursor: pointer; display: grid; place-items: center; }
.podc-kclose svg { width: 14px; height: 14px; stroke: currentColor; stroke-width: 2; fill: none; }
.podc-nodecards .ribbon-list { margin-bottom: 4px; }
.podc-nodecards .podc-empty { padding: 8px 2px; }

/* ============================================================
   v3 — native-iOS pass: content column · corner widget ·
   up-next carousel · segmented filters · material polish
   ============================================================ */

/* unified played-state icon sizing */
.podc-sec-ic { display: grid; place-items: center; }
.tl-pod-done { display: inline-flex; align-items: center; gap: 4px; color: var(--accent-text); font-weight: 700; }
.tl-pod-done svg { width: 13px; height: 13px; }

/* — thumbnail node-code fits its tile (52px Podcasts rows); hidden on tiny crests — */
.tl-pod-art .podc-art-code { font-size: 13px; letter-spacing: -.02em; }
.podc-q-art .podc-art-code, .podc-un-art .podc-art-code, .podc-mn-art .podc-art-code { font-size: 12px; letter-spacing: -.02em; }
.tl-pc-art .podc-art-code { display: none; } /* 17px All-tab chip — too tiny for a legible code */

/* — content reading column on wide screens (hero stays full-screen; art + bg full-bleed) — */
@media (min-width: 900px) {
  .podc-hero { --podc-pad: max(22px, calc((100vw - 720px) / 2)); }
  .podc-hcard { padding-left: var(--podc-pad); padding-right: var(--podc-pad); }
  /* full-width header bars (banner + card headers); content stays in the column */
  .podc-hcard > .podc-hero-top, .podc-hcard > .podc-hcard-hd { margin-left: calc(-1 * var(--podc-pad)); margin-right: calc(-1 * var(--podc-pad)); padding-left: var(--podc-pad); padding-right: var(--podc-pad); }
  #textbookRoot .tl-hd, #textbookRoot .tl-search, #textbookRoot .tl-segbar, #textbookRoot .tl-content { max-width: 760px; margin-left: auto; margin-right: auto; }
}

/* — minimised player: compact draggable corner widget on wide screens — */
@media (min-width: 900px) {
  .podc-mini { left: auto; right: 20px; bottom: 20px; width: 320px; height: 74px; border-radius: 18px; cursor: grab; touch-action: none; }
  .podc-mini.podc-dragging { transition: none; cursor: grabbing; box-shadow: 0 18px 50px -10px rgba(0,0,0,.7); }
  .podc-mini[data-corner="tl"] { left: 20px; right: auto; top: 20px; bottom: auto; }
  .podc-mini[data-corner="tr"] { right: 20px; left: auto; top: 20px; bottom: auto; }
  .podc-mini[data-corner="bl"] { left: 20px; right: auto; bottom: 20px; top: auto; }
  .podc-mini[data-corner="br"] { right: 20px; left: auto; bottom: 20px; top: auto; }
  .podc-mini[data-corner="tc"] { left: calc(50% - 160px); right: auto; top: 20px; bottom: auto; }
  .podc-mini[data-corner="bc"] { left: calc(50% - 160px); right: auto; bottom: 20px; top: auto; }
  .podc-mini #podc-miniFwd { display: none; }
  .podc-mini .podc-m-sub { display: none; }
  .podc-mini .podc-m-art { width: 48px; height: 48px; }
}

/* — card 1 up-next carousel — */
.podc-hero-carousel { position: relative; }
.podc-hero-track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.podc-hero-track::-webkit-scrollbar { display: none; }
.podc-hero-slide { flex: 0 0 100%; scroll-snap-align: center; display: flex; justify-content: center; }
.podc-hero-slide[hidden] { display: none; }
.podc-upnext-slide { flex-direction: column; align-items: center; gap: 14px; padding: 8px 0 12px; }
.podc-upnext-card { width: min(70%, 258px); aspect-ratio: 1; border-radius: var(--radius-xl, 22px); position: relative; overflow: hidden; box-shadow: 0 24px 60px -16px rgba(0,0,0,.7); }
.podc-upnext-ring { position: absolute; inset: 0; display: grid; place-items: center; background: rgba(8,8,14,.34); }
.podc-upnext-ring svg { width: 88px; height: 88px; }
.podc-ring-bg { fill: none; stroke: rgba(255,255,255,.22); stroke-width: 5; }
.podc-ring-fg { fill: none; stroke: var(--accent); stroke-width: 5; stroke-linecap: round; transform: rotate(-90deg); transform-origin: center; transition: stroke-dashoffset 1s linear; }
.podc-ring-num { position: absolute; font-size: 26px; font-weight: 700; color: rgba(255,255,255,.96); font-variant-numeric: tabular-nums; }
.podc-upnext-info { text-align: center; max-width: 80%; }
.podc-un-kick { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--accent-text); }
.podc-un-name { font-size: 14px; font-weight: 600; color: var(--text); margin-top: 4px; line-height: 1.3; }
.podc-upnext-actions { display: flex; gap: 8px; }
.podc-upnext-actions button { border: 0; font: inherit; font-size: 12px; font-weight: 700; padding: 9px 18px; border-radius: var(--radius-pill); cursor: pointer; }
.podc-un-playnow { background: var(--accent); color: var(--accent-on); }
.podc-un-dismiss { background: var(--surface-elevated); color: var(--text-muted); }
.podc-carousel-dots { display: flex; justify-content: center; gap: 6px; margin-top: 10px; }
.podc-carousel-dots[hidden] { display: none; }
.podc-carousel-dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--border-strong); transition: background .2s var(--ease-out), width .2s var(--ease-out); }
.podc-carousel-dots i.on { background: var(--accent); width: 16px; border-radius: 3px; }

/* — Podcasts tab: segmented section control + filters/sort buttons — */
.tl-segbar { display: flex; gap: 8px; align-items: center; padding: 0 16px 10px; }
.tl-seg-scroll { display: flex; gap: 4px; overflow-x: auto; scrollbar-width: none; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 3px; flex: 1 1 auto; min-width: 0; }
.tl-seg-scroll::-webkit-scrollbar { display: none; }
.tl-seg-pill { flex: 0 0 auto; border: 0; background: transparent; color: var(--text-muted); font: inherit; font-size: 12px; font-weight: 600; padding: 6px 13px; border-radius: var(--radius-pill); cursor: pointer; white-space: nowrap; transition: background .15s var(--ease-out), color .15s; }
.tl-seg-pill.on { background: var(--surface-floating); color: var(--text); }
.tl-filt-btn, .tl-sort-btn { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); font: inherit; font-size: 12px; font-weight: 600; padding: 7px 12px; border-radius: var(--radius-pill); cursor: pointer; }
.tl-filt-btn.on { background: var(--accent-soft); color: var(--accent-text); border-color: transparent; }
.tl-filt-btn svg, .tl-sort-btn svg { width: 14px; height: 14px; stroke: currentColor; stroke-width: 2; fill: none; }
.tl-filt-badge { min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; background: var(--accent); color: var(--accent-on); font-size: 10px; font-weight: 800; display: inline-grid; place-items: center; }
/* filters bottom-sheet (iOS material + grabber) */
.tl-fsheet-scrim { position: fixed; inset: 0; z-index: 1690; background: rgba(0,0,0,.5); opacity: 0; pointer-events: none; transition: opacity .2s var(--ease-out); }
.tl-fsheet-scrim.show { opacity: 1; pointer-events: auto; }
.tl-fsheet { position: fixed; left: 50%; bottom: 0; transform: translate(-50%, 100%); z-index: 1700; width: 100%; max-width: 520px; background: var(--surface-floating); border-radius: 22px 22px 0 0; padding: 8px 20px calc(24px + env(safe-area-inset-bottom, 0px)); box-shadow: 0 -12px 40px -10px rgba(0,0,0,.6); transition: transform var(--duration-md, .2s) var(--ease-sheet-spring, cubic-bezier(.32,1,.48,1)); }
.tl-fsheet.show { transform: translate(-50%, 0); }
.tl-fsheet-grab { width: 38px; height: 5px; border-radius: 3px; background: var(--border-strong); margin: 0 auto 16px; }
.tl-fsheet h4 { font-size: 13px; font-weight: 700; color: var(--text); margin: 16px 0 9px; }
.tl-fsheet h4:first-of-type { margin-top: 2px; }
.tl-fgroup { display: flex; gap: 7px; flex-wrap: wrap; }
.tl-fsheet-done { width: 100%; margin-top: 22px; border: 0; background: var(--accent); color: var(--accent-on); font: inherit; font-size: 14px; font-weight: 700; padding: 13px; border-radius: var(--radius); cursor: pointer; }

/* — transcript quick-nav (card 3): jump to top / current line — */
.podc-tx-nav { position: absolute; right: 16px; bottom: calc(20px + env(safe-area-inset-bottom, 0px)); z-index: 6; display: flex; flex-direction: column; gap: 8px; }
.podc-tx-nav[hidden] { display: none; }
.podc-txn-btn { width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--border-strong); background: color-mix(in srgb, var(--surface-floating) 90%, transparent); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); color: var(--text); display: grid; place-items: center; cursor: pointer; box-shadow: 0 6px 18px -6px rgba(0,0,0,.5); font: inherit; font-size: 12px; font-weight: 700; }
.podc-txn-btn svg { width: 18px; height: 18px; }
.podc-txn-now { color: var(--accent-text); }

/* — padding polish: tighter, ≥44px secondary controls — */
.podc-sec { gap: 6px; min-height: 44px; }
.podc-sec span { font-size: 10.5px; }

/* v3-refine: dismiss control, rail high-yield dot, tappable up-next crest.
   Mobile (default): an in-bar ✕ button with a ≥44px tap target. Wide screens override
   it to the floating corner badge on the draggable widget (below). */
.podc-m-close { flex: none; width: 40px; height: 44px; border: 0; background: transparent; color: var(--text-muted); display: grid; place-items: center; cursor: pointer; padding: 0; }
.podc-m-close svg { width: 18px; height: 18px; }
@media (min-width: 900px) {
  .podc-mini .podc-m-close { width: 24px; height: 24px; position: absolute; top: -10px; right: -10px; border-radius: 50%; background: var(--surface-floating); border: 1px solid var(--border-strong); place-items: center; z-index: 5; } /* corner badge — WCAG 2.5.8: 24×24 min */
  .podc-mini .podc-m-close svg { width: 12px; height: 12px; }
}
.podc-rt-tier { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 5px; vertical-align: 1px; }
.podc-rt-tier-r { background: var(--red); }
.podc-rt-tier-a { background: var(--amber); }
.podc-rt-tier-g { background: var(--green); }
.podc-upnext-card { cursor: pointer; }

/* loading spinner — tile crest while a track mints/loads, + hero/mini play button */
@keyframes podcSpin { to { transform: rotate(360deg); } }
.podc-rt-art.is-loading::after, .tl-pod-art.is-loading::after { content: ""; position: absolute; inset: 0; margin: auto; width: 26px; height: 26px; border-radius: 50%; border: 3px solid rgba(255,255,255,.28); border-top-color: rgba(255,255,255,.95); animation: podcSpin .7s linear infinite; z-index: 4; }
.podc-tplay.podc-spinning svg, .podc-m-btn.podc-spinning svg { animation: podcSpin .8s linear infinite; }

/* dark runway below the sticky card header so it isn't sitting in the red gradient zone */
.podc-hcard-hd::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 40px; background: linear-gradient(var(--bg), transparent); pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .podc-mini, .podc-hero, .podc-sheet, .podc-scrim, .podc-upnext, .podc-toast, .podc-hero-art, .podc-cont-card,
  .podc-rtile, .podc-menu, .podc-menu-scrim, .podc-hdots i, .podc-carousel-dots i, .podc-ring-fg, .tl-fsheet, .tl-fsheet-scrim { transition: none !important; }
  .podc-pull svg, .podc-rt-art.is-loading::after, .tl-pod-art.is-loading::after, .podc-tplay.podc-spinning svg, .podc-m-btn.podc-spinning svg { animation: none !important; }
}

/* ============================================================================
   pwa/motion/motion.css — the shared MOTION LANGUAGE (single source of truth)
   ----------------------------------------------------------------------------
   One home for motion tokens, keyframes, utility classes, and the ONE
   reduced-motion block. Surfaces (cinema card, Today grid card, hero buttons,
   session/haul) wire to these via window.iatroMotion (motion.js) so a primitive
   works universally regardless of the card/hero context it lands on.

   Step 1 (this commit) is ADDITIVE: everything here is namespaced .mo-* / --mo-*
   so it cannot collide with the existing scattered animation rules. Step 2
   migrates the card/cinema/hero/session keyframes INTO this file and deletes the
   originals, repointing references.

   Constraints honoured (from the consolidation audit):
   - Height morph ONLY on the .mo-reveal-body child wrapper — never the outer
     .fc-card--v2 (its inline max-height is rewritten every frame by
     _syncFcStageAvail; a card-level height transition would fight it).
   - :active press feedback is PRM-exempt (instant direct manipulation).
   ========================================================================== */

:root {
  /* durations */
  --mo-dur-fast: 120ms;
  --mo-dur-base: 240ms;
  --mo-dur-slow: 380ms;
  /* easings — alias the existing design tokens so there is one vocabulary */
  --mo-ease-out:    var(--ease-out,    cubic-bezier(.4,.05,.2,1));
  --mo-ease-spring: var(--ease-spring, cubic-bezier(.34,1.56,.64,1));
  --mo-ease-in:     cubic-bezier(.4,0,1,1);
  /* shared knobs */
  --mo-reveal-ceiling: 600px;   /* generous cap; the inner scroller clips real content */
  --mo-press-depth: 3px;
}

/* ---- keyframes (the shared vocabulary) ---------------------------------- */
@keyframes mo-reveal-in   { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:none; } }
@keyframes mo-pulse-ring  { 0% { box-shadow:0 0 0 0 var(--mo-pulse-color, rgba(255,255,255,.45)); }
                            55% { box-shadow:0 0 0 9px rgba(255,255,255,0); }
                            100% { box-shadow:0 0 0 0 rgba(255,255,255,0); } }
@keyframes mo-stagger-in  { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }
@keyframes mo-spin        { to { transform:rotate(360deg); } }
@keyframes mo-progress-pulse { 0% { filter:brightness(1); } 40% { filter:brightness(1.6); } 100% { filter:brightness(1); } }

/* ---- press / touch feedback (universal, PRM-exempt) --------------------- */
/* base: any tappable element — subtle scale + brightness */
.mo-press { transition: transform var(--mo-dur-fast) var(--mo-ease-out), filter var(--mo-dur-fast) var(--mo-ease-out); }
.mo-press:active { transform: scale(.97); filter: brightness(.96); }

/* hero: scale-spring for the per-tab primary CTA */
.mo-press-hero { transition: transform var(--mo-dur-base) var(--mo-ease-spring), filter var(--mo-dur-fast); }
.mo-press-hero:active { transform: scale(.96); }

/* 3d: Duolingo-style depress for grade buttons — resting shadow crushes on press.
   The element sets --mo-press-shadow (a darker shade of its own colour). */
.mo-press-3d { box-shadow: 0 var(--mo-press-depth) 0 var(--mo-press-shadow, rgba(0,0,0,.4));
  transition: transform var(--mo-dur-fast) var(--mo-ease-out), box-shadow var(--mo-dur-fast) var(--mo-ease-out); }
.mo-press-3d:active { transform: translateY(var(--mo-press-depth)); box-shadow: 0 0 0 var(--mo-press-shadow, rgba(0,0,0,.4)); }

/* ---- reveal morph (child-wrapper height; never the card) --------------- */
.mo-reveal-body { max-height: 0; overflow: hidden; }
.mo-reveal-body.mo-revealed { max-height: var(--mo-reveal-ceiling); }
.mo-reveal-body.mo-morphing { transition: max-height var(--mo-dur-base) var(--mo-ease-out); }

/* ---- reveal content stagger (the micro-pause beat) --------------------- */
.mo-reveal-anim { animation: mo-reveal-in var(--mo-dur-base) var(--mo-ease-spring) both;
  animation-delay: var(--mo-reveal-delay, 0ms); }

/* ---- attention pulse (box-shadow ripple, no transform) ----------------- */
.mo-pulse { animation: mo-pulse-ring 700ms var(--mo-ease-spring) forwards; }

/* ---- entrance stagger (list rows; JS sets animation-delay per row) ------ */
.mo-stagger-row { animation: mo-stagger-in var(--mo-dur-slow) var(--mo-ease-spring) backwards; }

/* ---- loading morph (label keeps; spinner appended) --------------------- */
.mo-loading { pointer-events: none; opacity: .72; position: relative; }
.mo-loading::after { content:''; display:inline-block; width:14px; height:14px; margin-left:8px;
  vertical-align:-2px; border:2px solid rgba(255,255,255,.32); border-top-color:#fff; border-radius:50%;
  animation: mo-spin .7s linear infinite; }

/* ---- progress pulse (brightness flash on the fill, never width) -------- */
.mo-progress-pulse { animation: mo-progress-pulse 320ms var(--mo-ease-out) both; }

/* ---- particle (celebrate(); JS drives the WAAPI flight) ---------------- */
.mo-particle { will-change: transform, opacity; }

/* ---- app component bindings -------------------------------------------
   Bind the per-tab HERO buttons to the hero press-spring in ONE place (#8),
   rather than scattering a class across ~10 render templates that rebuild
   often. motion.css loads last, so this wins over the old per-element :active
   rules (which are removed). Transition keeps filter so hover effects survive. */
.hero-act, .sh-act-card, .ppr-action, .start-action-btn, .pharma-session-launch {
  transition: transform var(--mo-dur-base) var(--mo-ease-spring), filter var(--mo-dur-fast) var(--mo-ease-out);
}
.hero-act:active, .sh-act-card:active, .ppr-action:active,
.start-action-btn:active, .pharma-session-launch:active {
  transform: scale(.96);
}

/* ============================================================================
   THE ONE reduced-motion block (replaces the per-file duplicates in Step 2)
   :active press states are intentionally NOT suppressed — instant direct
   manipulation is PRM-exempt (WCAG 2.1).
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .mo-reveal-body.mo-morphing { transition: none !important; }
  .mo-reveal-anim,
  .mo-pulse,
  .mo-stagger-row,
  .mo-progress-pulse { animation: none !important; }
  .mo-press-hero,
  .hero-act, .sh-act-card, .ppr-action, .start-action-btn, .pharma-session-launch { transition: none !important; }
  .mo-loading::after { animation: none !important; }
}
