/* Design — bench aliases on top of the shared portfolio tokens.
 *
 * The canonical color/type/geometry tokens (--bg, --surface, --text,
 * --accent, --font-sans, --radius, etc.) live in tokens.css (imported
 * before this file from base.html). Those variables are SHARED with
 * libearden.dev so the operator's portfolio and the bench read as
 * one person's work.
 *
 * Below: bench-specific aliases that map the older variable names
 * scattered across this 4500-line file to the portfolio tokens. The
 * existing `var(--accent-color)` / `var(--surface-color)` / etc.
 * sprinkled through every rule pick up the new amber palette without
 * a per-rule rewrite.
 *
 * Visual-alignment commit (2026-05-27): bench is now dark-only by
 * default. The old `[data-theme="dark"]` override is gone — :root
 * IS the dark palette. localStorage `theme=dark` still sets the
 * data-attribute (no-op visually). localStorage `theme=light` no
 * longer flips to a separate light palette; the toggle UI hides it
 * pending a follow-up nav redesign.
 */

/* ─────────────────────────────────────────────────────────────────
   :root — token vocabulary
   ─────────────────────────────────────────────────────────────────
   The single source of restyling power. Every visual value (color,
   spacing, type size, line-height, radius, shadow, motion) is named
   below; rules reference `var(--…)` rather than literals.

   To restyle the whole app: edit this block, not the rules below.

   Theme scoping: bench is dark-only after the 2026-05-27 portfolio
   alignment (see comment at top of file). All values live in :root;
   if light theme is restored later, mirror everything in
   `:root[data-theme="light"]`. The no-flash <head> script still
   reads/writes localStorage["theme"] so the migration stays cheap.

   ─────────────────────────────────────────────────────────────── */
:root {
  /* === Surface + text + accent — bench aliases on the shared tokens.
     The canonical values live in static/css/tokens.css (shared with
     libearden.dev). These aliases keep the older bench names
     (`--surface-color`, `--brand-color`, etc.) resolving without
     grep-editing every rule. New code should reference the
     unaliased portfolio names where possible (`--bg`, `--surface`,
     `--accent`). === */
  --background-color:    var(--bg);
  --surface-color:       var(--surface);
  --surface-raised:      var(--surface-2);
  --text-color:          var(--text);
  --text-alt-color:      var(--text-muted);
  --heading-color:       var(--text);
  --border-color:        var(--border);
  --border-color-strong: var(--text-faint);

  --brand-color:         var(--accent);
  --brand-color-strong:  var(--accent-hover);
  --accent-color:        var(--accent);

  /* Code blocks read on --surface-2 (lifted, not bg-tinted) so inline
     <code> is clearly its own surface. */
  --code-bg: var(--surface-2);

  /* === Type scale ===
     One stepped scale used by every font-size in the app. Restyling
     the typographic feel is a single :root edit, not a grep.
     Pairing: `--font-sans` (Inter) is the default for headings + body;
     `--font-mono` (Geist Mono) is reserved for chrome — eyebrows,
     tag chips, badges, metadata, timestamps, code, SVG ticks. Body
     prose stays sans so /writings + /content remain readable. */
  --text-2xs:  0.625rem;   /* 10px — tick marks, smallest microcopy */
  --text-xs:   0.75rem;    /* 12px — chips, metadata, eyebrows */
  --text-sm:   0.875rem;   /* 14px — secondary text, UI labels */
  --text-base: 1rem;       /* 16px — body */
  --text-md:   1.0625rem;  /* 17px — h3 / lead paragraphs */
  --text-lg:   1.25rem;    /* 20px — minor section heads */
  --text-xl:   1.5rem;     /* 24px — h2 / interview timer */
  --text-2xl:  1.75rem;    /* 28px — larger section heads */
  --text-3xl:  2rem;       /* 32px — h1 default */
  --text-4xl:  2.25rem;    /* 36px — large page titles */
  --text-5xl:  2.5rem;     /* 40px — hero-scale (sparingly) */

  --weight-semibold: 600;
  --border-thin: 1px;
  --resource-reader-height: 70vh;

  --leading-tight:  1.25;
  --leading-snug:   1.4;
  --leading-normal: 1.6;

  --tracking-tight:  -0.015em;
  --tracking-normal: 0;
  --tracking-wide:   0.04em;
  --tracking-wider:  0.08em;
  --tracking-widest: 0.12em;

  /* === Spacing scale ===
     All margins, padding, gaps reference this. A half-step
     (`--space-0-5`) covers chip paddings that need to be smaller
     than --space-1 without going back to a literal value. */
  --space-0-5: 2px;
  --space-1:   4px;
  --space-2:   8px;
  --space-3:   12px;
  --space-4:   16px;
  --space-5:   24px;
  --space-6:   32px;
  --space-7:   48px;
  --space-8:   64px;

  /* Density knob — one multiplier flips comfortable ↔ compact.
     Density-aware components compute padding as
     `calc(var(--space-N) * var(--density))`. Default = 1
     (comfortable); `html[data-density="compact"]` overrides to 0.75. */
  --density: 1;

  /* === Radii === */
  --radius-sm:   2px;
  --radius-md:   4px;
  --radius:      6px;       /* portfolio scale (kept) */
  --radius-pill: 999px;
  --radius-card:  var(--radius);  /* legacy aliases — kept */
  --radius-input: var(--radius);

  /* === Semantic state colors ===
     Used by .result, banners, badges, and any "this is OK/warn/err"
     surface. Each color has a `-dim` companion (~15% alpha) for
     backgrounds + faint borders. */
  --ok:       #4ade80;
  --ok-dim:   rgba(74, 222, 128, 0.15);
  --warn:     #f5b042;
  --warn-dim: rgba(245, 176, 66, 0.15);
  --err:      #c43c3c;
  --err-dim:  rgba(196, 60, 60, 0.15);
  --info:     #6b8aff;
  --info-dim: rgba(107, 138, 255, 0.15);

  /* === Shadows === */
  --focus-ring: 0 0 0 3px var(--accent-dim);
  --shadow-sm:       0 1px 2px rgba(0, 0, 0, 0.25);
  --shadow-md:       0 1px 2px rgba(0, 0, 0, 0.35),
                     0 1px 3px rgba(0, 0, 0, 0.25);
  --shadow-lg:       0 8px 24px rgba(0, 0, 0, 0.40);
  --shadow-popover:  0 6px 18px rgba(0, 0, 0, 0.18);    /* dropdowns, panels */
  --shadow-overlay:  0 12px 30px rgba(0, 0, 0, 0.28);   /* modals, big floaters */
  --shadow-card: var(--shadow-md);                       /* legacy alias — kept */

  /* === Surface overlays ===
     Very-low-opacity white tints used for row hovers and faint
     stripes on dark surfaces. Single token avoids the 0.02 / 0.03 /
     0.04 lottery scattered through component rules. */
  --surface-overlay-faint:  rgba(255, 255, 255, 0.02);
  --surface-overlay:        rgba(255, 255, 255, 0.03);
  --surface-overlay-strong: rgba(255, 255, 255, 0.04);

  /* === Motion ===
     One scale for all transition durations + a small ease set. */
  --duration-fast: 100ms;
  --duration-base: 150ms;
  --duration-slow: 250ms;
  --ease-out:      cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-emphasis: cubic-bezier(0.22, 1, 0.36, 1);

  /* --- Panel / menu / page indirection (docs/STYLEGUIDE.md, Law 4) -------
     Components read these instead of getting a second copy of themselves
     inside a theme scope. Dark resolves them to the flat surfaces; the
     hyperbolic block turns them to glass. */
  --panel-fill:          var(--surface-color);
  --panel-fill-raised:   var(--surface-raised);
  --panel-fill-recessed: var(--surface-color);
  --panel-border:        var(--border-color);
  --panel-blur:          none;
  --panel-inset:         none;

  /* Popovers float over content they cannot predict, so they carry their
     own fill rather than the panel one. */
  --menu-fill:   var(--surface-2);
  --menu-border: var(--border);
  --menu-blur:   none;

  /* An input is a work surface: opaque in every theme. */
  --input-bg: var(--surface-raised);

  /* The page column. Transparent here is what keeps dark unchanged. */
  --page-fill:      transparent;
  --page-border:    transparent;
  --page-shadow:    none;
  --page-pad-block: 0;

  /* --- Shadow ladder (Law 2) --------------------------------------------
     Five steps, redefined per theme, nothing else legal. The legacy
     --shadow-sm/md/lg/card aliases are deliberately NOT repointed at these
     yet: that would restyle every card in the app. New work reads the
     ladder; the alias migration is its own change. */
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.25);
  --shadow-2: 0 1px 2px rgba(0, 0, 0, 0.35), 0 2px 8px rgba(0, 0, 0, 0.22);
  --shadow-3: 0 8px 24px rgba(0, 0, 0, 0.40);
  --shadow-4: 0 6px 18px rgba(0, 0, 0, 0.18);
  --shadow-5: 0 12px 30px rgba(0, 0, 0, 0.28);

  /* Onboarding bubbles (design handoff). Law 4: these alias the panel
     indirection tokens, which the hyperbolic block redefines on :root
     itself — so the strip picks up glass in the chamber and flat
     surface in dark with no themed copy of any rule. */
  --bubble-fill:   var(--panel-fill);
  --bubble-border: var(--panel-border);
  --bubble-blur:   var(--panel-blur);
  --bubble-shadow: var(--panel-inset);
  --bubble-rule:   var(--accent);      /* the 3px left rule */
  --bubble-maxw:   68ch;               /* ch, not px — survives larger-text */
  --bubble-travel: var(--travel-md);   /* consumed by motion.css */
}

/* ─────────────────────────────────────────────────────────────────
   User themes
   ─────────────────────────────────────────────────────────────────
   A theme overrides only the shared *primitives* from tokens.css.
   Every bench alias above (`--surface-color`, `--brand-color`, …) and
   every rule below resolves through them, so ~9 values restyle the
   whole app without touching a single component rule.

   Selected in /settings (persisted per user) and applied server-side
   as `data-theme` on <html>. Dark is `:root` — the default — so it
   needs no block here.

   Adding a theme: see docs/THEMES.md (generation prompt + the
   contrast floors a theme must clear).
   ───────────────────────────────────────────────────────────────── */

/* Hyperbolic Time Chamber — the endless white void where a day is a
   year. Deliberately light: the chamber's defining feature is a
   blinding, horizonless expanse. Vaporwave lands in the orchid accent
   and the violet cast through the greys, kept deep enough to stay
   legible (neon magenta fails contrast on white). */
:root[data-theme="hyperbolic"] {
  /* What "high contrast" means in a LIGHT theme. The global
     high-contrast block darkens toward white because the bench used to
     be dark-only; here that would put body copy white on near-white.
     Each theme declares its own ramp and the global block consumes it. */
  --hc-text:           #14101c;
  --hc-text-alt:       #3a3350;
  --hc-border:         #6b6280;
  --hc-border-strong:  #2a2438;

  --bg:           #F7F5FA;  /* the void — pearl, faint violet cast */
  --surface:      #FFFFFF;  /* blinding white — cards float in it */
  --surface-2:    #EFEBF5;  /* lifted lavender tint — code blocks */
  --border:       #DCD5E8;  /* pale lavender hairline */

  --text:         #2A2438;  /* deep violet-charcoal, never pure black */
  --text-muted:   #6B6280;
  --text-faint:   #9A93AC;  /* decorative only — not body copy */

  --accent:       #A62E8A;
  --accent-hover: #C4419F;
  /* Decorative rose (design's dominant accent, #CF7A9E, 96 uses). NEVER
     behind text — 2.3:1 on the pearl bg. --accent above stays the deeper
     magenta because bench uses it as link/badge TEXT (AA). This one is for
     soft fills, gradient washes, and glows only. */
  --accent-glow:  #CF7A9E;

  /* === Bench Design System port (claude.ai/design "Bench Design
     System", tokens/*.css) — everything below is chamber-only and
     rides the existing alias layer; the dark default is untouched.

     Signal set — each has an -ink (AA text on white) and -dim (soft
     fill) variant. Gold = time/frames, mint = the sand/pass, sky =
     info, plum = tertiary. */
  /* Base gold brightened to the design's decorative gold (#E6A63F, 32
     uses) — used only in gradients/fills/borders here, never as text
     (text takes --gold-ink #8A6318, kept AA). */
  --gold:         #E6A63F;
  /* -ink deepened from the DS's #9A6F1E: that measured 4.16:1 on the
     pearl --bg (AA needs 4.5) — the DS checked it on pure white only. */
  --gold-ink:     #8A6318;
  --gold-dim:     rgba(230, 166, 63, 0.14);
  --mint:         #3E9B76;
  --mint-ink:     #2C7C5C;
  --mint-dim:     rgba(62, 155, 118, 0.14);
  --sky:          #3F82C4;
  --sky-ink:      #2E6EAC;
  --sky-dim:      rgba(63, 130, 196, 0.14);
  --plum:         #7B5FD0;
  --plum-dim:     rgba(123, 95, 208, 0.14);

  /* Semantic states re-hued for white (override the dark set) */
  --ok:        var(--mint-ink);
  --ok-dim:    var(--mint-dim);
  --info:      var(--sky-ink);
  --info-dim:  var(--sky-dim);
  --warn:      var(--gold-ink);
  --warn-dim:  var(--gold-dim);
  /* Deepened from the DS's #D8556B viz-fail (3.57:1): bench uses
     --err as TEXT (field errors, hint failures), which needs AA. The
     original stays available for graphics via --err-dim's hue. */
  --err:       #B93049;
  --err-dim:   rgba(216, 85, 107, 0.14);
  /* Soft accent fill rebased onto the design's rose (decorative only —
     used as fills/borders on chips + selected states, never text). */
  --accent-dim: rgba(207, 122, 158, 0.14);

  /* Glass — translucent white fills over the iridescent void. Work
     surfaces (code blocks) stay near-opaque: --code-bg keeps resolving
     to the opaque --surface-2, the DS's load-bearing legibility rule. */
  --glass-alpha:  0.55;
  --glass-blur:   18px;
  --glass-fill:        rgba(255, 255, 255, var(--glass-alpha));
  --glass-fill-raised: rgba(255, 255, 255, calc(var(--glass-alpha) + 0.08));
  /* Recessed fill + hairline: the DS chrome pair (colors.css) — the
     header bar sits BEHIND the floating panels, so it takes the
     dimmer fill and the softer seam. */
  --glass-fill-recessed: rgba(255, 255, 255, calc(var(--glass-alpha) - 0.10));
  /* Popovers float over arbitrary content, so they carry their own alpha
     rather than the panel one — at 0.55 the nav dropdowns were unreadable
     against the void (operator feedback, 2026-08-10). */
  --glass-alpha-menu: 0.88;
  --glass-fill-menu:   rgba(255, 255, 255, var(--glass-alpha-menu));
  --glass-hairline:    rgba(255, 255, 255, 0.55);
  --glass-border:      rgba(255, 255, 255, 0.78);

  /* Depth: soft violet lift instead of the dark theme's black drops */
  --shadow-glass: 0 10px 30px rgba(150, 120, 170, 0.16);
  --shadow-float: 0 24px 60px rgba(120, 110, 160, 0.22);
  --inset-hi:     inset 0 1px 0 rgba(255, 255, 255, 0.9);
  --shadow-sm:      0 2px 8px rgba(150, 120, 170, 0.10);
  --shadow-md:      var(--shadow-glass);
  --shadow-lg:      var(--shadow-float);
  --shadow-card:    var(--shadow-glass);
  --shadow-popover: var(--shadow-float);
  --shadow-overlay: var(--shadow-float);

  /* Geometry — deliberately rounder than the portfolio's crisp 6px:
     panels read as smooth objects floating in the void. */
  --radius-sm:    8px;
  --radius:       14px;
  --radius-card:  20px;
  --radius-input: 14px;

  /* Iridescence — the pearl sky (pastels only, never behind text) */
  --iris-rose:     rgba(255, 206, 227, 0.85);
  --iris-mint:     rgba(200, 238, 223, 0.82);
  --iris-lavender: rgba(215, 206, 246, 0.78);
  --iris-peach:    rgba(255, 232, 206, 0.70);
  --iris-sky:      rgba(206, 224, 247, 0.70);

  /* Decorative gradients — NEVER behind text */
  --grad-spine: linear-gradient(180deg, var(--gold), var(--accent-glow));
  --grad-sand:  linear-gradient(180deg, #DAF1E5, #84D2AC);
  --grad-frame: linear-gradient(135deg, #F6E19A, #C99A34);

  /* --- Folded in from hyperbolic-fixes.css ----------------------------- */

  /* D1 — the browser painted every UA control (checkbox, date input,
     scrollbar) in dark mode because this scope never overrode it. */
  color-scheme: light;
  accent-color: var(--accent);

  /* D3 — a white veil over the radials so text never sits on saturated
     colour. Tune --void-veil, not the radials. */
  --void-veil: rgba(255, 255, 255, 0.55);
  --grad-void:                                                        /* bench-void-allowed */
    linear-gradient(var(--void-veil), var(--void-veil)),               /* bench-void-allowed */
    radial-gradient(52% 42% at 12% -4%, var(--iris-rose), transparent 60%),     /* bench-void-allowed */
    radial-gradient(50% 42% at 86% 2%,  var(--iris-mint), transparent 60%),     /* bench-void-allowed */
    radial-gradient(46% 36% at 52% 0%,  var(--iris-lavender), transparent 60%), /* bench-void-allowed */
    radial-gradient(58% 46% at 94% 72%, var(--iris-peach), transparent 62%),    /* bench-void-allowed */
    radial-gradient(56% 46% at 4% 90%,  var(--iris-sky), transparent 62%),      /* bench-void-allowed */
    linear-gradient(178deg, #FAF5F8 0%, #F1EDF6 44%, #E7F0F4 100%);    /* bench-void-allowed */

  /* D2 — the "pink to mint header gradient" was never a gradient: it was
     saturate() amplifying the void's radials through the glass. */
  --header-saturate: 1.05;

  /* Glass indirection. --glass-border (0.78), not --glass-hairline: with
     --glass-alpha at 0.55 the hairline is byte-identical to --glass-fill,
     so a panel edge disappears into its own fill. */
  --panel-fill:          var(--glass-fill);
  --panel-fill-raised:   var(--glass-fill-raised);
  --panel-fill-recessed: var(--glass-fill-recessed);
  --panel-border:        var(--glass-border);
  --panel-blur:          blur(var(--glass-blur));
  --panel-inset:         var(--inset-hi);

  --menu-fill:   var(--glass-fill-menu);
  --menu-border: var(--border-color);
  --menu-blur:   blur(var(--glass-blur));

  --input-bg: var(--surface);

  --page-fill:      var(--panel-fill);
  --page-border:    var(--panel-border);
  --page-shadow:    var(--shadow-2);
  --page-pad-block: var(--space-6);

  /* Ladder: violet lifts rather than black drops. */
  --shadow-1: 0 2px 8px rgba(150, 120, 170, 0.10);
  --shadow-2: 0 10px 30px rgba(150, 120, 170, 0.16);
  --shadow-3: 0 24px 60px rgba(120, 110, 160, 0.22);
  --shadow-4: 0 24px 60px rgba(120, 110, 160, 0.22);
  --shadow-5: 0 24px 60px rgba(120, 110, 160, 0.22);
}

/* High contrast kills glass everywhere at once — the whole reason the
   indirection above exists. This MUST come after the hyperbolic block:
   both selectors have the same specificity, so source order decides. When
   it sat earlier, the theme block won and --menu-blur stayed at 18px. */
:root[data-high-contrast] {
  --panel-fill:        var(--surface-color);
  --panel-fill-raised: var(--surface-raised);
  --panel-blur:        none;
  --panel-inset:       none;
  --menu-fill:         var(--surface-2);
  --menu-blur:         none;
}

/* The pearl void — layered pastel radials drifting behind content.
   Fixed pseudo-element so text never sits on a gradient directly;
   the drift is one of the DS's two sanctioned ambient motions and
   collapses under reduce-motion (both the OS setting and the bench
   a11y toggle).

   Paint-order note: `html, body` BOTH set an opaque background, and a
   negative-z pseudo paints BETWEEN them (html bg → pseudo → body bg),
   so an opaque body hides the void entirely. Body goes transparent in
   this theme; html keeps the pearl base under the radials. */
:root[data-theme="hyperbolic"] body { background: transparent; }
:root[data-theme="hyperbolic"] body::before {
  content: "";
  position: fixed;
  inset: -6%;
  z-index: -1;
  pointer-events: none;
  background: var(--grad-void);
  animation: bench-drift 24s ease-in-out infinite;
}
@keyframes bench-drift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(-2%, 1.5%, 0) scale(1.08); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  :root[data-theme="hyperbolic"] body::before { animation: none; }
}
:root[data-theme="hyperbolic"][data-reduce-motion] body::before { animation: none; }

/* Frosted panels — the floating surfaces get the full glass recipe
   (translucent fill + backdrop blur + lit top edge). Work surfaces
   (code, prose editors) are excluded by design: they keep the opaque
   token fills for legibility. */
:root[data-theme="hyperbolic"] .problem-card,
:root[data-theme="hyperbolic"] .next-action,
:root[data-theme="hyperbolic"] .settings__panel,
:root[data-theme="hyperbolic"] .fb-panel {
  background: var(--glass-fill);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.45);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.45);
  border-color: var(--glass-border);
  box-shadow: var(--shadow-glass), var(--inset-hi);
}
:root[data-theme="hyperbolic"] .problem-card:hover {
  box-shadow: var(--shadow-float), var(--inset-hi);
  border-color: var(--accent);
}
/* Command palette in the chamber. The default dialog uses --surface-2,
   which resolves to the lavender tint here and read washed-out and flat
   (operator feedback, 2026-07-21). Give it the full glass treatment:
   violet scrim, raised frosted dialog, orchid-tinted active row. */
:root[data-theme="hyperbolic"] .palette {
  background: rgba(42, 36, 56, 0.35); /* --text at 35% — violet scrim */
}
:root[data-theme="hyperbolic"] .palette__dialog {
  background: var(--glass-fill-raised);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.45);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.45);
  border-color: var(--glass-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-float), var(--inset-hi);
}
:root[data-theme="hyperbolic"] .palette__input {
  border-bottom-color: var(--border);
}
:root[data-theme="hyperbolic"] .palette__item.is-active {
  background: var(--accent-dim);
}
:root[data-theme="hyperbolic"] .palette__group:not(:first-child) {
  border-top-color: var(--border);
}

/* Header bar — the DS shell's .hdr (Bench App Preview, shell CSS):
   recessed frosted glass over the void with a bright hairline seam.
   The backdrop-filter forces a stacking context, which would trap the
   nav dropdowns' z-index inside the header and let positioned main
   content paint over them — the explicit z-index (matching the
   dropdowns' own 30) keeps the header layer above the page. */
:root[data-theme="hyperbolic"] .site-header {
  position: relative;
  z-index: 30;
  background: var(--glass-fill-recessed);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--header-saturate));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--header-saturate));
  border-bottom-color: var(--glass-hairline);
}

/* Palette hint — the DS shell's ⌘K affordance is a translucent mono
   pill (.pill: glass border, pill radius, frosted fill). Hover/focus
   restated because this themed rule outweighs the base pseudo-class
   rules on specificity. */
:root[data-theme="hyperbolic"] .nav__palette-hint {
  background: var(--glass-fill);
  border-color: var(--glass-border);
  border-radius: var(--radius-pill);
}
:root[data-theme="hyperbolic"] .nav__palette-hint:hover,
:root[data-theme="hyperbolic"] .nav__palette-hint:focus-visible {
  border-color: var(--accent);
}

/* High-contrast a11y toggle beats atmosphere: glass goes opaque. */
:root[data-theme="hyperbolic"][data-high-contrast] .problem-card,
:root[data-theme="hyperbolic"][data-high-contrast] .next-action,
:root[data-theme="hyperbolic"][data-high-contrast] .settings__panel,
:root[data-theme="hyperbolic"][data-high-contrast] .fb-panel,
:root[data-theme="hyperbolic"][data-high-contrast] .nav__group-dropdown,
:root[data-theme="hyperbolic"][data-high-contrast] .palette__dialog,
:root[data-theme="hyperbolic"][data-high-contrast] .site-header,
:root[data-theme="hyperbolic"][data-high-contrast] .nav__palette-hint {
  background: var(--surface);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
:root[data-theme="hyperbolic"][data-high-contrast] .site-header {
  border-bottom-color: var(--border-color);
}
/* The near-white glass border vanishes on the opaque surface. */
:root[data-theme="hyperbolic"][data-high-contrast] .nav__palette-hint {
  border-color: var(--border-color);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  background: var(--background-color);
  color: var(--text-color);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Accessibility preferences (toggled from /settings → stored on
   users.settings_json.a11y, applied as data-attributes on <html>).

   Earlier values were too subtle (user feedback #31): a 9% font bump
   is invisible at-a-glance, and adjusting only --text-alt-color
   produces a barely-perceptible contrast difference. These changes:

   - larger-text: 16px → 19px (~19% bump; lines up with WCAG's "large
     text" threshold of 18.66px / 14pt-bold).
   - high-contrast: bumps PRIMARY text color too (not just alt), uses
     pure black/white on body text, and thickens focus rings so
     keyboard navigation is unmistakable.
   - reduce-motion: also respects the system-level
     prefers-reduced-motion media query, so users who set this at the
     OS level get it for free without toggling here. */

html[data-larger-text="1"] { font-size: 19px; }
html[data-larger-text="1"] code, html[data-larger-text="1"] pre { font-size: 0.95em; }

/* Explicit user toggle. */
html[data-reduce-motion="1"] *,
html[data-reduce-motion="1"] *::before,
html[data-reduce-motion="1"] *::after {
  animation-duration: 0.001s !important;
  transition-duration: 0.001s !important;
  scroll-behavior: auto !important;
}
/* OS-level preference: respected without requiring the toggle. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001s !important;
    transition-duration: 0.001s !important;
    scroll-behavior: auto !important;
  }
}
html[data-reduce-motion="1"] .stat-pentagon__value { filter: none; }

/* High-contrast: max-contrast pure white text + stronger borders +
   thicker focus rings. Bench is dark-only now; the old light-theme
   high-contrast branch is gone. */
html[data-high-contrast="1"] {
  /* The fallbacks are the dark-theme ramp, which is what this block used
     to hardcode. A theme that needs a different one (any LIGHT theme —
     see hyperbolic) declares --hc-* and wins here without a
     theme-scoped rule. */
  --text-color:          var(--hc-text, #ffffff);
  --text-alt-color:      var(--hc-text-alt, #e6e8ee);
  --border-color:        var(--hc-border, #8a8fa0);
  --border-color-strong: var(--hc-border-strong, #c4c7d0);
  --focus-ring: 0 0 0 3px var(--accent);
}
html[data-high-contrast="1"] a {
  text-decoration: underline;
  text-underline-offset: 2px;
}
html[data-high-contrast="1"] *:focus-visible {
  outline: 3px solid var(--brand-color);
  outline-offset: 2px;
}

h1, h2, h3, h4 { color: var(--heading-color); line-height: 1.25; margin: 0 0 var(--space-4); letter-spacing: -0.005em; }
h1 { font-size: var(--text-3xl); font-weight: 700; letter-spacing: -0.015em; }
h2 { font-size: var(--text-xl); font-weight: 600; }
h3 { font-size: var(--text-md); font-weight: 600; }

/* Anchors — portfolio motif: amber, no underline by default. Hover
   shifts the color shade (and prose contexts add underline; see
   `.md a` / `.muted a` rules below). Component links (buttons,
   cards, header nav) get their own hover via the component class —
   the global `a:hover` doesn't impose an underline that would
   conflict with their chrome. */
a { color: var(--accent); text-decoration: none; border-bottom: none; }
a:hover { color: var(--accent-hover); }
a:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* Prose anchors — markdown-rendered content (`.md` containers like
   problem prompts, content items, reflection notes). These read as
   inline links inside running text; portfolio uses underline-on-hover
   for the affordance. */
.md a,
.problem__prompt a,
.refs__list a,
.writing-body a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--accent-dim);
  text-underline-offset: 3px;
}
.md a:hover,
.problem__prompt a:hover,
.refs__list a:hover,
.writing-body a:hover {
  text-decoration-color: var(--accent-hover);
  color: var(--accent-hover);
}

.muted { color: var(--text-muted); font-size: var(--text-sm); }

/* CTA visibility — anchors in muted contexts (page metadata, settings
   panels, hints) read as quiet links until you hover. Underlined-by-
   default at lower contrast so the affordance is visible without
   pulling weight from primary content; brightens to accent on hover. */
a.muted, .muted a, .today__hint a, .page__meta a {
  color: var(--text-muted);
  text-decoration: underline;
  text-decoration-color: var(--text-faint);
  text-underline-offset: 3px;
  border-bottom: none;
}
a.muted:hover, .muted a:hover, .today__hint a:hover, .page__meta a:hover {
  color: var(--accent-hover);
  text-decoration-color: var(--accent-hover);
}

/* Arrow-suffixed CTAs ("retake →", "manage JDs →") — amber, weight
   bumps on hover (not color, which is already accent). */
.action-link {
  color: var(--accent);
  font-weight: 500;
  text-decoration: none;
  border-bottom: none;
}
.action-link:hover {
  color: var(--accent-hover);
  font-weight: 600;
}

.container {
  max-width: var(--maxw-wide);
  margin: 0 auto;
  padding: 0 var(--space-5);
}

/* Narrower variant — applied via the `main_class` block in base.html.
   --maxw (720px) is portfolio's prose width — comfortable line length
   for the bench's prose-heavy surfaces (home, reading, problem,
   reflect). */
.container--narrow {
  max-width: var(--maxw);
}

.site-header {
  border-bottom: 1px solid var(--border-color);
  padding: var(--space-4) 0;
  margin-bottom: var(--space-7);
}
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
/* All direct-child anchors of .site-header (the public-page chrome:
   `about`, `docs ↗`, possibly more) inherit the muted-link styling
   from `.muted a`. In the flex row they're still vulnerable to
   shrinking — pin them to their content width so they never wrap
   mid-word into ugly stacks. Suppress the prose-style underline
   here too; in the header chrome these read as nav, not prose. */
.site-header .container > a,
.site-header .container > .alpha-pill {
  flex-shrink: 0;
  white-space: nowrap;
}
.site-header .container > a.muted {
  text-decoration: none;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-muted);
}
.site-header .container > a.muted:hover {
  color: var(--accent-hover);
  text-decoration: none;
}
.brand {
  font-weight: 700;
  border: none;
  white-space: nowrap;
  flex-shrink: 0;
}
/* Alpha / invite-only pill — sits next to the brand on public pages
   (login, request-access, access-denied). Pinned width via
   white-space: nowrap + flex-shrink: 0 so the row can't squeeze it
   into a circle when chrome gets crowded. */
.alpha-pill {
  display: inline-flex;
  align-items: center;
  margin-left: var(--space-2);
  margin-right: auto;
  padding: 2px 8px;
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  color: var(--text-muted);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: help;
  user-select: none;
  white-space: nowrap;
  flex-shrink: 0;
}
.theme-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: transparent;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  padding: var(--space-1) var(--space-3);
  color: var(--text-color);
  cursor: pointer;
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: 1;
}
.theme-toggle:hover { border-color: var(--accent); color: var(--accent); }
.theme-toggle__icon { display: inline-flex; align-items: center; }
/* Bench is dark-only after the portfolio visual alignment (2026-05-27).
   Sun icon hidden permanently; moon icon always shown. The toggle
   button still flips localStorage, but the visual no longer pretends
   light mode is available. The hide-the-button decision is queued
   with the nav redesign per operator's note. */
.theme-toggle__icon--sun  { display: none; }
.theme-toggle__icon--moon { display: inline-flex; }
.theme-toggle__label { font-variant: small-caps; letter-spacing: 0.04em; }

.today { margin-bottom: var(--space-7); }
.card-stack { display: flex; flex-direction: column; gap: var(--space-4); }

.problem-card {
  display: block;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-5);
  color: var(--text-color);
  text-decoration: none;
  box-shadow: var(--shadow-card);
  transition: border-color var(--duration-fast) ease, box-shadow var(--duration-fast) ease;
}
.problem-card:hover {
  border-color: var(--brand-color);
  color: var(--text-color);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25), 0 4px 12px var(--accent-dim);
}
.problem-card__head { display: flex; gap: var(--space-2); margin-bottom: var(--space-3); flex-wrap: wrap; }
.problem-card__title { margin: 0 0 var(--space-2); font-size: var(--text-lg); font-weight: 700; }
.problem-card__tags { margin-top: var(--space-2); display: flex; gap: var(--space-2); flex-wrap: wrap; }
.problem-card__why { margin-top: var(--space-3); font-size: var(--text-sm); color: var(--text-alt-color); }
.problem-card__why summary { cursor: pointer; }
.problem-card__why ul { margin: var(--space-2) 0 0; padding-left: var(--space-5); }

/* Badges + tags — portfolio motif: small uppercase monospace with a
   faint border. Quiet by default; accent only when the badge IS
   surfacing accent state (e.g., the active difficulty). */
.badge {
  display: inline-block;
  padding: 2px var(--space-2);
  font-size: var(--text-xs);
  border-radius: var(--radius);
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
/* Type-specific badges use color to differentiate problem types, but
   keep within the amber-or-quiet palette. The debug/read variants
   originally used hardcoded oranges/cyans — collapse to the shared
   palette: muted for compose/read, accent for debug (the "intervention"
   problem type that warrants visual emphasis). */
.badge--code_compose { color: var(--text-muted); border-color: var(--border); }
.badge--code_debug   { color: var(--accent); border-color: var(--accent-dim); }
.badge--code_read    { color: var(--text-muted); border-color: var(--border); }

.tag {
  display: inline-block;
  font-size: var(--text-xs);
  color: var(--text-muted);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2px var(--space-2);
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.recent-list { list-style: none; padding: 0; margin: 0; }
.recent-list li { padding: var(--space-2) 0; border-bottom: 1px solid var(--border-color); font-size: var(--text-sm); }
.recent-list li:last-child { border-bottom: none; }

.problem__head { margin-bottom: var(--space-6); }
.problem__meta { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-3); }
.warmup-banner {
  background: var(--surface-color);
  border-left: 3px solid var(--accent-color);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
}
.problem__prompt.md {
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-6);
}
.md p { margin: 0 0 var(--space-3); }
.md p:last-child { margin-bottom: 0; }
.md code {
  background: var(--code-bg);
  padding: 1px 6px;
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: 0.875em;
}
.md pre {
  background: var(--code-bg);
  border-radius: var(--radius-input);
  padding: var(--space-3) var(--space-4);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.5;
}
.md pre code { background: transparent; padding: 0; font-size: inherit; }
.md ul, .md ol { margin: 0 0 var(--space-3); padding-left: var(--space-5); }
.md li { margin-bottom: var(--space-1); }
.md a { color: var(--brand-color); border-bottom: 1px solid transparent; }
.md a:hover { border-bottom-color: var(--brand-color); }
.md strong { color: var(--heading-color); }
.md h1, .md h2, .md h3, .md h4 { margin: var(--space-4) 0 var(--space-2); }
.md blockquote {
  border-left: 3px solid var(--border-color);
  padding-left: var(--space-3);
  margin: var(--space-3) 0;
  color: var(--text-alt-color);
}

.solve label { display: block; font-size: var(--text-sm); color: var(--text-alt-color); margin-bottom: var(--space-2); }
.solve textarea {
  width: 100%;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.5;
  padding: var(--space-4);
  background: var(--code-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
  resize: vertical;
  tab-size: 4;
  transition: border-color var(--duration-fast) ease, box-shadow var(--duration-fast) ease;
}
.solve textarea:focus {
  outline: none;
  border-color: var(--brand-color);
  box-shadow: var(--focus-ring);
}

/* Global form-element legibility pass. Light mode in particular was
   suffering from inputs/textareas that blended into the surface; this
   pulls them onto a raised background with stronger borders and an
   obvious focus ring. */
input[type="text"],
input[type="search"],
input[type="email"],
input[type="number"],
input[type="url"],
input[type="password"],
select,
textarea {
  font-family: inherit;
  /* --input-bg, not --surface-raised: an input is a work surface and stays
     opaque in every theme (docs/STYLEGUIDE.md, legibility carve-out). */
  background: var(--input-bg, var(--surface-raised));
  border: 1px solid var(--border-color);
  color: var(--text-color);
  border-radius: var(--radius-input);
  transition: border-color var(--duration-fast) ease, box-shadow var(--duration-fast) ease;
}
input[type="text"]:focus,
input[type="search"]:focus,
input[type="email"]:focus,
input[type="number"]:focus,
input[type="url"]:focus,
input[type="password"]:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--brand-color);
  box-shadow: var(--focus-ring);
}
input::placeholder, textarea::placeholder {
  color: var(--text-alt-color);
  opacity: 0.7;
}

.lang-toggle { margin-bottom: var(--space-3); display: flex; gap: var(--space-4); font-size: var(--text-sm); }
.editor-tabs {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
}
.editor-tab {
  background: transparent;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-alt-color);
  cursor: pointer;
  font-family: inherit;
  font-size: var(--text-sm);
  padding: 4px var(--space-3);
}
.editor-tab:hover {
  border-color: var(--brand-color);
  color: var(--brand-color);
}
.editor-tab.is-active {
  border-color: var(--brand-color);
  background: var(--accent-dim);
  color: var(--heading-color);
  font-weight: 600;
}
.editor-panel__hint {
  margin: 0 0 var(--space-2);
}
.confidence { margin: var(--space-5) 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); font-size: var(--text-sm); }
.confidence span { color: var(--text-alt-color); }

.aux {
  margin: var(--space-4) 0;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-color);
}
.aux summary { cursor: pointer; font-size: var(--text-sm); color: var(--text-alt-color); }
.aux pre {
  background: var(--code-bg);
  border-radius: var(--radius-input);
  padding: var(--space-3);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.5;
}
.aux button {
  background: transparent;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  padding: 2px var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-alt-color);
  cursor: pointer;
  margin-top: var(--space-2);
}

/* ─── Button grammar (WS2 grammar pass, 2026-05-28) ─────────────
   One shared `.btn` base + 4 modifiers covers every button in the
   app. Legacy class names (.primary, .primary-link, .muted-button,
   .bordered-button, .btn-danger-link) ride the same rules via the
   shared selectors below — no per-template churn required, new
   markup uses the new vocabulary.

     .btn.btn--primary  — amber fill, near-black text. The CTA.
     .btn.btn--ghost    — transparent, bordered, muted text. Default
                          action. Hover brightens border to amber.
     .btn.btn--danger   — red border + text. Destructive operations.
     .btn.btn--link     — looks like an anchor; for inline triggers
                          inside running text (forms that don't
                          warrant a bordered button).

   Anchors styled as buttons take .btn.btn--primary directly. The
   previous .primary-link alias resolves to .btn.btn--primary.

   Sizes: default. Add .btn--sm for chip-sized buttons (table-row
   actions, dense inboxes). Add .btn--block for full-width within
   a card. */

.btn,
button.primary,
.primary-link,
.muted-button,
.bordered-button,
.btn-danger-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  appearance: none;
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-5);
  font-family: inherit;
  font-size: var(--text-base);
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  text-decoration: none;
  transition: background var(--duration-fast) ease,
              border-color var(--duration-fast) ease,
              color var(--duration-fast) ease,
              box-shadow var(--duration-fast) ease,
              transform var(--duration-fast) ease;
}
.btn:focus-visible,
button.primary:focus-visible,
.primary-link:focus-visible,
.muted-button:focus-visible,
.bordered-button:focus-visible,
.btn-danger-link:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.btn:active,
button.primary:active,
.primary-link:active,
.muted-button:active,
.bordered-button:active {
  transform: translateY(0.5px);
}
.btn[disabled],
.btn[aria-busy="true"],
button.primary[disabled],
button.primary[aria-busy="true"] {
  opacity: 0.6;
  cursor: not-allowed;
}

/* Primary — amber fill. */
.btn--primary,
button.primary,
.primary-link {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
}
.btn--primary:hover,
button.primary:hover,
.primary-link:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--bg);
}

/* Ghost — bordered transparent. Default for non-primary actions. */
.btn--ghost,
.muted-button,
.bordered-button {
  background: transparent;
  color: var(--text-muted);
  border-color: var(--border-color);
  font-size: var(--text-sm);
  font-weight: 500;
  padding: var(--space-2) var(--space-4);
}
.btn--ghost:hover,
.muted-button:hover,
.bordered-button:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* Danger — red text + border. */
.btn--danger,
.btn-danger-link {
  background: transparent;
  color: var(--err);
  border-color: var(--err-dim);
  font-size: var(--text-sm);
  font-weight: 500;
  padding: var(--space-2) var(--space-4);
}
.btn--danger:hover,
.btn-danger-link:hover {
  border-color: var(--err);
  background: var(--err-dim);
  color: var(--err);
}

/* Link — inline-text trigger that looks like an anchor. */
.btn--link {
  background: transparent;
  border-color: transparent;
  color: var(--accent);
  padding: 0;
  font-size: inherit;
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--accent-dim);
  text-underline-offset: 3px;
}
.btn--link:hover {
  color: var(--accent-hover);
  text-decoration-color: var(--accent-hover);
  transform: none;
}

/* Size + width modifiers */
.btn--sm {
  font-size: var(--text-xs);
  padding: var(--space-1) var(--space-3);
}
.btn--block {
  width: 100%;
}

.htmx-indicator { display: none; margin-left: var(--space-3); color: var(--text-alt-color); }
.htmx-request .htmx-indicator { display: inline; }

.result {
  margin-top: var(--space-5);
  padding: var(--space-4);
  border-radius: var(--radius-card);
  border: 1px solid var(--border-color);
  background: var(--surface-color);
}
.result__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.result__verdict {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  letter-spacing: 0.08em;
}
.result__score {
  font-size: var(--text-sm);
  color: var(--text-alt-color);
}
.result__score strong { color: var(--heading-color); }
.result--pass { border-color: var(--ok); }
.result--pass .result__verdict { color: var(--ok); }
.result--partial { border-color: var(--warn); }
.result--partial .result__verdict { color: var(--warn); }
.result--fail .result__verdict { color: var(--err); }
.result__message {
  margin: 0 0 var(--space-3);
  color: var(--text-alt-color);
  font-size: var(--text-sm);
}
.result__output {
  background: var(--code-bg);
  padding: var(--space-3);
  border-radius: var(--radius-input);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  white-space: pre-wrap;
  margin: 0;
}
.result__nav { margin-top: var(--space-4); font-size: var(--text-sm); }

/* LLM-graded review panel. Sits beneath the test result. */
.review {
  margin-top: var(--space-5);
  padding: var(--space-5);
  border: 1px solid var(--border-color);
  border-left: 3px solid var(--brand-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
}
.review__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}
.review__title { margin: 0; font-size: var(--text-base); font-weight: 600; }
.review__summary {
  font-size: var(--text-sm);
  line-height: 1.6;
  margin: 0 0 var(--space-5);
}
.review__phases {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.review-phase { }
.review-phase__name {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-alt-color);
  margin: 0 0 var(--space-2);
  font-weight: 700;
}
.review-phase__line {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: var(--space-2);
  align-items: start;
  margin: 0 0 var(--space-2);
  font-size: var(--text-sm);
  line-height: 1.5;
}
.review-phase__line:last-child { margin-bottom: 0; }
.review-phase__label {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text-alt-color);
  text-align: center;
}
.review-phase__line--q { color: var(--text-alt-color); font-style: italic; }
.review-phase__line--q .review-phase__label { color: var(--accent-color); font-style: normal; }

.review--skipped {
  border-left-color: var(--border-color);
}
.review--skipped p { margin: 0; font-size: var(--text-sm); }

/* Interview mode — strict timed variant of the problem flow. */
.interview-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  background: var(--surface-color);
  border: 1px solid var(--brand-color);
  border-radius: var(--radius-card);
  padding: var(--space-3) var(--space-5);
  margin-bottom: var(--space-4);
}
.interview-banner__left { display: flex; align-items: baseline; gap: var(--space-3); }
.interview-banner__label {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--brand-color);
  font-family: var(--font-mono);
}
.interview-banner__timer {
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--heading-color);
  font-variant-numeric: tabular-nums;
}
.interview-banner__timer--over { color: var(--err); }

.interview-alert {
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-input);
  border-left: 3px solid var(--text-alt-color);
  background: var(--surface-color);
  font-size: var(--text-sm);
}
.interview-alert--soft   { border-left-color: var(--accent-color); }
.interview-alert--warn   { border-left-color: var(--warn); }
.interview-alert--danger { border-left-color: var(--err); color: var(--err); }

.interview-aids-hidden {
  border: 1px dashed var(--border-color);
  border-radius: var(--radius-input);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-4) 0;
  font-size: var(--text-sm);
}

.problem__try-interview {
  margin: var(--space-3) 0 0;
  font-size: var(--text-sm);
}
.problem__try-interview a {
  color: var(--text-color);
  border-bottom: 1px dotted var(--border-color);
}
.problem__try-interview a:hover {
  color: var(--brand-color);
  border-bottom-color: var(--brand-color);
}

.problem-card-wrap {
  display: flex;
  flex-direction: column;
}
.problem-card__interview-link {
  align-self: flex-end;
  margin-top: var(--space-1);
  padding: 4px var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-alt-color);
  font-family: var(--font-mono);
  border: none;
}
.problem-card__interview-link:hover { color: var(--brand-color); border: none; }

/* Algo-interviews rubric signal grid — interview-mode reviews only. */
.rubric-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-2);
  margin: 0 0 var(--space-5);
}
.rubric-cell {
  padding: var(--space-3);
  border-radius: var(--radius-input);
  background: var(--background-color);
  border: 1px solid var(--border-color);
  border-top-width: 2px;
}
.rubric-cell--strong { border-top-color: var(--brand-color); }
.rubric-cell--mid    { border-top-color: var(--accent-color); }
.rubric-cell--weak   { border-top-color: var(--text-alt-color); opacity: 0.85; }
.rubric-cell__label {
  display: block;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-alt-color);
  font-weight: 700;
  margin-bottom: 4px;
}
.rubric-cell__value {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--heading-color);
}
.rubric-cell--strong .rubric-cell__value { color: var(--brand-color); }
.rubric-cell--mid    .rubric-cell__value { color: var(--accent-color); }
.rubric-cell--weak   .rubric-cell__value { color: var(--text-alt-color); }

/* Header navigation — primary site nav.
   Linear-relaxed: simple horizontal nav with subtle active state. */
.site-header .container {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}
.brand { margin-right: var(--space-4); }
.header-nav {
  display: flex;
  gap: var(--space-4);
  flex: 1;
  align-items: center;
  flex-wrap: wrap;
  min-width: 0;
}
.header-controls {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Header icon button — used for the admin-only feedback-inbox icon
   sitting next to the profile menu + theme toggle. Same visual
   weight as .theme-toggle: bordered, transparent, muted-by-default,
   amber on hover/focus. Square so it reads as a glyph, not a label. */
.header-icon {
  position: relative;        /* anchor for .header-icon__badge */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-alt-color);
  text-decoration: none;
  border-bottom: none;       /* defeat the global a { border-bottom } if any */
  transition: color var(--duration-fast) ease, border-color var(--duration-fast) ease;
}
.header-icon:hover,
.header-icon:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
  text-decoration: none;
}
.header-icon:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* Notification badge — operator review 2026-05-28. Shown on the
   inbox icon when there's an open queue. Amber pill anchored to the
   top-right corner. Renders cleanly through ~99; counts past that
   wrap and look ugly but the inbox at that volume has bigger problems
   than badge layout. */
.header-icon--has-badge { border-color: var(--accent-dim); }
.header-icon__badge {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 18px;
  text-align: center;
  letter-spacing: 0;
  pointer-events: none;
}
.header-nav__link {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-alt-color);
  border: none;
  padding: 4px 0;
  position: relative;
  transition: color var(--duration-fast) ease;
}
.header-nav__link:hover {
  color: var(--text);
  text-decoration: none;
}
.header-nav__link.is-active {
  color: var(--heading-color);
}
.header-nav__link.is-active::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -10px;
  height: 2px;
  background: var(--brand-color);
  border-radius: var(--radius-sm);
}

/* Hybrid grouped nav (WS2 port, operator pick 2026-05-28).
   The .nav--hybrid modifier on .header-nav switches the layout
   from a flat row of links to a mix: single top-level links plus
   .nav__group dropdowns. Each .nav__group contains a trigger
   native summary + a dropdown panel (no JS required to toggle). The trigger styles
   intentionally mirror .header-nav__link so the row reads as one
   nav, not "links plus buttons." */
.nav__group {
  position: relative;
}
.nav__group-trigger {
  appearance: none;
  background: transparent;
  border: none;
  color: var(--text-alt-color);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 500;
  padding: var(--space-1) 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  position: relative;
  transition: color var(--duration-fast) ease;
}
.nav__group-trigger::after {
  content: "▾";
  font-size: var(--text-2xs);
  opacity: 0.6;
}
.nav__group-trigger:hover {
  color: var(--text);
}
.nav__group-trigger.is-active {
  color: var(--heading-color);
}
.nav__group-trigger.is-active::before {
  content: "";
  position: absolute;
  left: 0;
  right: var(--space-3);  /* don't underline the chevron */
  bottom: -10px;
  height: 2px;
  background: var(--brand-color);
  border-radius: var(--radius-sm);
}
.nav__group-trigger:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}
.nav__group-dropdown {
  position: absolute;
  top: calc(100% + var(--space-3));
  left: 0;
  min-width: 200px;
  padding: var(--space-2);
  background: var(--menu-fill);
  -webkit-backdrop-filter: var(--menu-blur);
  backdrop-filter: var(--menu-blur);
  border: 1px solid var(--menu-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-popover);
  display: none;
  z-index: 30;
}
/* Native disclosures expose their actual expanded state to assistive tech. */
.nav__group[open] .nav__group-dropdown {
  display: block;
}
.nav__group-trigger::-webkit-details-marker { display: none; }
.nav__group-link {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
}
.nav__group-link:hover {
  color: var(--text);
  background: var(--surface);
}
.nav__group-link:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.profile-menu {
  position: relative;
}
.profile-menu__trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 4px 10px 4px 6px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-pill);
  background: var(--background-color);
  color: var(--text-color);
  cursor: pointer;
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: 1;
}
.profile-menu__trigger:hover,
.profile-menu.is-open .profile-menu__trigger {
  border-color: var(--brand-color);
  color: var(--heading-color);
}
.profile-menu__trigger:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.profile-menu__initial {
  width: 1.45rem;
  height: 1.45rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-color);
  background: var(--surface-color);
  font-size: var(--text-xs);
  font-weight: 700;
}
.profile-menu__trigger-label {
  font-weight: 500;
  color: var(--text-alt-color);
}

.profile-menu__dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 236px;
  padding: var(--space-2);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-raised);
  box-shadow: var(--shadow-card);
  z-index: 30;
}
.profile-menu__signed-in {
  margin: 0 0 var(--space-2);
  padding: var(--space-2);
  color: var(--text-alt-color);
  font-size: var(--text-xs);
}
.profile-menu__email {
  display: block;
  margin-top: 2px;
  color: var(--text-color);
  font-family: var(--font-mono);
  overflow-wrap: anywhere;
}
.profile-menu__section {
  margin: var(--space-2) var(--space-2) var(--space-1);
  color: var(--text-alt-color);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.profile-menu__item {
  display: block;
  width: 100%;
  padding: var(--space-2);
  border: none;
  border-radius: var(--radius-input);
  background: transparent;
  color: var(--text-color);
  font-family: inherit;
  font-size: var(--text-sm);
  text-align: left;
  cursor: pointer;
}
.profile-menu__item:hover {
  color: var(--heading-color);
  background: var(--surface-color);
}
.profile-menu__item:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.profile-menu__item,
.profile-menu__item:hover {
  border-bottom: none;
  text-decoration: none;
}
.profile-menu__separator {
  border: 0;
  border-top: 1px solid var(--border-color);
  margin: var(--space-2) 0;
}
.profile-menu__signout {
  margin: 0;
}

.site-header { padding: var(--space-5) 0; }

/* Generic page scaffolding — used by /skills, /library, /settings. */
.page { max-width: 920px; margin: 0 auto; }
.page__head { margin-bottom: var(--space-7); }
.page__title { font-size: var(--text-4xl); margin: 0 0 var(--space-2); letter-spacing: -0.015em; }
.page__meta { color: var(--text-alt-color); font-size: var(--text-sm); margin: 0; }
.page__section { margin-bottom: var(--space-7); }
.page__section--centered { display: flex; justify-content: center; }
.page__section--filters { margin-bottom: var(--space-6); }

/* /aim — consolidated Skills + JDs + Credentials surfaces. */
.page--aim { max-width: 860px; }
.aim-details {
  margin-bottom: var(--space-5);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  /* D10 — a featured card is lifted, not outlined in the selection colour.
     The accent border on [open] is correct and stays: it means "open". */
  box-shadow: var(--shadow-2);
  overflow: clip;
}
.aim-details[open] {
  border-color: var(--brand-color);
}
.aim-details__summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
}
.aim-details__summary::-webkit-details-marker { display: none; }
.aim-details__summary::after {
  content: "+";
  color: var(--text-alt-color);
  font-size: var(--text-md);
  line-height: 1;
}
.aim-details[open] > .aim-details__summary::after { content: "−"; }
.aim-details__title {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--heading-color);
}
.aim-details__meta {
  font-size: var(--text-sm);
  color: var(--text-alt-color);
}
.aim-details__body {
  padding: 0 var(--space-6) var(--space-6);
  border-top: 1px solid var(--border-color);
}

.aim-stand-grid {
  display: grid;
  grid-template-columns: minmax(280px, 1fr) 2fr;
  gap: var(--space-5);
  align-items: start;
}
.aim-stand-grid__chart {
  justify-self: start;
  width: 100%;
}
.aim-stand-grid__chart .stat-pentagon {
  margin: 0;
  max-width: 420px;
}
.aim-stand-grid__axes .section-label {
  margin-top: var(--space-2);
}

.aim-axis-row {
  border: 1px solid transparent;
  border-radius: var(--radius-input);
  padding: var(--space-2);
  margin-inline: calc(-1 * var(--space-2));
  transition: border-color var(--duration-fast) ease, background-color var(--duration-fast) ease;
}
.aim-axis-row:hover,
.aim-axis-row.is-highlighted {
  background: var(--surface-raised);
  border-color: var(--brand-color);
}
.aim-axis-row.is-highlighted .axis-row__name {
  color: var(--heading-color);
  font-weight: 600;
}
.aim-axis-row.is-highlighted .axis-row__bar {
  border-color: var(--brand-color);
  background: var(--background-color);
}

.aim-stand__evidence {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-raised);
  padding: var(--space-4);
}
.aim-stand__evidence .section-label {
  margin-top: 0;
}

.aim-calibration {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-raised);
  padding: var(--space-4);
}
.aim-calibration .section-label {
  margin-top: 0;
}
.aim-calibration-chart-wrap {
  overflow-x: auto;
  padding-bottom: var(--space-2);
}
.aim-calibration-chart {
  width: 100%;
  max-width: 560px;
  height: auto;
  display: block;
}
.aim-calibration-chart__plot {
  fill: var(--surface-color);
  stroke: var(--border-color);
}
.aim-calibration-chart__grid {
  stroke: var(--border-color);
  stroke-width: 1;
  opacity: 0.45;
}
.aim-calibration-chart__diag {
  stroke: var(--brand-color);
  stroke-width: 1.6;
  stroke-dasharray: 6 5;
  opacity: 0.85;
}
.aim-calibration-chart__point {
  fill: var(--accent-color);
  stroke: var(--background-color);
  stroke-width: 1.5;
  transition: transform var(--duration-fast) ease, opacity var(--duration-fast) ease;
  transform-origin: center;
}
.aim-calibration-chart__point:hover {
  transform: scale(1.08);
}
.aim-calibration-chart__tick,
.aim-calibration-chart__label {
  fill: var(--text-alt-color);
  font-family: var(--font-mono);
  font-size: 10px;
}
.aim-calibration-chart__label {
  font-size: 11px;
}

@media (max-width: 720px) {
  .aim-stand-grid { grid-template-columns: 1fr; }
  .aim-details__summary { padding: var(--space-4); }
  .aim-details__body { padding: 0 var(--space-4) var(--space-5); }
}

/* Onboarding */
.onboarding { max-width: 720px; margin: 0 auto; }
.onboarding__head { margin-bottom: var(--space-7); }
.onboarding__lede { color: var(--text-color); font-size: var(--text-md); line-height: 1.6; }
.onboarding__panel {
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-5);
}
.onboarding__phases { padding-left: var(--space-5); margin: var(--space-3) 0; }
.onboarding__phases li { margin-bottom: var(--space-2); }
.onboarding__phases li span { color: var(--brand-color); font-weight: 700; }
.onboarding__cta { margin-top: var(--space-4); }
.onboarding__skip { margin-top: var(--space-3); }

/* Two-column path picker on /onboarding. Stacks on narrow viewports. */
.onboarding__paths {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
  margin-top: var(--space-4);
}
@media (max-width: 720px) {
  .onboarding__paths { grid-template-columns: 1fr; }
}
.onboarding__path {
  padding: var(--space-5);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  display: flex;
  flex-direction: column;
}
.onboarding__path h3 { margin-top: 0; margin-bottom: var(--space-3); }
.onboarding__path p { flex: 1; }
.onboarding__path form { margin-top: var(--space-4); }
.onboarding__path button { width: 100%; }
/* Legacy .muted-button block lived here; consolidated into the
   shared .btn / .btn--ghost grammar above. Removed 2026-05-28. */

/* Assessment */
.assess { max-width: 680px; margin: 0 auto; }
.assess__progress { color: var(--text-alt-color); font-size: var(--text-sm); margin: 0 0 var(--space-5); }
.assess__prompt {
  font-size: var(--text-md);
  font-weight: 500;
  line-height: 1.5;
  margin: 0 0 var(--space-5);
}
.assess__options { border: none; padding: 0; margin: 0 0 var(--space-5); display: flex; flex-direction: column; gap: var(--space-3); }
.assess__option {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  cursor: pointer;
  line-height: 1.5;
}
.assess__option:has(input:checked) { border-color: var(--brand-color); background: var(--background-color); }
.assess__option:hover { border-color: var(--text-alt-color); }
.assess__option input { margin-top: 4px; }
.assess__option-text { flex: 1; }
.assess__actions { display: flex; gap: var(--space-3); align-items: center; }
.assess__axes { margin-top: var(--space-5); font-size: var(--text-xs); }
.assess__reveal:not(:empty) { display: flex; flex-direction: column; gap: var(--space-3); align-items: flex-start; margin-top: var(--space-4); }
.assess__reveal-line { margin: 0; color: var(--text-alt-color); font-size: var(--text-sm); }

/* Stat pentagon — a radar chart over the 5 consolidated stats.
   Source: app/services/skill_stats.py + templates/_skill_chart.html

   Visual hierarchy (back-to-front):
     1. Grid rings (low-key context)
     2. Outline pentagon (definition only, no fill)
     3. Spokes
     4. Value polygon (the message — soft glow)
     5. Stems connecting badges to data vertices
     6. Dots
     7. Stat badges (tier-colored: strong / mid / weak) */

.stat-pentagon {
  display: flex;
  justify-content: center;
  margin: var(--space-5) auto;
  max-width: 540px;
}
.stat-pentagon svg { width: 100%; height: auto; display: block; }

.stat-pentagon--animate-in svg {
  animation: stat-pentagon-in 600ms var(--ease-emphasis);
  transform-origin: 50% 50%;
}

@keyframes stat-pentagon-in {
  from {
    opacity: 0.35;
    transform: scale(0.94);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

html[data-reduce-motion="1"] .stat-pentagon--animate-in svg {
  animation: none !important;
}
@media (prefers-reduced-motion: reduce) {
  .stat-pentagon--animate-in svg {
    animation: none !important;
  }
}

.stat-pentagon__grid {
  fill: none;
  stroke: var(--border-color);
  stroke-width: 1;
}
.stat-pentagon__outline {
  fill: none;
  stroke: var(--border-color);
  stroke-width: 1.5;
  stroke-linejoin: round;
}
.stat-pentagon__spoke {
  stroke: var(--border-color);
  stroke-width: 1;
  opacity: 0.40;
}
.stat-pentagon__tick {
  fill: var(--text-alt-color);
  font-family: var(--font-mono);
  font-size: 9px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.stat-pentagon__value {
  fill: var(--brand-color);
  fill-opacity: 0.28;
  stroke: var(--brand-color);
  stroke-width: 2;
  stroke-linejoin: round;
}
.stat-pentagon__value-edge {
  stroke: var(--brand-color);
  stroke-width: 2;
  stroke-linecap: round;
  opacity: 0.35;
  transition: opacity var(--duration-base) ease, stroke-width var(--duration-base) ease;
}
.stat-pentagon__value-edge.is-highlighted {
  opacity: 1;
  stroke-width: 3;
}
.stat-pentagon__center { fill: var(--text-alt-color); }

.stat-pentagon__stem {
  stroke-width: 1;
  stroke-dasharray: 2 3;
  opacity: 0.6;
}
.stat-pentagon__stem--strong { stroke: var(--brand-color); }
.stat-pentagon__stem--mid    { stroke: var(--accent-color); }
.stat-pentagon__stem--weak   { stroke: var(--text-alt-color); }

.stat-pentagon__dot {
  stroke: var(--background-color);
  stroke-width: 2;
  transition: stroke-width var(--duration-base) ease;
}
.stat-pentagon__dot--strong { fill: var(--brand-color); }
.stat-pentagon__dot--mid    { fill: var(--accent-color); }
.stat-pentagon__dot--weak   { fill: var(--text-alt-color); }
.stat-pentagon__dot.is-highlighted { stroke-width: 3; }

/* Stat badges. Tier color → ring + accent dot inside.
   Strong = solid brand ring; Mid = solid accent ring;
   Weak = dashed muted ring (signals "to improve"). */
.stat-badge__bg {
  fill: var(--background-color);
}
.stat-badge__ring {
  fill: none;
  stroke-width: 1.75;
}
.stat-badge--strong .stat-badge__ring { stroke: var(--brand-color); }
.stat-badge--mid    .stat-badge__ring { stroke: var(--accent-color); }
.stat-badge--weak   .stat-badge__ring {
  stroke: var(--text-alt-color);
  stroke-dasharray: 4 4;
  opacity: 0.7;
}

.stat-badge__label {
  fill: var(--heading-color);
  font-family: var(--font-sans);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
}
.stat-badge__pct {
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.stat-badge__pct-unit {
  font-family: var(--font-sans);
  font-size: 10px;
  font-weight: 500;
  fill: var(--text-alt-color);
}
.stat-badge--strong .stat-badge__pct { fill: var(--brand-color); }
.stat-badge--mid    .stat-badge__pct { fill: var(--accent-color); }
.stat-badge--weak   .stat-badge__pct,
.stat-badge--weak   .stat-badge__label { fill: var(--text-alt-color); }

.stat-pentagon [data-axis] {
  cursor: pointer;
}
.stat-badge {
  transition: opacity var(--duration-base) ease;
}
.stat-badge.is-highlighted .stat-badge__ring {
  stroke-width: 2.5;
}

/* Dark mode: lift the value polygon a touch for contrast against the
   darker background. */
:root[data-theme="dark"] .stat-pentagon__value {
  fill-opacity: 0.32;
}
:root[data-theme="dark"] .stat-pentagon__grid { opacity: 0.7; }

/* Result + home skill summary */
.assess-result { max-width: 720px; margin: 0 auto; }
.assess-result__head { margin-bottom: var(--space-6); }
.assess-result__suggestion { margin: var(--space-7) 0; }
.assess-result__continue { display: flex; gap: var(--space-5); align-items: center; margin-top: var(--space-7); }
.imposter-intercept__axes ul {
  margin: var(--space-3) 0 0;
  padding-left: var(--space-5);
  display: grid;
  gap: var(--space-3);
}
.imposter-intercept__axes li {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: baseline;
}
/* Legacy .primary-link block lived here; consolidated into the
   shared .btn / .btn--primary grammar above. Removed 2026-05-28. */

.home-banner {
  background: var(--surface-color);
  border-left: 3px solid var(--accent-color);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-6);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: var(--text-sm);
}

/* One-shot orientation toast — sibling of .home-banner, softer (no
   hard left rule, dashed border instead) so it reads as helpful
   context rather than a "you must act" call-out. Fires only on the
   /onboarding/skip → /?toast=ramp_intro redirect; any other nav
   drops the query param so the toast doesn't haunt the user. */
.home-toast {
  background: var(--surface-color);
  border: 1px dashed var(--accent-color);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-6);
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-color);
}

/* Today — the daily action. Owns the page's visual weight. */
.today { margin-bottom: var(--space-8); }
.today__head { margin-bottom: var(--space-5); }
.today__nav {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-alt-color);
}
.today__date { font-family: var(--font-mono); }
.today__nav-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  color: var(--text-alt-color);
  text-decoration: none;
  font-size: var(--text-sm);
  line-height: 1;
}
.today__nav-arrow[aria-disabled="true"],
.today__nav-arrow--disabled {
  opacity: 0.35;
  cursor: not-allowed;
  pointer-events: none;
}
a.today__nav-arrow { text-decoration: none; }
a.today__nav-arrow:hover { color: var(--brand-color); border-color: var(--brand-color); }
.today__title { font-size: var(--text-4xl); margin: 0 0 var(--space-2); letter-spacing: -0.01em; }
.today__hint { margin: 0; color: var(--text-alt-color); font-size: var(--text-sm); }
.today__hint a { color: var(--text-color); border-bottom: 1px dotted var(--border-color); }
.today__hint a:hover { color: var(--brand-color); border-bottom-color: var(--brand-color); }
.today__warmup { margin: var(--space-5) 0 0; font-size: var(--text-sm); color: var(--text-alt-color); }
.warmup-link {
  color: var(--text-alt-color);
  border: none;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  margin-right: var(--space-3);
}
.warmup-link:hover { color: var(--brand-color); border: none; }

/* Section labels — portfolio motif: mono uppercase amber eyebrow.
   Used standalone for secondary section markers, and paired with an
   h2/h3 title for the portfolio's "eyebrow → bold heading" pattern. */
.section-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent);
  font-weight: 500;
  margin: 0;
}

/* Explicit "eyebrow" alias — same shape as .section-label, used when
   the markup intent is the portfolio's eyebrow-above-heading motif
   (e.g., on /about's section heads) rather than a standalone label. */
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent);
  font-weight: 500;
  margin: 0 0 var(--space-2);
  display: block;
}

/* Legacy .bordered-button block lived here; consolidated into the
   shared .btn grammar above. Falls back to .btn--ghost defaults
   (border = --border-color, text = --text-muted, hover = amber).
   Callsites that genuinely want a loud amber border should migrate
   to .btn--primary. Removed 2026-05-28. */

.page__head--skills {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-5);
  flex-wrap: wrap;
}

/* Skill strip — compact 5-cell summary that replaces the giant
   pentagon card on the home page. */
.home-stats { margin-bottom: var(--space-7); }
.home-stats__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}
.skill-strip {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-2);
}
.skill-strip__cell {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-input);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-top-width: 2px;
}
.skill-strip__cell--strong { border-top-color: var(--brand-color); }
.skill-strip__cell--mid    { border-top-color: var(--accent-color); }
.skill-strip__cell--weak   { border-top-color: var(--text-alt-color); opacity: 0.85; }
.skill-strip__label {
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--text-alt-color);
  margin-bottom: 2px;
}
.skill-strip__pct {
  font-size: var(--text-xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--heading-color);
}
.skill-strip__cell--strong .skill-strip__pct { color: var(--brand-color); }
.skill-strip__cell--mid    .skill-strip__pct { color: var(--accent-color); }
.skill-strip__cell--weak   .skill-strip__pct { color: var(--text-alt-color); }
.skill-strip__unit {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--text-alt-color);
  margin-left: 1px;
}

.home-recent { margin-top: var(--space-7); }
.home-recent header { margin-bottom: var(--space-3); }

/* Weekend rest-day home variant. Keeps the same visual vocabulary as
   empty-states/details cards: soft surface, light border, restrained
   hierarchy. */
.rest-day {
  max-width: 760px;
  margin: 0 auto var(--space-8);
}
.rest-day__head {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  padding: var(--space-6);
  margin-bottom: var(--space-5);
}
.rest-day__day {
  margin: 0 0 var(--space-2);
  font-size: var(--text-4xl);
  letter-spacing: -0.015em;
}
.rest-day__greeting {
  margin: 0 0 var(--space-3);
  font-size: var(--text-base);
}
.rest-day__copy {
  margin: 0;
  color: var(--text-alt-color);
  line-height: 1.65;
}
.rest-day__recap {
  margin-top: 0;
}
.rest-day__recap-body {
  display: grid;
  gap: var(--space-5);
}
.rest-day__section + .rest-day__section {
  border-top: 1px solid var(--border-color);
  padding-top: var(--space-4);
}
.rest-day__list {
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
}
.rest-day__item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
}
.rest-day__item a {
  color: var(--text-color);
}
.rest-day__item a:hover {
  color: var(--brand-color);
}
.rest-day__meta {
  font-size: var(--text-sm);
  white-space: nowrap;
}
.rest-day__no-recap {
  margin: 0;
  padding: var(--space-4) var(--space-5);
  border: 1px dashed var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
}

/* Public dashboard (/public/dashboard): aggregate-only metric cards
   plus a compact weekly activity spark chart. */
.page--public-dashboard { max-width: 760px; }
.public-dashboard__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}
.public-metric-card {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.public-metric-card__triplet {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
}
.public-metric-card__triplet p,
.public-metric-card__single {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.public-metric-card__value {
  font-size: var(--text-2xl);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--heading-color);
}
.public-chart-card {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  padding: var(--space-4);
}
.public-chart-card__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
}
.public-chart {
  width: 100%;
  height: auto;
  display: block;
  margin-top: var(--space-2);
}
.public-chart__axis {
  stroke: var(--border-color);
  stroke-width: 1;
}
.public-chart__bar {
  fill: var(--brand-color);
  opacity: 0.82;
}
.public-chart__bar--empty {
  fill: var(--border-color);
  opacity: 0.55;
}
.public-chart__labels {
  margin-top: var(--space-2);
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: var(--space-2);
  font-size: var(--text-2xs);
  font-family: var(--font-mono);
  letter-spacing: 0.03em;
}
.public-chart__labels span {
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (max-width: 720px) {
  .public-metric-card__value { font-size: var(--text-xl); }
}

/* ─── Today layout — two-column with side rail (WS4, 2026-05-28) ──
   Operator picked prototype variant B (two-column). Primary column
   holds the relevant-now content (next-action hero, today's picks,
   done-today). Right rail holds the dashboard-glance content
   (pinned + active initiatives, 7-day signal, weak axis).

   Mobile: collapses to single column at ≤900px so the page is a
   port, not a redesign, when the mobile app comes online (WS4
   brief: "Design it now so the mobile step is a port, not a
   redesign"). */
.home-layout {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr);
  gap: var(--space-6);
  align-items: start;
}
.home-layout__primary {
  /* Reset the natural <main> stacking so flow children get
     the surface's standard spacing. */
  min-width: 0;
}
.home-layout__rail {
  position: sticky;
  top: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
@media (max-width: 900px) {
  .home-layout {
    grid-template-columns: 1fr;
  }
  .home-layout__rail {
    position: static;
    /* On mobile, the rail moves below primary content — it's
       dashboard-glance, not what-to-do-now. */
    order: 2;
  }
}

/* Rail card — used for each section in the home-rail. Same surface
   treatment as a focus-section so the two surfaces visually rhyme. */
.home-rail__card {
  padding: var(--space-4) var(--space-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.home-rail__heading {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
  color: var(--text-muted);
  margin: 0 0 var(--space-3);
  font-weight: 600;
}
.home-rail__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.home-rail__row {
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
  font-size: var(--text-sm);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border);
}
.home-rail__row:last-child {
  border-bottom: none;
  padding-bottom: 0;
}
.home-rail__row-title {
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
}
.home-rail__row-title:hover { color: var(--accent); }
.home-rail__row-meta {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.home-rail__row-meta .home-rail__urgent  { color: var(--err); }
.home-rail__row-meta .home-rail__soon    { color: var(--warn); }
.home-rail__row-meta .home-rail__future  { color: var(--info); }

.home-rail__stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}
.home-rail__stat {
  display: flex;
  flex-direction: column;
  line-height: var(--leading-tight);
}
.home-rail__stat-value {
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.home-rail__stat-label {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  color: var(--text-muted);
}
.home-rail__streak {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.home-rail__streak strong {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.home-rail__weak {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.home-rail__weak-axis {
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--text);
}
.home-rail__weak-score {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.home-rail__weak-explain {
  margin: 0;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* Today blocks: four sequential modes (Readings / Watch / Practice /
   Compose) plus optional Recent footer. Compose is the primary block
   and gets the brand-purple anchor; the others are quieter until
   content lands. */
.today-block { margin-bottom: var(--space-7); }
.today-block__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}
.today-block__count {
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  letter-spacing: 0.05em;
}
.today-block__aside { margin: var(--space-4) 0 0; font-size: var(--text-sm); color: var(--text-alt-color); }

/* Empty-state for not-yet-built Today modes. Designed to look
   intentional (a placeholder for an upcoming feature) rather than
   "broken page." */
.empty-state {
  background: var(--surface-color);
  border: 1px dashed var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-4) var(--space-5);
}
.empty-state__msg {
  margin: 0;
  color: var(--text-alt-color);
  font-size: var(--text-sm);
  line-height: 1.6;
}
.empty-state em { color: var(--text-color); font-style: normal; font-weight: 500; }

/* Content cards on Today — readings / videos / podcasts / exercises.
   Slightly different from problem cards: less ceremony, no "why
   surfaced" expander, the source and duration anchor the meta row. */
.content-card {
  display: block;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  color: var(--text-color);
  text-decoration: none;
}
.content-card:hover {
  border-color: var(--brand-color);
  color: var(--text-color);
}
.content-card--done { opacity: 0.7; }
.content-card--done .content-card__title { color: var(--text-alt-color); }
.content-card__meta {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-xs);
  margin-bottom: var(--space-2);
}
.content-card__kind {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
  color: var(--brand-color);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}
.content-card__duration {
  color: var(--text-alt-color);
  font-family: var(--font-mono);
}
.content-card__status {
  margin-left: auto;
  color: var(--ok);
  font-size: var(--text-xs);
}
.content-card__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-md);
  font-weight: 600;
}
.content-card__source {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  font-size: var(--text-sm);
  color: var(--text-alt-color);
  align-items: center;
}

.tag--axis {
  background: var(--background-color);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

/* Single-content view (/content/<slug>). */
.content__meta {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  margin-bottom: var(--space-3);
  font-size: var(--text-sm);
}
.content__kind {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
  color: var(--brand-color);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}
.content__done {
  color: var(--ok);
}
.content__tags {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-top: var(--space-3);
}
.content__actions {
  display: flex;
  gap: var(--space-4);
  align-items: center;
  margin-top: var(--space-6);
}
.content__actions form { margin: 0; }
.page--content { max-width: 720px; }

/* Favorite button — sits in the content header meta row. */
.content__favorite-form { display: inline; margin: 0; margin-left: auto; }
.content__favorite {
  background: transparent;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-alt-color);
  padding: 4px var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  cursor: pointer;
}
.content__favorite:hover { color: var(--brand-color); border-color: var(--brand-color); }
.content__favorite.is-favorited { color: var(--warn); border-color: var(--warn); }
.content__favorite.is-favorited:hover { color: var(--text-alt-color); border-color: var(--text-alt-color); }

/* Rating row — radio buttons styled as cells. */
.content__rating {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: stretch;
  margin: var(--space-3) 0 0;
}
.content__rating-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  background: var(--surface-color);
  cursor: pointer;
  min-width: 64px;
  font-size: var(--text-xs);
}
.content__rating-cell input { width: auto; accent-color: var(--brand-color); }
.content__rating-cell:focus-within { box-shadow: var(--focus-ring); }
.content__rating-cell:hover { border-color: var(--text-alt-color); }
.content__rating-cell.is-active {
  border-color: var(--brand-color);
  background: var(--background-color);
}
.content__rating-cell.is-active span:first-of-type { color: var(--brand-color); }

/* Reflection textarea */
.content__reflect {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.content__reflect textarea {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: 1.5;
  padding: var(--space-3);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
  resize: vertical;
}
.content__reflect textarea:focus { outline: none; border-color: var(--brand-color); }
.content__reflect button { align-self: flex-start; }
.reflect-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

/* Drop-in autosave status pill — sits next to a textarea, surfaced by
   static/js/autosave.js. Stays muted-text until populated so it doesn't
   draw the eye on first paint. */
.autosave-status {
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  letter-spacing: 0.02em;
  opacity: 0.85;
}
.autosave-status:empty { display: none; }

/* Phase-aware hint ladder. The "Stuck? Get a nudge" row sits under
   each phase textarea (or the code editor for Implement). The hint
   slot below it receives the server-rendered HTML fragment. Color
   intensifies with tier so the user feels the ladder. */
.phase__hint-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-2);
}
.hint-status {
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  letter-spacing: 0.02em;
}
.hint-status--error { color: var(--err); }
:root[data-theme="dark"] .hint-status--error { color: var(--err); }
.hint-slot:empty { display: none; }
.hint {
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-left-width: 3px;
  border-radius: var(--radius-input);
  font-size: var(--text-sm);
  line-height: 1.5;
}
.hint--tier-1 { border-left-color: var(--info); }   /* light blue — gentle */
.hint--tier-2 { border-left-color: var(--brand-color); }   /* purple — direction */
.hint--tier-3 { border-left-color: var(--warn); }   /* orange — scaffolding */
.hint__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
  font-size: var(--text-xs);
}
.hint__tier {
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: var(--code-bg);
  border: 1px solid var(--border-color);
}
.hint-tier--1 { color: var(--info); border-color: var(--info-dim); }
.hint-tier--2 { color: var(--brand-color); border-color: var(--accent-dim); }
.hint-tier--3 { color: var(--warn); border-color: var(--warn-dim); }
.hint-tier--exhausted { color: var(--text-alt-color); }
.hint__method { font-family: var(--font-mono); }
.hint__body { margin: 0; }

/* Reflect / Hamming. Lean on existing tokens — this is functional UI,
   not a poster. The intent is "weekly journaling surface", quiet. */
.page--reflect, .page--reflect-detail { max-width: 760px; }
.reflect__week-card {
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-5);
  box-shadow: var(--shadow-card);
}
.reflect__stats {
  list-style: none;
  padding: 0;
  margin: var(--space-2) 0 var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--text-sm);
}
.reflect__stats .tag { margin-left: var(--space-2); }
.reflect__gen {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.reflect__gen button[disabled] {
  opacity: 0.72;
  cursor: not-allowed;
}
.reflect__gen button[aria-busy="true"] { cursor: progress; }

.reflect__gen-indicator {
  display: none;
  margin-left: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  min-width: min(100%, 16rem);
}
.reflect__gen.htmx-request .reflect__gen-indicator { display: inline-flex; }

.reflect__gen-skeleton {
  display: grid;
  gap: var(--space-1);
  width: min(100%, 16rem);
}

.reflect__gen-skeleton-line {
  height: 0.5rem;
  border-radius: var(--radius-pill);
  background: linear-gradient(
    90deg,
    var(--surface-raised) 0%,
    var(--border-color) 46%,
    var(--surface-raised) 100%
  );
  background-size: 220% 100%;
  animation: reflect-gen-shimmer 1.2s var(--ease-out) infinite;
}

.reflect__gen-skeleton-line--lg { width: 100%; }
.reflect__gen-skeleton-line--md { width: 88%; }
.reflect__gen-skeleton-line--sm { width: 76%; }
.reflect__gen-skeleton-line--xs { width: 64%; }

.reflect__gen-indicator-copy {
  font-size: var(--text-sm);
}

@keyframes reflect-gen-shimmer {
  from { background-position: 100% 0; }
  to { background-position: -100% 0; }
}

html[data-reduce-motion="1"] .reflect__gen-skeleton-line,
html[data-reduce-motion="true"] .reflect__gen-skeleton-line {
  animation: none;
  background-position: 0 0;
}

@media (prefers-reduced-motion: reduce) {
  .reflect__gen-skeleton-line {
    animation: none;
    background-position: 0 0;
  }
}

/* Run-tests progress indicator on /problem (validation 2026-05-25:
   "the basic 'running…' text wasn't visually clear that anything was
   happening"). Same pattern as the /reflect generate button: real
   animated ring + aria-busy on the submit + hx-disabled-elt to prevent
   double-submit. */
.solve button[aria-busy="true"] { cursor: progress; }

.run-tests-indicator {
  display: none;
  margin-left: var(--space-2);
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  vertical-align: middle;
}
.solve.htmx-request .run-tests-indicator { display: inline-flex; }

.run-tests-spinner {
  width: 0.875rem;
  height: 0.875rem;
  border: 2px solid var(--border-color);
  border-top-color: var(--brand-color);
  border-radius: var(--radius-pill);
  animation: run-tests-spin 0.8s linear infinite;
  flex: 0 0 auto;
}

@keyframes run-tests-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

[data-reduce-motion="1"] .run-tests-spinner {
  animation-duration: 1.6s;
}
.reflect-card {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-4);
  background: var(--surface-color);
}
.reflect-card__head { display: flex; gap: var(--space-3); align-items: baseline; font-size: var(--text-sm); }
.reflect-card__summary { margin: var(--space-3) 0; }
.reflect__history { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--space-2); font-size: var(--text-sm); }
.reflect__summary {
  background: var(--surface-color);
  border-left: 3px solid var(--brand-color);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-input);
  font-size: var(--text-sm);
}
.reflect__prompts {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.reflect-prompt {
  padding: var(--space-4);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-left: 3px solid var(--accent-color);
  border-radius: var(--radius-input);
}
.reflect-prompt__label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-alt-color);
}
.reflect-prompt__body { margin: var(--space-2) 0 0; font-size: var(--text-base); line-height: 1.5; }
.reflect__response {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.reflect__response textarea {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: 1.55;
  padding: var(--space-4);
  background: var(--input-bg, var(--surface-raised));
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
  resize: vertical;
}
.reflect__response textarea:focus { outline: none; border-color: var(--brand-color); box-shadow: var(--focus-ring); }
.reflect-calibration {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  padding: var(--space-3) var(--space-4);
  margin: 0;
  background: var(--surface-color);
}
.reflect-calibration > legend {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-alt-color);
  padding: 0 var(--space-1);
}
.reflect-calibration__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}
.reflect-calibration__field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-alt-color);
}
.reflect-calibration__field input,
.reflect-calibration__field textarea {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: 1.45;
  color: var(--text-color);
  background: var(--input-bg, var(--surface-raised));
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  padding: var(--space-2) var(--space-3);
}
.reflect-calibration__field input:focus,
.reflect-calibration__field textarea:focus {
  outline: none;
  border-color: var(--brand-color);
  box-shadow: var(--focus-ring);
}
.reflect-calibration__field--full {
  margin-top: var(--space-3);
}

@media (max-width: 640px) {
  .reflect-calibration__grid {
    grid-template-columns: 1fr;
  }
}

/* Cross-linking — small footer sections on /content and /attempt that
   surface the temporal arc between reading and practice. */
.crosslink { margin-top: var(--space-6); }
.crosslink__list {
  list-style: none;
  padding: 0;
  margin: var(--space-3) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.crosslink-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  background: var(--surface-color);
}
.crosslink-row__title { font-size: var(--text-sm); border-bottom: none; }
.crosslink-row__title:hover { color: var(--brand-color); }
.crosslink-row__meta { display: flex; gap: var(--space-2); align-items: center; font-size: var(--text-xs); }

/* "Up next" hero card on /. The whole-app flow nudge — surfaces the
   single highest-priority undone action and gets out of the way once
   completion advances. Brand accent on the left edge so it reads as a
   call-to-action rather than chrome. */
/* Quieter than the original "purple-bordered card" — the Up-next
   is the primary CTA but it doesn't need a heavy frame to claim
   that role; the typographic hierarchy (verb badge + large title)
   already does. Just a thin top rule to separate from the strip. */
/* Up-next hero. After feedback #24 ("looks terrible, margins empty,
   crowded"), the redesign was over-corrected to flat-with-top-rule.
   This middle-ground version restores subtle card-feel — soft surface
   tint + brand-color left rule + comfortable padding — without going
   back to the heavy purple-bordered shadow card. Reads as "this is
   the thing to do" without screaming. */
.next-action {
  margin: var(--space-6) 0 var(--space-7);
  padding: var(--space-5) var(--space-5);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-left: 3px solid var(--brand-color);
  border-radius: var(--radius-card);
  box-shadow: none;
}
.next-action--caught_up { border-left-color: var(--ok); }
.next-action__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-sm);
  margin-bottom: var(--space-2);
  flex-wrap: wrap;
}
.next-action__verb {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--brand-color);
  font-weight: 700;
}
.next-action--caught_up .next-action__verb { color: var(--ok); }
.next-action__badge {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  padding: 1px 8px;
  background: var(--code-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-pill);
  color: var(--text-alt-color);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* Difficulty + warmup color-cues on the Up next card. Green for easy,
   amber for medium, red for hard, blue-purple for warmup. Drop the
   visual barrier so the user instantly sees "this is a starter." */
.next-action__badge--easy   { color: var(--ok); border-color: var(--ok-dim); background: var(--ok-dim); }
.next-action__badge--medium { color: var(--warn); border-color: var(--warn-dim); background: var(--warn-dim); }
.next-action__badge--hard   { color: var(--err); border-color: var(--err-dim); background: var(--err-dim); }
/* Warmup badge uses the generic .next-action__badge text content "warmup" — give it the same brand tint as external content. */
.next-action--practice .next-action__badge:not(.next-action__badge--easy):not(.next-action__badge--medium):not(.next-action__badge--hard) {
  /* fallback for problem_type badges — keep default styling */
}
.next-action__duration {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-alt-color);
}
.next-action__label {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.next-action__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: -0.01em;
}
.next-action__title a { border-bottom: none; }
.next-action__title a:hover { color: var(--brand-color); }
.next-action__why {
  margin: 0 0 var(--space-4);
  color: var(--text-alt-color);
  font-size: var(--text-sm);
  line-height: 1.5;
}
.next-action__cta {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.next-action__cta .primary-link {
  font-size: var(--text-base);
  font-weight: 600;
}
.next-action__skip { font-size: var(--text-sm); }

.track-progress {
  margin: var(--space-5) 0 var(--space-6);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-color);
  border-radius: var(--radius-input);
  border: 1px solid var(--border-color);
}

.track-progress__label {
  margin: 0 0 var(--space-2);
  color: var(--text-alt-color);
  font-size: var(--text-sm);
}

.track-progress__bar {
  height: 8px;
  background: var(--border-color);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.track-progress__fill {
  height: 100%;
  background: var(--ok);
  transition: width var(--duration-base) ease;
}

/* Daily progress strip at the top of /. Five segments, one per
   daily slot. Done segments are filled (green); pending segments
   are outlined. Reads at-a-glance: "where am I in today's plan?" */
.daily-progress {
  margin: var(--space-5) 0 var(--space-6);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-color);
  border-radius: var(--radius-input);
  border: 1px solid var(--border-color);
}
.daily-progress__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
}
.daily-progress__label {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-alt-color);
  font-weight: 600;
}
.daily-progress__count {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text-color);
  font-weight: 600;
}
.daily-progress__segments {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
}
/* Each segment is a 5px-tall bar with a label below — much quieter
   than the previous pill-button style. Bar carries the done/not state;
   label carries the slot identity. */
.daily-progress__seg {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  background: none;
  border: none;
  padding: 0;
  position: relative;
}
.daily-progress__seg::before {
  content: "";
  display: block;
  height: 5px;
  background: var(--border-color);
  border-radius: var(--radius-sm);
  transition: background-color var(--duration-base) ease;
}
.daily-progress__seg--done::before {
  background: var(--ok);
}
.daily-progress__seg-label {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-align: center;
  color: var(--text-alt-color);
}
.daily-progress__seg--done .daily-progress__seg-label {
  color: var(--ok);
}
/* The old ✓ glyph is no longer needed — bar color does the work. */
.daily-progress__seg-check { display: none; }
@media (max-width: 480px) {
  .daily-progress__seg-label { font-size: var(--text-2xs); letter-spacing: 0.02em; }
}

.next-action__ramp {
  font-size: var(--text-sm);
  margin: 0 0 var(--space-4);
  padding: 0;
  background: none;
  border: none;
  color: var(--text-alt-color);
}

/* Reset-progress page. Destructive action: red CTA, explicit list of
   what gets deleted, separate list of what's preserved. */
.page--settings-reset { max-width: 680px; }
.reset__list {
  list-style: none;
  padding: 0;
  margin: var(--space-3) 0;
}
.reset__row {
  display: flex;
  justify-content: space-between;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border-color);
  font-size: var(--text-sm);
  font-family: var(--font-mono);
}
.reset__row:last-child { border-bottom: none; }
.reset__row--empty { opacity: 0.5; }
.reset__count {
  color: var(--text-alt-color);
  font-variant-numeric: tabular-nums;
}
.reset__total { margin-top: var(--space-3); font-size: var(--text-sm); }
.reset__keep {
  margin: var(--space-3) 0;
  padding-left: var(--space-5);
  color: var(--text-alt-color);
  font-size: var(--text-sm);
}
.reset__keep li { margin-bottom: var(--space-1); }
.reset__form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  margin-top: var(--space-4);
}
/* Type-the-count confirmation. The user has to retype the visible row
   count number; submit is disabled until match. Prevents single-click
   fat-finger deletes. */
.reset__type-confirm {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--text-sm);
  max-width: 56ch;
}
.reset__type-confirm input {
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-base);
  background: var(--input-bg, var(--surface-raised));
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
  width: 200px;
}
.reset__type-confirm input:focus {
  outline: none;
  border-color: var(--err);
  box-shadow: 0 0 0 3px var(--err-dim);
}
.reset__confirm {
  background: var(--err);
  color: #fff;
  border: none;
  border-radius: var(--radius-input);
  padding: var(--space-3) var(--space-5);
  font-family: inherit;
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--duration-fast) ease, transform var(--duration-fast) ease, opacity var(--duration-fast) ease;
}
.reset__confirm:disabled {
  background: var(--border-color);
  color: var(--text-alt-color);
  cursor: not-allowed;
  opacity: 0.7;
}
.reset__confirm:not(:disabled):hover { background: var(--err); }
.reset__confirm:not(:disabled):active { transform: translateY(0.5px); }
.reset__confirm:focus { outline: none; box-shadow: 0 0 0 3px var(--err-dim); }
.settings__reset-link { margin-top: var(--space-3); font-size: var(--text-sm); }
.settings__reset-link a { color: var(--err); border-bottom-color: var(--err-dim); }
:root[data-theme="dark"] .reset__confirm { background: var(--err); }
:root[data-theme="dark"] .reset__confirm:hover { background: var(--err); }

/* "Done today" tray. Lives at the bottom of the home page; appears
   only when the user has completed at least one item. Each row has
   the title, kind/duration/timestamp, and a "requeue" button that
   un-completes the item so it returns to today's slot. */
.done-today { margin-top: var(--space-7); }
.done-today__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.done-today__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-left: 3px solid var(--ok);
  border-radius: var(--radius-input);
  font-size: var(--text-sm);
}
.done-today__title {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  text-decoration: none;
  color: var(--text-color);
  border-bottom: none;
  flex: 1 1 auto;
}
.done-today__title:hover { color: var(--brand-color); }
.done-today__check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-pill);
  background: var(--ok);
  color: #fff;
  font-size: var(--text-sm);
  font-weight: 700;
}
.done-today__meta {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.done-today__undo-form { display: inline; margin: 0; }
.done-today__undo {
  font-size: var(--text-xs);
  padding: 2px var(--space-3);
}

/* Section-header completion tick — green ✓ next to "Reading" /
   "Listening" / "Practicing" when that kind is done. */
.today-block__done {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-left: var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--ok);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: 700;
  vertical-align: middle;
}

/* External-content paste form. Single-column entry; axis-pick grid
   floats inline. Reuses the .field-error styling for validation errors. */
.page__cta {
  margin-top: var(--space-3);
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.ext-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-4);
  max-width: 720px;
}
.ext-form__field { display: flex; flex-direction: column; gap: var(--space-2); }
.ext-form__field > span,
.ext-form__field > legend {
  font-size: var(--text-sm);
  color: var(--text-alt-color);
}
.ext-form__field input[type="text"],
.ext-form__field input[type="url"],
.ext-form__field input[type="number"],
.ext-form__field select,
.ext-form__field textarea {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  padding: var(--space-2) var(--space-3);
  background: var(--input-bg, var(--surface-raised));
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
}
.ext-form__field input:focus,
.ext-form__field select:focus,
.ext-form__field textarea:focus {
  outline: none;
  border-color: var(--brand-color);
  box-shadow: var(--focus-ring);
}
/* Parse-URL row: input + "Parse with Claude" button side-by-side.
   Button styled as secondary (border, no fill) so it doesn't compete
   with the primary Save action below. */
.ext-form__url-row {
  display: flex;
  gap: var(--space-2);
  align-items: stretch;
}
.ext-form__url-row input[type="url"] { flex: 1; }
.ext-form__parse-btn {
  white-space: nowrap;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  font-weight: 600;
  background: transparent;
  color: var(--brand-color);
  border: 1px solid var(--brand-color);
  border-radius: var(--radius-input);
  cursor: pointer;
  transition: background-color var(--duration-base) ease;
}
.ext-form__parse-btn:hover { background: var(--accent-dim); }
.ext-form__parse-btn:disabled { opacity: 0.6; cursor: wait; }
.ext-form__parse-status {
  font-size: var(--text-xs);
  min-height: 1em;
}

.ext-form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}
.ext-form__axes { border: none; padding: 0; margin: 0; }
.ext-form__axis-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-2);
}
.ext-form__axis-check {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  background: var(--surface-color);
  cursor: pointer;
}
.ext-form__axis-check:hover { border-color: var(--brand-color); }
.ext-form__actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-2);
}

/* External-content marker. Color-distinct from .badge--time so the
   user can scan and see "this one's mine". */
.badge--external {
  background: var(--accent-dim);
  color: var(--brand-color);
  border-color: var(--brand-color);
  font-weight: 600;
}
:root[data-theme="dark"] .badge--external {
  background: var(--accent-dim);
  color: var(--brand-color);
  border-color: var(--brand-color);
}

/* Sign-in page (Phase 3 — GitHub OAuth via Supabase). Centered card
   with one big CTA. Same surface treatment as other panels. */
.page--login, .page--auth-callback { max-width: 560px; }
.login__panel {
  margin-top: var(--space-5);
  padding: var(--space-6);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
.login__form { display: flex; flex-direction: column; gap: var(--space-4); }
.login__github {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-3) var(--space-5);
  font-family: inherit;
  font-size: var(--text-base);
  font-weight: 600;
  color: #fff;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  cursor: pointer;
  transition: background var(--duration-fast) ease, transform var(--duration-fast) ease;
}
/* The "Continue with GitHub" affordance is an anchor (not a button)
   so CSP's form-action 'self' doesn't block the OAuth redirect to
   Supabase. Override the global `a { border-bottom: 1px solid }` and
   force same-color text on hover so the link styling doesn't bleed
   through. */
.login__github { border-bottom: 1px solid var(--border); text-decoration: none; }
.login__github:hover { background: var(--bg); color: #fff; border-bottom-color: var(--bg); }
.login__github:active { transform: translateY(0.5px); }
.login__github:focus { outline: none; box-shadow: var(--focus-ring); }
.login__github svg { flex: 0 0 20px; }
.login__meta { margin-top: var(--space-4); font-size: var(--text-sm); }

.library-row__star { color: var(--warn); margin-right: 4px; }

/* Writings */
.page--writing-public { max-width: 920px; }
.writing-public-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--space-4);
}
.writing-public-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
.writing-public-card__title {
  margin: 0;
  font-size: var(--text-md);
  line-height: 1.35;
}
.writing-public-card__blurb {
  margin: 0;
  color: var(--text-alt-color);
  line-height: 1.65;
  font-size: var(--text-sm);
}
.writing-public-card__actions,
.writing-public-card__updated {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}
.writing-public-card__updated {
  color: var(--text-alt-color);
  margin-top: auto;
}

.page--writings, .page--writing { max-width: 760px; }
.writing__head-meta { display: flex; gap: var(--space-3); align-items: baseline; margin-top: var(--space-3); }
.writing__form { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-5); }
.writing__title-field { display: flex; flex-direction: column; gap: var(--space-2); font-size: var(--text-sm); }
.writing__title-field span { color: var(--text-alt-color); }
.writing__title-field input {
  font-family: var(--font-sans);
  font-size: var(--text-md);
  font-weight: 600;
  padding: var(--space-3) var(--space-4);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--heading-color);
}
.writing__title-field input:focus { outline: none; border-color: var(--brand-color); }
.writing__form textarea {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.6;
  padding: var(--space-4);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
  resize: vertical;
  min-height: 360px;
}
.writing__form textarea:focus { outline: none; border-color: var(--brand-color); }
.writing__form-actions { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; }
.writing__source-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.writing__source-list li { display: flex; gap: var(--space-3); align-items: baseline; font-size: var(--text-sm); }
.writing__preview {
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
}

/* Credentials flow */
.page--credentials, .page--gap { max-width: 760px; }
.cred-upload {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-5);
  border: 1px dashed var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
}
.cred-upload__field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--text-sm);
}
.cred-upload__field span { color: var(--text-alt-color); }
.cred-upload input[type="file"] {
  padding: var(--space-2);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  background: var(--background-color);
  color: var(--text-color);
  font-family: inherit;
}
.cred-upload button { align-self: flex-start; }
.cred-upload code { font-family: var(--font-mono); font-size: var(--text-sm); background: var(--background-color); padding: 1px 6px; border-radius: var(--radius-md); }

.credential-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.credential-row__details {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  overflow: clip;
}
.credential-row__summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
}
.credential-row__summary::-webkit-details-marker { display: none; }
.credential-row__summary::after {
  content: "+";
  color: var(--text-alt-color);
  font-size: var(--text-base);
  line-height: 1;
}
.credential-row__details[open] > .credential-row__summary::after { content: "−"; }
.credential-row__headline {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
}
.credential-row__filename { color: var(--heading-color); }
.credential-row__date {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}
.credential-row__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.credential-row__body {
  border-top: 1px solid var(--border-color);
  padding: var(--space-3) var(--space-4) var(--space-4);
}
.credential-row__summary-md {
  font-size: var(--text-sm);
  line-height: 1.6;
}
.credential-row__actions { margin-top: var(--space-3); }

.cred-file {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  margin-bottom: var(--space-3);
  background: var(--surface-color);
}
.cred-file__head { display: flex; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-2); font-size: var(--text-sm); }
.cred-file__name { font-weight: 500; }
.cred-file__text {
  margin: var(--space-2) 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  white-space: pre-wrap;
  background: var(--code-bg);
  padding: var(--space-3);
  border-radius: var(--radius-input);
  max-height: 320px;
  overflow-y: auto;
}

/* Gap grid — paired credentials vs. self bars per axis. */
.gap-grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: var(--space-4) 0;
}
.gap-row {
  display: grid;
  grid-template-columns: 180px 1fr 50px;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--border-color);
}
.gap-row:last-child { border-bottom: none; }
.gap-row__name { font-size: var(--text-sm); color: var(--text-color); }
.gap-row__bars { display: flex; flex-direction: column; gap: 4px; }
.gap-row__bar { display: grid; grid-template-columns: 36px 1fr 40px; align-items: center; gap: var(--space-3); }
.gap-row__legend {
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-alt-color);
  font-family: var(--font-mono);
}
.gap-row__track {
  height: 6px;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.gap-row__fill { display: block; height: 100%; border-radius: var(--radius-md); }
.gap-row__fill--cred { background: var(--accent-color); }
.gap-row__fill--self { background: var(--brand-color); }
.gap-row__num {
  text-align: right;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-alt-color);
  font-variant-numeric: tabular-nums;
}
.gap-row__delta {
  text-align: right;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text-alt-color);
  font-variant-numeric: tabular-nums;
}
.gap-row--positive .gap-row__delta { color: var(--warn); }   /* CV implies more than you rated */
.gap-row--negative .gap-row__delta { color: var(--ok); }   /* You rated higher than CV alone implies — fine */
.gap-grid__legend { display: flex; gap: var(--space-2); align-items: center; font-size: var(--text-xs); }
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; }
.dot--cred { background: var(--accent-color); }
.dot--self { background: var(--brand-color); }

/* JDs */
.page--jds, .page--jd-detail { max-width: 760px; }
.jd-card {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-4) var(--space-5);
  background: var(--surface-color);
}
.jd-card--active { border-left: 3px solid var(--brand-color); }
.jd-card__head { display: flex; gap: var(--space-2); align-items: baseline; }
.jd-card__title { font-weight: 600; font-size: var(--text-base); color: var(--heading-color); }
.jd-card__summary { margin: var(--space-3) 0 0; color: var(--text-alt-color); font-size: var(--text-sm); line-height: 1.6; }
.jd-card__actions { margin: var(--space-3) 0 0; font-size: var(--text-sm); }

.jd-upload {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-5);
  border: 1px dashed var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
}
.jd-upload__field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--text-sm);
}
.jd-upload__field span { color: var(--text-alt-color); }
.jd-upload__field textarea,
.jd-upload__field input[type="text"] {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: 1.5;
  padding: var(--space-3) var(--space-4);
  background: var(--background-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
  resize: vertical;
}
.jd-upload__field textarea:focus,
.jd-upload__field input[type="text"]:focus { outline: none; border-color: var(--brand-color); }
.jd-upload__row { display: flex; gap: var(--space-4); flex-wrap: wrap; }
.jd-upload__row .jd-upload__field { flex: 1; min-width: 200px; }

.jd-list { list-style: none; padding: 0; margin: 0; }
.jd-row { border-bottom: 1px solid var(--border-color); padding: var(--space-3) 0; }
.jd-row:last-child { border-bottom: none; }
.jd-row__main {
  display: flex; gap: var(--space-3); align-items: baseline; flex-wrap: wrap;
  border: none; color: var(--heading-color);
}
.jd-row__title { font-weight: 500; }
.jd-row__meta { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; margin-left: auto; }

.jd-summary { font-size: var(--text-base); line-height: 1.6; }
.jd-source {
  background: var(--code-bg);
  border: 1px solid var(--border-color);
  padding: var(--space-3);
  border-radius: var(--radius-input);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  white-space: pre-wrap;
  max-height: 360px;
  overflow-y: auto;
  margin-top: var(--space-2);
}
.jd-detail__actions { display: flex; gap: var(--space-3); align-items: center; }
.jd-detail__actions form { margin: 0; }

/* Floating feedback widget — fixed bottom-right corner, opens an
   inline panel for typed feedback with auto-captured context. */
.fb-fab {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 100;
}
.fb-fab__open {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  color: var(--text-alt-color);
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-size: var(--text-sm);
  cursor: pointer;
  box-shadow: var(--shadow-popover);
}
.fb-fab__open:hover { color: var(--brand-color); border-color: var(--brand-color); }
.fb-fab__label { font-weight: 500; }

.fb-panel {
  display: none;
  position: absolute;
  right: 0;
  bottom: 48px;
  width: 360px;
  max-width: calc(100vw - 40px);
  background: var(--background-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-4);
  box-shadow: var(--shadow-overlay);
}
.fb-fab--open .fb-panel { display: block; }
.fb-fab--open .fb-fab__open { color: var(--brand-color); border-color: var(--brand-color); }

.fb-panel__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-2);
}
.fb-panel__close {
  background: transparent;
  border: none;
  color: var(--text-alt-color);
  font-size: var(--text-xl);
  line-height: 1;
  cursor: pointer;
  padding: 0 var(--space-1);
}
.fb-panel__close:hover { color: var(--brand-color); }
.fb-panel__url {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  word-break: break-all;
  margin: 0 0 var(--space-3);
}
.fb-panel textarea {
  width: 100%;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: 1.5;
  padding: var(--space-3);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
  resize: vertical;
}
.fb-panel textarea:focus { outline: none; border-color: var(--brand-color); }
.fb-panel__attach {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  font-family: var(--font-mono);
}
.fb-panel__attach-label {
  cursor: pointer;
  color: var(--text-alt-color);
  border: 1px dashed var(--border-color);
  border-radius: var(--radius-sm);
  padding: var(--space-0-5) var(--space-2);
}
.fb-panel__attach-label:hover { color: var(--text-color); border-color: var(--border-color-strong); }
.fb-panel__attach-label input[type="file"] {
  /* Visually hidden but focusable — the label is the affordance. */
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}
.fb-panel__attach-list { font-size: var(--text-2xs); word-break: break-all; }
.fb-panel__diag {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
  font-size: var(--text-xs);
}
.fb-item__attachments { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.fb-item__thumb {
  max-height: 72px;
  max-width: 120px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  display: block;
}
.fb-panel__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: var(--space-3);
  gap: var(--space-3);
}
.fb-panel__hint {
  font-size: var(--text-xs);
  font-family: var(--font-mono);
}

/* Status banner — empty by default; ok/err classes flip its appearance. */
.fb-status {
  font-size: var(--text-sm);
  margin-top: var(--space-3);
  padding: 0;
  line-height: 1.5;
}
.fb-status:empty { display: none; }
.fb-status--ok {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--ok-dim);
  border-left: 3px solid var(--ok);
  border-radius: var(--radius-md);
  color: var(--text-color);
}
.fb-status--ok a { color: var(--ok); border-bottom: 1px dotted var(--ok); }
.fb-status--err {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--warn-dim);
  border-left: 3px solid var(--err);
  border-radius: var(--radius-md);
  color: var(--text-color);
}
.fb-status__icon {
  font-family: var(--font-mono);
  font-weight: 700;
  flex-shrink: 0;
}
.fb-status--ok .fb-status__icon { color: var(--ok); }
.fb-status--err .fb-status__icon { color: var(--err); }

/* Feedback inbox page */
.page--feedback { max-width: 820px; }
.fb-list { list-style: none; padding: 0; margin: 0; }
.fb-item {
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  margin-bottom: var(--space-3);
}
.fb-item__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
  font-size: var(--text-xs);
  flex-wrap: wrap;
}
.fb-item__id {
  font-family: var(--font-mono);
  color: var(--brand-color);
  font-weight: 700;
}
.fb-item__url {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-alt-color);
  border: none;
}
.fb-item__url:hover { color: var(--brand-color); border: none; }
.fb-item__body {
  margin: var(--space-2) 0;
  font-size: var(--text-sm);
  line-height: 1.5;
  white-space: pre-wrap;
}
.fb-item__body--quiet { color: var(--text-alt-color); font-size: var(--text-sm); }
.fb-item__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
}
.fb-item__notes {
  font-family: inherit;
  font-size: var(--text-sm);
  padding: 4px var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  background: var(--background-color);
  color: var(--text-color);
  width: 280px;
  max-width: 100%;
}
/* Keep long source paths and triage controls inside narrow inbox cards. */
.page--feedback .fb-item__url {
  overflow-wrap: anywhere;
  min-width: 0;
  max-width: 100%;
}
.page--feedback .fb-item__actions {
  flex-wrap: wrap;
  align-items: flex-end;
}
.page--feedback .fb-item__actions > form {
  flex: 0 1 calc(var(--maxw) / 3);
  min-width: 0;
  max-width: 100%;
  align-items: flex-start;
}
.page--feedback .fb-item__notes {
  min-width: 0;
  width: 100%;
}
.fb-item--quiet {
  padding: var(--space-2) var(--space-3);
  background: transparent;
  border-color: var(--border-color);
  opacity: 0.75;
}
.fb-item__notes-display {
  font-size: var(--text-xs);
  margin: var(--space-1) 0 0;
}

/* Inbox sync diagnostic banner — operator review 2026-05-28. Shown
   when the bench/GH auto-archive sync would have run but didn't, so
   the operator can see why instead of staring at unchanged open items.
   Three variants: --warn (config missing), --err (call crashed),
   --ok (sync ran and closed items). */
.fb-sync {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius, 6px);
  margin: var(--space-3) 0 var(--space-4);
  font-size: var(--text-sm);
  line-height: 1.45;
  border: 1px solid var(--border-color);
}
.fb-sync code {
  background: var(--surface-2, var(--surface-color));
  padding: 0.1em 0.35em;
  border-radius: var(--radius-md);
}
.fb-sync--warn {
  border-color: var(--accent-dim, var(--accent));
  background: var(--accent-dim);
}
.fb-sync--err {
  border-color: var(--err-dim);
  background: var(--err-dim);
  color: var(--err);
}
.fb-sync--err code,
.fb-sync--err strong { color: var(--text-color); }
.fb-sync--ok {
  border-color: var(--accent-dim, var(--accent));
  background: var(--accent-dim);
}

/* GitHub-style inbox tabs (Open / Backlog / Closed). */
.fb-tabs {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border-bottom: 1px solid var(--border-color);
  margin: var(--space-4) 0 var(--space-5);
  padding-bottom: 0;
  flex-wrap: wrap;
}
.fb-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-alt-color);
  border: 1px solid transparent;
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-input) var(--radius-input) 0 0;
  text-decoration: none;
  margin-bottom: -1px;
  text-transform: capitalize;
}
.fb-tab:hover { color: var(--text-color); }
.fb-tab.is-active {
  color: var(--text-color);
  border-color: var(--border-color);
  border-bottom-color: var(--brand-color);
  background: var(--surface-color);
  font-weight: 600;
}
.fb-tab__count {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  padding: 1px 8px;
  background: var(--code-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-pill);
  color: var(--text-alt-color);
}
.fb-tab.is-active .fb-tab__count {
  color: var(--text-color);
}
.fb-tab__dot {
  width: 10px; height: 10px; border-radius: var(--radius-pill); flex: 0 0 10px;
  background: var(--text-alt-color);
}
.fb-tab__dot--open    { background: var(--ok); }   /* green, matches GH */
.fb-tab__dot--backlog { background: var(--brand-color); }   /* purple */
.fb-tab__dot--closed  { background: var(--text-muted); }   /* gray */
.fb-tab__dot--pending  { background: var(--warn); }  /* amber */
.fb-tab__dot--granted  { background: var(--ok); }  /* green */
.fb-tab__dot--declined { background: var(--err); }  /* red */
.fb-tabs__spacer { flex: 1 1 auto; }
.fb-tabs__note { font-size: var(--text-xs); }

/* Status pill on each row mirrors the tab dot color so triaged items
   can be skimmed without re-reading the tab header. */
.fb-item__status {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border: 1px solid var(--border-color);
  color: var(--text-alt-color);
}
.fb-item__status--open    { color: var(--ok); border-color: var(--ok-dim); }
.fb-item__status--backlog { color: var(--brand-color); border-color: var(--accent-dim); }
.fb-item__status--archived,
.fb-item__status--dismissed { color: var(--text-muted); border-color: var(--text-faint); }
.fb-item__status--pending { color: var(--warn); border-color: var(--warn-dim); }
.fb-item__status--granted { color: var(--ok); border-color: var(--ok-dim); }
.fb-item__status--declined { color: var(--err); border-color: var(--err-dim); }
.fb-item--backlog  { opacity: 0.92; }
.fb-item--archived,
.fb-item--dismissed { opacity: 0.72; }
.fb-item--declined { opacity: 0.85; }

kbd {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  padding: 1px 6px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--code-bg);
  color: var(--text-alt-color);
}

/* Library — browseable problem list. */
.filters {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.filters__group {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.filters__label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-alt-color);
  font-weight: 700;
  margin-right: var(--space-2);
  min-width: 40px;
}
.filter-chip {
  font-size: var(--text-sm);
  padding: 3px var(--space-3);
  border-radius: var(--radius-md);
  background: transparent;
  border: 1px solid var(--border-color);
  color: var(--text-alt-color);
  font-family: var(--font-mono);
}
.filter-chip:hover { color: var(--heading-color); border-color: var(--text-alt-color); }
.filter-chip.is-active {
  background: var(--brand-color);
  color: #fff;
  border-color: var(--brand-color);
}

.library-list { list-style: none; padding: 0; margin: 0; }
.library-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4);
  border-bottom: 1px solid var(--border-color);
}
.library-row:last-child { border-bottom: none; }
.library-row:hover { background: var(--surface-color); }
.library-row__main {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  border: none;
  color: var(--heading-color);
}
.library-row__title { font-weight: 500; font-size: var(--text-sm); }
.library-row__meta { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; }
.library-row__status {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-alt-color);
  font-family: var(--font-mono);
}
.library-row--attempted .library-row__title { color: var(--text-alt-color); }

/* Skills — per-axis breakdown bars (the original bar layout lives
   on the Skills detail page; the home page uses the strip). */
.axis-grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.axis-row {
  display: grid;
  grid-template-columns: 220px 1fr 50px;
  align-items: center;
  gap: var(--space-4);
  font-size: var(--text-sm);
  padding: var(--space-2) 0;
}
.axis-row__name { color: var(--text-color); }
.axis-row__bar {
  height: 6px;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.axis-row__fill { display: block; height: 100%; border-radius: var(--radius-md); }
.axis-row--strong .axis-row__fill { background: var(--brand-color); }
.axis-row--mid    .axis-row__fill { background: var(--accent-color); }
.axis-row--weak   .axis-row__fill { background: var(--text-alt-color); opacity: 0.55; }
.axis-row__pct {
  text-align: right;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-alt-color);
  font-variant-numeric: tabular-nums;
}

.problem-card--inline { display: block; max-width: 480px; }

/* Settings */
.settings { max-width: 720px; margin: 0 auto; }
.settings__panel {
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-5);
  margin-bottom: var(--space-5);
}
.settings__retake { margin-top: var(--space-4); }

/* Danger zone — separated visually from the rest of /settings.
   Red-on-dim border + red action buttons. Reset + delete-account live
   here, each behind their own confirmation page. */
.settings__panel--danger {
  border-color: var(--err-dim);
  margin-top: var(--space-7);
}
.settings__panel--danger h2 {
  color: var(--err);
}
.settings__danger-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  border-top: 1px solid var(--border-color);
}
.settings__danger-row:first-of-type {
  border-top: none;
  padding-top: var(--space-3);
}
.settings__danger-text { flex: 1; min-width: 0; }
.settings__danger-text strong {
  display: block;
  margin-bottom: 0.25rem;
}
.settings__danger-text p { margin: 0; }

/* Red action button — used for destructive affordances. The
   transparent-by-default + fill-on-hover pattern mirrors
   .bordered-button but in the danger palette. */
.btn-danger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: transparent;
  color: var(--err);
  border: 1px solid var(--err);
  border-radius: var(--radius, 6px);
  padding: var(--space-2) var(--space-4);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  flex-shrink: 0;
  white-space: nowrap;
}
.btn-danger:hover {
  background: var(--err-dim);
  color: var(--err);
  border-color: var(--err);
  text-decoration: none;
}
.btn-danger:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--err-dim);
}
/* Submit-button variant — same look as the anchor variant, used on
   confirmation pages. */
button.btn-danger { font-family: inherit; }
button.btn-danger:disabled,
button.btn-danger[aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
}
.settings__field-list { list-style: none; padding: 0; margin: 0 0 var(--space-4); }
.settings__field-list li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-color);
}
.settings__field-list li:last-child { border-bottom: none; }
.settings__label { font-size: var(--text-sm); font-weight: 500; }
.settings__value { color: var(--text-color); }
.settings__profile-edit { margin-top: var(--space-3); }
.settings__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-3);
}
.settings__form-actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.settings__field { display: flex; flex-direction: column; gap: var(--space-2); font-size: var(--text-sm); }
.settings__field span { color: var(--text-alt-color); }
.settings__field input[type="text"], .settings__field input[type="email"] {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  padding: var(--space-2) var(--space-3);
  background: var(--background-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
}
.settings__field input:focus { outline: none; border-color: var(--brand-color); box-shadow: var(--focus-ring); }
.settings__field--error input,
.settings__field--error select { border-color: var(--err); }
.settings__field--error input:focus,
.settings__field--error select:focus { box-shadow: 0 0 0 3px var(--err-dim); }
/* Native select. Sized to match the text inputs so the form reads as
   one column of consistent controls. */
.settings__field select {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  padding: var(--space-2) var(--space-3);
  background: var(--input-bg, var(--surface-raised));
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
  min-height: 36px;
  /* Keep the native dropdown arrow — the cross-platform appearance is
     fine and tells the user "this opens on click" without ambiguity. */
}
.settings__field select:focus { outline: none; border-color: var(--brand-color); box-shadow: var(--focus-ring); }
.field-error {
  font-size: var(--text-sm);
  color: var(--err);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: 2px;
}
.field-error[hidden] { display: none; }
.field-error::before {
  content: "!";
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 16px; height: 16px;
  border-radius: var(--radius-pill);
  background: var(--err);
  color: #fff;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
}
:root[data-theme="dark"] .field-error { color: var(--err); }
:root[data-theme="dark"] .field-error::before { background: var(--err); }
:root[data-theme="dark"] .settings__field--error input { border-color: var(--err); }
.settings__form button { align-self: flex-start; }
.settings__form-actions button { align-self: auto; }
.settings__checkbox {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  background: var(--background-color);
  cursor: pointer;
}
.settings__checkbox span { display: flex; flex-direction: column; gap: 2px; font-size: var(--text-sm); }
.settings__checkbox strong { font-weight: 500; color: var(--heading-color); }
.settings__checkbox .muted { font-size: var(--text-sm); }

/* Per-problem references panel. Sits between the prompt and the
   phase scaffolding; opt-in expansion. */
.refs {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  padding: var(--space-3) var(--space-5);
  margin-bottom: var(--space-5);
}
.refs > summary {
  cursor: pointer;
  font-size: var(--text-sm);
  color: var(--text-alt-color);
  font-weight: 500;
}
.refs[open] > summary { color: var(--heading-color); margin-bottom: var(--space-3); }
.refs__group { margin-bottom: var(--space-3); }
.refs__group:last-child { margin-bottom: 0; }
.refs__group-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-alt-color);
  margin: 0 0 var(--space-2);
  font-weight: 700;
}
.refs__list { list-style: none; padding: 0; margin: 0; }
.refs__item {
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-color);
  font-size: var(--text-sm);
  line-height: 1.5;
}
.refs__item:last-child { border-bottom: none; }
.refs__title { color: var(--heading-color); }
.refs__item a { color: var(--heading-color); border-bottom: 1px dotted var(--border-color); }
.refs__item a:hover { color: var(--brand-color); border-bottom-color: var(--brand-color); }
.refs__book {
  display: inline-block;
  margin-left: var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-alt-color);
  font-family: var(--font-mono);
}
.refs__why {
  display: block;
  color: var(--text-alt-color);
  font-size: var(--text-sm);
  margin-top: 2px;
}

/* Engineering Method phase sections. */
.phase {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-4) var(--space-5);
  margin: 0 0 var(--space-4);
  background: var(--background-color);
}
.phase__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}
.phase__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-alt-color);
}
.phase__name {
  font-size: var(--text-base);
  font-weight: 700;
  margin: 0;
  letter-spacing: 0.01em;
}
.phase__timer {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-alt-color);
  font-variant-numeric: tabular-nums;
}
.phase__hint {
  margin: 0 0 var(--space-3);
  color: var(--text-alt-color);
  font-size: var(--text-sm);
  line-height: 1.5;
}
.phase textarea {
  width: 100%;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: 1.5;
  padding: var(--space-3) var(--space-4);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
  resize: vertical;
}
.phase textarea:focus { outline: none; border-color: var(--brand-color); }

.phase--implement { border-left: 3px solid var(--brand-color); }
.phase--implement .phase__name { color: var(--heading-color); }

.plan-gate {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  background: var(--surface-color);
  border: 1px dashed var(--border-color);
  border-radius: var(--radius-input);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
  font-size: var(--text-sm);
}
.plan-gate__msg { color: var(--text-alt-color); flex: 1; }
.plan-gate__bypass {
  background: transparent;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  padding: 2px var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-alt-color);
  cursor: pointer;
}
.plan-gate__bypass:hover { border-color: var(--brand-color); color: var(--brand-color); }
.code--locked { opacity: 0.55; cursor: not-allowed; }
.cm-editor.cm-readonly { opacity: 0.55; }
#cm-mount { margin-top: var(--space-2); }
#cm-mount .cm-editor { font-family: var(--font-mono); }

.badge--em { color: var(--accent-color); border-color: var(--accent-color); }

/* Slack-style soft syntax highlighting.
   Only four token roles get color; everything else stays body text.
   Pygments class prefix is "hl-" (see app/services/markdown.py). */

.code-block {
  background: var(--code-bg);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  padding: var(--space-3) var(--space-4);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--text-color);
}
.code-block code { font-family: inherit; background: transparent; padding: 0; }

/* Light defaults. Tokens uncolored render as body text. */
.code-block .hl-k,  /* keyword */
.code-block .hl-kc, .code-block .hl-kd, .code-block .hl-kn,
.code-block .hl-kp, .code-block .hl-kr, .code-block .hl-kt {
  color: var(--brand-color);
}
.code-block .hl-s,  /* string */
.code-block .hl-s1, .code-block .hl-s2, .code-block .hl-sa,
.code-block .hl-sb, .code-block .hl-sc, .code-block .hl-sd,
.code-block .hl-se, .code-block .hl-sh, .code-block .hl-si,
.code-block .hl-sx, .code-block .hl-sr, .code-block .hl-ss {
  color: var(--ok);
}
.code-block .hl-c,  /* comment */
.code-block .hl-c1, .code-block .hl-cm, .code-block .hl-cp,
.code-block .hl-cs, .code-block .hl-ch {
  color: var(--text-alt-color);
  font-style: italic;
}
.code-block .hl-mi, .code-block .hl-mf, .code-block .hl-mh,
.code-block .hl-mo, .code-block .hl-il { /* numbers */
  color: var(--warn);
}
.code-block .hl-nb { color: var(--brand-color); } /* builtin: a hair softer than keywords */
.code-block .hl-nd { color: var(--warn); } /* decorator */

/* Dark palette: same hues, lifted for contrast against var(--bg). */
:root[data-theme="dark"] .code-block .hl-k,
:root[data-theme="dark"] .code-block .hl-kc,
:root[data-theme="dark"] .code-block .hl-kd,
:root[data-theme="dark"] .code-block .hl-kn,
:root[data-theme="dark"] .code-block .hl-kp,
:root[data-theme="dark"] .code-block .hl-kr,
:root[data-theme="dark"] .code-block .hl-kt {
  color: var(--brand-color);
}
:root[data-theme="dark"] .code-block .hl-s,
:root[data-theme="dark"] .code-block .hl-s1,
:root[data-theme="dark"] .code-block .hl-s2,
:root[data-theme="dark"] .code-block .hl-sa,
:root[data-theme="dark"] .code-block .hl-sb,
:root[data-theme="dark"] .code-block .hl-sc,
:root[data-theme="dark"] .code-block .hl-sd,
:root[data-theme="dark"] .code-block .hl-se,
:root[data-theme="dark"] .code-block .hl-sh,
:root[data-theme="dark"] .code-block .hl-si,
:root[data-theme="dark"] .code-block .hl-sx,
:root[data-theme="dark"] .code-block .hl-sr,
:root[data-theme="dark"] .code-block .hl-ss {
  color: var(--ok);
}
:root[data-theme="dark"] .code-block .hl-c,
:root[data-theme="dark"] .code-block .hl-c1,
:root[data-theme="dark"] .code-block .hl-cm,
:root[data-theme="dark"] .code-block .hl-cp,
:root[data-theme="dark"] .code-block .hl-cs,
:root[data-theme="dark"] .code-block .hl-ch {
  color: var(--text-alt-color);
}
:root[data-theme="dark"] .code-block .hl-mi,
:root[data-theme="dark"] .code-block .hl-mf,
:root[data-theme="dark"] .code-block .hl-mh,
:root[data-theme="dark"] .code-block .hl-mo,
:root[data-theme="dark"] .code-block .hl-il {
  color: var(--warn);
}
:root[data-theme="dark"] .code-block .hl-nb { color: var(--brand-color); }
:root[data-theme="dark"] .code-block .hl-nd { color: var(--warn); }

/* Reference-solution / pitfalls aux panes reuse the same block style. */
.aux pre.code-block { margin: var(--space-2) 0 0; }

@media (max-width: 768px) {
  .container { padding: 0 var(--space-4); }
  h1 { font-size: var(--text-xl); }
}

/* --- Readiness page ------------------------------------------------------ */
/* The hero is the load-bearing visual: a big match-% + hours-to-100%
   side-by-side, with a thick filled bar underneath so the user gets
   the gestalt before reading any numbers. */
.readiness__hero {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: var(--space-5);
}
.readiness__hero-head { display: flex; flex-direction: column; gap: var(--space-1); }
.readiness__hero-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.readiness__hero-jd { margin: 0; font-size: var(--text-lg); font-weight: 600; letter-spacing: -0.01em; }
.readiness__hero-stats { display: flex; gap: var(--space-6); align-items: baseline; flex-wrap: wrap; }
.readiness__hero-stat { display: flex; flex-direction: column; gap: var(--space-1); }
.readiness__hero-num {
  font-size: var(--text-5xl);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--brand-color);
  line-height: 1;
}
.readiness__hero-num-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-alt-color);
}
.readiness__hero-bar {
  height: 8px;
  background: var(--border-color);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.readiness__hero-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--brand-color), var(--ok));
  border-radius: var(--radius-md);
  transition: width var(--duration-slow) ease;
}

/* Slider: hours-per-week input + live weeks readout. The slider
   itself is native <input type=range> styled minimally. */
.readiness__slider-section { margin-top: var(--space-5); }
.readiness__slider-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-2);
}
.readiness__slider {
  width: 100%;
  accent-color: var(--brand-color);
}
.readiness__slider-readout {
  font-size: var(--text-base);
  display: flex;
  align-items: baseline;
  gap: var(--space-1);
  flex-wrap: wrap;
}
.readiness__slider-readout strong { font-variant-numeric: tabular-nums; font-weight: 600; }
.readiness__slider-sep { color: var(--text-alt-color); margin: 0 var(--space-2); }
.readiness__slider-caveat { font-size: var(--text-sm); margin-top: var(--space-3); }

/* Per-axis gap bars: dimmed track + filled portion + a thin vertical
   target marker at the JD's required level. Gives "I'm at 40, they
   want ≥65" in a single glance. */
.readiness__gap-list { list-style: none; padding: 0; margin: var(--space-3) 0 0; display: flex; flex-direction: column; gap: var(--space-4); }
.readiness__gap-row { display: flex; flex-direction: column; gap: var(--space-2); }
.readiness__gap-head { display: flex; justify-content: space-between; align-items: baseline; }
.readiness__gap-label { font-weight: 600; font-size: var(--text-sm); }
.readiness__gap-hours {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-alt-color);
}
.readiness__gap-bar {
  position: relative;
  height: 8px;
  background: var(--border-color);
  border-radius: var(--radius-md);
  overflow: visible;
}
.readiness__gap-bar-fill {
  height: 100%;
  background: var(--brand-color);
  border-radius: var(--radius-md);
  transition: width var(--duration-slow) ease;
}
.readiness__gap-bar-target {
  position: absolute;
  top: -2px;
  bottom: -2px;
  width: 2px;
  background: var(--text-color);
  border-radius: var(--radius-sm);
}
.readiness__gap-meta { font-size: var(--text-xs); font-family: var(--font-mono); }

.readiness__at-target { list-style: none; padding: 0; margin: var(--space-3) 0 0; display: flex; flex-direction: column; gap: var(--space-2); }
.readiness__at-target li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: var(--text-sm);
}
.readiness__at-target-label::before { content: "✓ "; color: var(--ok); font-weight: 700; }

.readiness__other-jds { list-style: none; padding: 0; margin: var(--space-3) 0 0; display: flex; flex-direction: column; gap: var(--space-2); }
.readiness__other-jd {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-color);
  border-radius: var(--radius-input);
  font-size: var(--text-sm);
}

.page__section--muted { background: var(--code-bg); padding: var(--space-4); border-radius: var(--radius-card); margin-top: var(--space-6); }
.page__section--muted p { margin: 0 0 var(--space-2); }
.page__section--muted p:last-child { margin: 0; }

/* --- Mentor voices (LIS-297) -------------------------------------------- */
/* Voice picker on /problem — sits above "run tests". Compact so it
   doesn't compete with the submit affordance. Lens text below the
   select previews what that voice will emphasize. */
.voice-picker {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: var(--space-3) 0;
  font-size: var(--text-sm);
}
.voice-picker__label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-alt-color);
}
.voice-picker__select {
  width: max-content;
  min-width: 220px;
  padding: var(--space-1) var(--space-2);
  background: var(--input-bg, var(--surface-raised));
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  color: var(--text-color);
  font-size: var(--text-sm);
}
.voice-picker__select:focus {
  outline: none;
  border-color: var(--brand-color);
  box-shadow: var(--focus-ring);
}
.voice-picker__lens {
  font-size: var(--text-sm);
  line-height: 1.4;
  min-height: 1.2em;
  max-width: 56ch;
}

/* Panel-style voice picker (used on /problem above run tests). The
   original bare-label version blended into the form; this gives it a
   subtle frame + brand-color left rule so it reads as "before you
   submit, choose how you want this critiqued." */
.voice-picker--panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-4) 0;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-left: 3px solid var(--brand-color);
  border-radius: var(--radius-input);
}
.voice-picker--panel .voice-picker__row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  justify-content: space-between;
  flex-wrap: wrap;
}
.voice-picker--panel .voice-picker__label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-alt-color);
  margin-right: var(--space-2);
}
.voice-picker--panel .voice-picker__lens {
  margin: 0;
  color: var(--text-alt-color);
  font-style: italic;
}
.voice-picker__manage {
  font-size: var(--text-sm);
  border-bottom: 1px dotted currentColor;
}

/* /voices browse page — small library of voice cards so the user can
   scan the roster before picking a default. */
.voice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}
.voice-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
}
.voice-card--current { border-color: var(--brand-color); border-width: 2px; }
.voice-card__name { margin: 0; font-size: var(--text-md); font-weight: 600; }
.voice-card__meta {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-alt-color);
}
.voice-card__works { font-size: var(--text-sm); color: var(--text-alt-color); }
.voice-card__lens { font-size: var(--text-sm); margin: var(--space-1) 0 0; }
.voice-card__lens strong { color: var(--brand-color); }
.voice-card__provocation {
  font-style: italic;
  border-left: 2px solid var(--brand-color);
  padding-left: var(--space-3);
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
  line-height: 1.5;
}

/* --- Voice notes (feedback #34) ----------------------------------------- */
/* Injected by static/js/voice-note.js next to every textarea tagged with
   data-voice-note. The button toggles dictation; the status line below
   announces state for screen readers. */
.voice-note-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-2) 0 0;
  padding: var(--space-1) var(--space-3);
  background: transparent;
  color: var(--text-alt-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  font-family: inherit;
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background-color var(--duration-base) ease, border-color var(--duration-base) ease, color var(--duration-base) ease;
}
.voice-note-btn:hover {
  border-color: var(--brand-color);
  color: var(--brand-color);
}
.voice-note-btn:disabled,
.voice-note-btn--disabled {
  cursor: not-allowed;
  opacity: 0.55;
}
.voice-note-btn--disabled:hover {
  border-color: var(--border-color);
  color: var(--text-alt-color);
}
.voice-note-btn--recording {
  background: var(--err-dim);
  border-color: var(--err);
  color: var(--err);
  animation: voice-note-pulse 1.4s ease-in-out infinite;
}
@keyframes voice-note-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--err-dim); }
  50%      { box-shadow: 0 0 0 4px var(--err-dim); }
}
[data-reduce-motion="1"] .voice-note-btn--recording {
  animation: none;
  box-shadow: 0 0 0 2px var(--err-dim);
}
.voice-note-btn__label {
  font-variant: small-caps;
  letter-spacing: 0.04em;
}
.voice-note-status {
  display: inline-block;
  margin-left: var(--space-3);
  font-size: var(--text-xs);
  min-width: 12ch;
}

/* --- /request-access form ----------------------------------------- */
/* Honeypot field — keep off-screen but in DOM. Bots fill, humans
   don't see it. Don't use display:none because some bots check for
   visibility and skip hidden inputs. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.request-access__form { display: flex; flex-direction: column; gap: var(--space-4); }
.form-field { display: flex; flex-direction: column; gap: var(--space-1); }
.form-field__label {
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--text-color);
}
.form-field__hint {
  font-size: var(--text-sm);
  color: var(--text-alt-color);
}
/* Inputs sit on --surface-raised (cards) so they're distinguishable
   from the page background in both light and dark themes. Text uses
   --text-color for full WCAG contrast against the surface — placeholder
   gets a softer --text-alt-color via ::placeholder below. */
.form-field input,
.form-field select,
.form-field textarea {
  font: inherit;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-input);
  background: var(--input-bg, var(--surface-raised));
  color: var(--text-color);
}
.form-field input::placeholder,
.form-field textarea::placeholder {
  color: var(--text-alt-color);
  opacity: 0.65;
}
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  outline: none;
  border-color: var(--brand-color);
  box-shadow: var(--focus-ring);
}
.form-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-2);
}
.form-meta { font-size: var(--text-sm); }
/* The "Send request" button. Reuse the established button--primary
   look (brand color, white text) so it doesn't fight existing CTAs. */
.button--primary {
  font: inherit;
  font-weight: 600;
  padding: var(--space-2) var(--space-4);
  background: var(--brand-color);
  color: #fff;
  border: none;
  border-radius: var(--radius-input);
  cursor: pointer;
}
.button--primary:hover { background: var(--brand-color-strong); }
.button--primary:focus { outline: none; box-shadow: var(--focus-ring); }

/* --- Feedback inbox LIS-301 additions ---------------------------- */
/* Submitter chip (admin scope) — same baseline as .tag but slightly
   muted so it reads as metadata, not a label. */
.tag--submitter {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
}
/* GH issue link — uses the brand color so it stands out as actionable
   (click to GitHub). */
.tag--gh {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--brand-color);
  border-color: var(--brand-color);
  text-decoration: none;
}
.tag--gh:hover {
  background: var(--brand-color);
  color: #fff;
}
/* Admin scope toggle ("all users · just mine") sits in the tabs row
   where the v2-roadmap note used to live. */
.fb-tabs__scope { font-size: var(--text-sm); }
.fb-scope {
  color: var(--text-alt-color);
  text-decoration: none;
  padding: 2px 6px;
  border-radius: var(--radius-md);
}
.fb-scope:hover { color: var(--text-color); }
.fb-scope.is-active {
  color: var(--text-color);
  background: var(--surface-color);
  font-weight: 600;
}

/* ─── /focus — collapsible sections by status (WS2 grammar pass, 2026-05-28)
   Replaces the prior gallery-of-cards layout. Each initiative status
   (active / dormant / closed / unassigned) is a native <details>
   section; Active is open by default. Rows are compact one-liners
   with a 7-day-activity number; click the title to drill into
   /decisions?initiative=<slug> for the full surface. */

.page--focus .page__head { margin-bottom: var(--space-5); }

.focus-section {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  margin-bottom: var(--space-3);
  overflow: clip;
}
.focus-section[open] {
  background: var(--surface-2);
}
.focus-section__summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
}
.focus-section__summary::-webkit-details-marker { display: none; }
.focus-section__summary::after {
  content: "+";
  margin-left: auto;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--text-md);
  line-height: 1;
}
.focus-section[open] > .focus-section__summary::after { content: "−"; }
.focus-section__summary:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.focus-section__dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--text-muted);
  flex-shrink: 0;
}
.focus-section__dot--active     { background: var(--ok); }
.focus-section__dot--dormant    { background: var(--info); }
.focus-section__dot--closed     { background: var(--text-faint); }
.focus-section__dot--unassigned { background: var(--warn); }
.focus-section__label {
  color: var(--text);
  font-weight: 600;
}
.focus-section__count {
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  margin-left: var(--space-1);
}
.focus-section__hint {
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  text-transform: none;
  letter-spacing: 0;
  margin-left: var(--space-2);
}
.focus-section__empty {
  padding: var(--space-3) var(--space-5) var(--space-5);
  font-size: var(--text-sm);
}

.focus-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.focus-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--border);
}
.focus-row--dormant   { opacity: 0.75; }
.focus-row--closed    { opacity: 0.55; }
.focus-row--pinned    { border-left: 3px solid var(--accent); }
.focus-row--unassigned .focus-row__title { font-style: italic; }

.focus-row__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.focus-row__title {
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
}
.focus-row__title:hover { color: var(--accent); }
.focus-row__pin {
  color: var(--accent);
  margin-left: var(--space-1);
}
.focus-row__meta {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
  flex-wrap: wrap;
}
.focus-row__target {
  font-weight: 500;
  cursor: help;
}
.focus-row__target--overdue { color: var(--err); }
.focus-row__target--soon    { color: var(--warn); }
.focus-row__target--future  { color: var(--info); }
.focus-row__signal {
  color: var(--text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.focus-row__decision {
  margin: 0;
  font-size: var(--text-sm);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: baseline;
}
.focus-row__prs {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.focus-row__pr {
  font-size: var(--text-sm);
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.focus-integrations {
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: var(--text-sm);
}
.focus-integrations li {
  padding: var(--space-1) 0;
}

.focus-card__foot { font-size: var(--text-xs); margin-top: auto; }

.focus-integrations { padding-left: 1rem; }
.focus-integrations li { margin-bottom: 0.25rem; }

.small { font-size: var(--text-sm); }

/* Writings index — delete affordance per row */

.writings-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.writings-row .library-row__main {
  flex: 1;
  min-width: 0;
}
.writings-row__delete {
  margin: 0;
  flex-shrink: 0;
}
/* Legacy .btn-danger-link block lived here; consolidated into the
   shared .btn / .btn--danger grammar above. Removed 2026-05-28. */

/* Home: make the active-track progress widget a clickable card */
.track-progress--linked {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: background var(--duration-base), border-color var(--duration-base);
}
.track-progress--linked:hover,
.track-progress--linked:focus-visible {
  background: var(--row-hover, var(--surface-overlay));
  border-radius: var(--radius-md);
}

/* Rest-day pregenerated-reflection CTA (GH #229) */
.rest-day__pregen {
  border: 1px solid var(--accent-color, var(--accent));
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  margin: 1rem 0 1.25rem;
  background: var(--accent-dim);
}
.rest-day__pregen-headline { margin: 0 0 0.25rem; }
.rest-day__pregen p.muted { margin: 0.25rem 0 0.75rem; font-size: var(--text-sm); }
.rest-day__pregen-cta {
  display: inline-block;
  font-weight: 600;
  color: var(--accent-color, var(--accent));
  text-decoration: none;
}
.rest-day__pregen-cta:hover { text-decoration: underline; }

/* /journal — chat-outcome log (BEN-82 / GH #212) */

.journal-facets {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0;
  margin: 0.5rem 0 1rem;
}

.journal-facet {
  display: inline-block;
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color, var(--border));
  font-size: var(--text-sm);
  text-decoration: none;
  color: inherit;
  transition: background var(--duration-base), border-color var(--duration-base);
}
.journal-facet:hover { background: var(--surface-overlay-strong); }
.journal-facet--active {
  background: var(--accent-dim);
  border-color: var(--accent-color, var(--accent));
  color: var(--accent-color, var(--accent));
  font-weight: 600;
}

.journal-entries {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.journal-entry {
  border: 1px solid var(--border-color, var(--border));
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  background: var(--surface-color, var(--surface));
}

.journal-entry__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: 0.5rem;
}

.journal-entry__permalink {
  color: var(--muted-color, var(--info));
  text-decoration: none;
  font-size: var(--text-sm);
  font-family: monospace;
}
.journal-entry__permalink:hover { color: var(--accent-color, var(--accent)); }

.journal-entry__initiative a {
  text-decoration: none;
  color: var(--accent-color, var(--accent));
  font-size: var(--text-sm);
  font-weight: 600;
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--warn-dim);
  border-radius: var(--radius-sm);
}
.journal-entry__initiative a:hover { background: var(--accent-dim); }

.journal-entry__decisions,
.journal-entry__next {
  margin: 0.5rem 0;
}
.journal-entry__decisions p,
.journal-entry__next p {
  margin: 0.25rem 0 0;
  white-space: pre-line;
}

.journal-entry__chat-link { margin-top: 0.5rem; }

.section-label.small { font-size: var(--text-xs); }

/* /news — RSS aggregator (rss-news-feed Phase 1).
   Visually quiet — these are external links, not bench content. The
   per-item card mirrors .journal-entry's shape so the two list
   surfaces feel coherent. */

.news-facets {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0;
  margin: 0.5rem 0 1rem;
}
.news-facet {
  display: inline-block;
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color, var(--border));
  font-size: var(--text-sm);
  text-decoration: none;
  color: inherit;
  transition: background var(--duration-base), border-color var(--duration-base);
}
.news-facet:hover { background: var(--surface-overlay-strong); }
.news-facet--active {
  background: var(--accent-dim);
  border-color: var(--accent-color, var(--accent));
  color: var(--accent-color, var(--accent));
  font-weight: 600;
}

.news-items {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.news-item {
  border: 1px solid var(--border-color, var(--border));
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  background: var(--surface-color, var(--surface));
}
.news-item--pinned {
  border-color: var(--accent-color, var(--accent));
  box-shadow: 0 0 0 1px var(--accent-color, var(--accent)) inset;
}
.news-item--dismissed { opacity: 0.55; }

.news-item__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  margin-bottom: 0.35rem;
}
.news-item__source a {
  text-decoration: none;
  color: var(--accent-color, var(--accent));
  font-size: var(--text-sm);
  font-weight: 600;
}
.news-item__source a:hover { text-decoration: underline; }
.news-item__time { font-family: monospace; }
.news-item__pin-badge { color: var(--accent-color, var(--accent)); margin-left: 0.25rem; }

.news-item__title {
  font-size: var(--text-base);
  margin: 0.25rem 0 0.5rem;
}
.news-item__title a { text-decoration: none; color: inherit; }
.news-item__title a:hover { text-decoration: underline; }

.news-item__summary {
  margin: 0.25rem 0 0.5rem;
  font-size: var(--text-sm);
  line-height: 1.4;
}

.news-item__actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.4rem;
}
.news-item__action { margin: 0; }
.news-item__action button {
  font-size: var(--text-sm);
  padding: 0.2rem 0.55rem;
}

.news-empty p { margin: 0.4rem 0; }

.news-toggle { text-align: center; margin-top: 1rem; }

/* /focus — last-decided row (BEN-82 cross-surface link) */
.focus-card__row--decision .focus-decision {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.focus-decision__excerpt {
  font-size: var(--text-sm);
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dashed transparent;
  transition: border-color var(--duration-base);
}
.focus-decision__excerpt:hover {
  border-bottom-color: var(--accent-color, var(--accent));
  color: var(--accent-color, var(--accent));
}
.focus-decision__time {
  font-family: monospace;
}

/* /tracks — first-time-here framing block */
.tracks-first-time {
  border: 1px solid var(--warn-dim);
  background: var(--accent-dim);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
}
.tracks-first-time p { margin: 0.4rem 0; }
.tracks-first-time .section-label { margin: 0 0 0.5rem; }

/* /reflect — first-reflection callout */
.reflect__first-time {
  border: 1px solid var(--warn-dim);
  background: var(--accent-dim);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
}
.reflect__first-time p { margin: 0.4rem 0; }
.reflect__first-time ul { margin: 0.5rem 0 0.4rem; padding-left: 1.25rem; }
.reflect__first-time li { margin: 0.35rem 0; }
.reflect__first-time .section-label { margin: 0 0 0.5rem; }

/* /aim — per-section empty-state explainers (gap #3) */
.aim-empty-explainer {
  background: var(--surface-overlay-faint);
  border-left: 3px solid var(--accent-color, var(--accent));
  border-radius: var(--radius-sm);
  padding: 0.75rem 1rem;
}
.aim-empty-explainer p { margin: 0; }
.aim-calibration--empty {
  background: var(--surface-overlay-faint);
  border-left: 3px solid var(--accent-color, var(--accent));
  border-radius: var(--radius-sm);
  padding: 0.75rem 1rem;
}
.aim-calibration--empty .section-label { margin: 0 0 0.4rem; }

/* ─── /connecting — networking tracker with warmth-decay (WS6, 2026-05-28)
   List rows use the same compact treatment as focus rows so the two
   dashboard-ish surfaces visually rhyme. Tier-coded left border +
   pill: warm (green) / fading (amber) / cold (red) / never (faint).
   Detail page reuses the page__head + .md grammar. */

.connecting-add {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  margin-bottom: var(--space-5);
  overflow: clip;
}
.connecting-add[open] { background: var(--surface-2); }
.connecting-add summary {
  cursor: pointer;
  padding: var(--space-3) var(--space-5);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
  color: var(--text-muted);
  list-style: none;
}
.connecting-add summary::-webkit-details-marker { display: none; }
.connecting-add summary:hover { color: var(--accent); }
.connecting-add summary:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.connecting-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5) var(--space-5);
}
.connecting-form__row {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.connecting-form__row label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  color: var(--text-muted);
}
.connecting-form__row input,
.connecting-form__row select,
.connecting-form__row textarea {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-base);
}
.connecting-form__row--split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}
@media (max-width: 600px) {
  .connecting-form__row--split { grid-template-columns: 1fr; }
}
.connecting-form button[type="submit"] {
  align-self: flex-start;
  margin-top: var(--space-2);
}

.connecting-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.connecting-row {
  padding: var(--space-3) var(--space-5);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius);
  background: var(--surface);
  margin-bottom: var(--space-2);
}
.connecting-row--warm   { border-left-color: var(--ok); }
.connecting-row--fading { border-left-color: var(--warn); }
.connecting-row--cold   { border-left-color: var(--err); }
.connecting-row--never  { border-left-color: var(--text-faint); }

.connecting-row__main {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  text-decoration: none;
}
.connecting-row__name {
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text);
}
.connecting-row__main:hover .connecting-row__name { color: var(--accent); }
.connecting-row__meta {
  display: inline-flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: baseline;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.connecting-row__tier {
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-pill);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  font-weight: 600;
}
.connecting-row__tier--warm   { background: var(--ok-dim);   color: var(--ok); }
.connecting-row__tier--fading { background: var(--warn-dim); color: var(--warn); }
.connecting-row__tier--cold   { background: var(--err-dim);  color: var(--err); }
.connecting-row__tier--never  {
  background: transparent;
  color: var(--text-faint);
  border: 1px solid var(--border);
}
.connecting-row__flag {
  color: var(--accent);
  font-weight: 600;
}
.connecting-row__context {
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
}

/* Detail page */
.connecting-history {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.connecting-history__row {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}
.connecting-history__head {
  display: flex;
  gap: var(--space-3);
  align-items: baseline;
  flex-wrap: wrap;
  margin-bottom: var(--space-2);
}
.connecting-history__kind {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  color: var(--text);
  font-weight: 600;
}
.connecting-history__direction {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-pill);
}
.connecting-history__direction--outbound { background: var(--info-dim); color: var(--info); }
.connecting-history__direction--inbound  { background: var(--accent-dim); color: var(--accent); }
.connecting-history__notes {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.connecting-detail__danger {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}

/* ─── Command palette (WS5 progressive enhancement, 2026-05-28) ──
   Vanilla JS overlay (static/js/palette.js) wires Cmd+K to this
   markup. Pure presentation here — no logic. Tokens-only; the
   overlay's drop-shadow is --shadow-overlay; the input + list use
   the same surface treatment as the profile dropdown so the
   palette reads as a denser cousin of that menu, not a new
   visual language. */

.palette {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 15vh;
  z-index: 1000;
}
.palette[hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .palette {
    animation: palette-fade var(--duration-fast) var(--ease-out);
  }
}
@keyframes palette-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.palette__dialog {
  width: min(560px, 92vw);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-overlay);
  display: flex;
  flex-direction: column;
  max-height: 70vh;
  overflow: hidden;
}

.palette__input {
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--text-md);
  padding: var(--space-4) var(--space-5);
  outline: none;
}
.palette__input::placeholder { color: var(--text-faint); }
.palette__input:focus { outline: none; box-shadow: none; }

.palette__list {
  list-style: none;
  margin: 0;
  padding: var(--space-2);
  overflow-y: auto;
  flex: 1;
  min-height: 80px;
}
.palette__group {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
  color: var(--text-faint);
  padding: var(--space-2) var(--space-3) var(--space-1);
  user-select: none;
}
.palette__group:not(:first-child) {
  margin-top: var(--space-2);
  border-top: 1px solid var(--border);
}
.palette__item {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  cursor: pointer;
  user-select: none;
  /* left accent bar reserved so the active state doesn't shift layout */
  box-shadow: inset 3px 0 0 transparent;
}
.palette__item:hover:not(.is-active) {
  background: var(--surface-raised, var(--surface));
}
.palette__item.is-active {
  background: var(--accent-dim);
  box-shadow: inset 3px 0 0 var(--accent);
}
.palette__item-label {
  font-size: var(--text-sm);
  color: var(--text);
}
.palette__item.is-active .palette__item-label { color: var(--accent); }
.palette__item-hint {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
}

.palette__empty {
  padding: var(--space-4) var(--space-5);
  font-size: var(--text-sm);
  text-align: center;
}

.palette__foot {
  display: flex;
  gap: var(--space-4);
  justify-content: center;
  flex-wrap: wrap;
  padding: var(--space-2) var(--space-5);
  border-top: 1px solid var(--border);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-wider);
}
.palette__foot kbd {
  display: inline-flex;
  align-items: center;
  padding: 1px var(--space-2);
  margin-right: var(--space-1);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: var(--text-2xs);
  color: var(--text);
}

/* ─── Nav palette hint button — visible affordance for the palette.
   Lives at the right end of the header nav. Pure presentation; the
   JS is bound to data-palette-trigger. Same visual weight as a
   .header-nav__link so the row stays balanced. */
.nav__palette-hint {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out);
}
.nav__palette-hint:hover,
.nav__palette-hint:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
  outline: none;
}
.nav__palette-hint:focus-visible { box-shadow: var(--focus-ring); }
.nav__palette-hint kbd {
  display: inline-flex;
  align-items: center;
  padding: 1px var(--space-2);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: var(--text-2xs);
  color: var(--text);
  letter-spacing: 0;
}

/* ─── Interview mode v1 (migration 014, 2026-05-28) ──────────────
   Phase-budgeted timer surface: corner toast for per-phase soft
   warnings, full-screen overlay for the hard cutoff, banner on the
   review page for cutoff-ended attempts, and time-vs-budget bars
   on the review page. All values via tokens. */

/* Per-phase soft-warning toast — fires at 80% of the active phase
   budget. Bottom-right; non-blocking; auto-dismisses after 4s. */
.phase-soft-warn {
  position: fixed;
  bottom: var(--space-5);
  right: var(--space-5);
  z-index: 100;
  padding: var(--space-3) var(--space-4);
  background: var(--warn-dim);
  border: 1px solid var(--warn);
  border-left: 3px solid var(--warn);
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text);
  box-shadow: var(--shadow-popover);
  letter-spacing: var(--tracking-wide);
}
@media (prefers-reduced-motion: no-preference) {
  .phase-soft-warn {
    animation: phase-soft-warn-in var(--duration-base) var(--ease-out);
  }
}
@keyframes phase-soft-warn-in {
  from { transform: translateY(8px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

/* Hard-cutoff overlay — full-screen takeover when the session timer
   hits zero. Form is locked; auto-submit fires in 3s. Centred card
   on a dimmed backdrop. */
.interview-cutoff-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1100;
  padding: var(--space-5);
}
.interview-cutoff-overlay__card {
  max-width: 480px;
  background: var(--surface-2);
  border: 1px solid var(--err);
  border-radius: var(--radius);
  padding: var(--space-6);
  box-shadow: var(--shadow-overlay);
  text-align: center;
}
.interview-cutoff-overlay__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
  color: var(--err);
  margin: 0 0 var(--space-3);
}
.interview-cutoff-overlay__title {
  margin: 0 0 var(--space-3);
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--text);
}
.interview-cutoff-overlay__body {
  margin: 0 0 var(--space-5);
  color: var(--text-muted);
  line-height: var(--leading-normal);
}
.interview-cutoff-overlay__countdown {
  font-family: var(--font-mono);
  font-size: var(--text-4xl);
  font-weight: 700;
  color: var(--accent);
  margin: 0;
  font-variant-numeric: tabular-nums;
}

/* Banner on the review page for cutoff-ended attempts so the
   operator sees the context before the partial-work grade. */
.cutoff-banner {
  margin: 0 0 var(--space-5);
  padding: var(--space-3) var(--space-5);
  background: var(--err-dim);
  border-left: 3px solid var(--err);
  border-radius: var(--radius);
  color: var(--text);
  font-size: var(--text-sm);
}
.cutoff-banner strong { color: var(--err); }

/* Per-phase time-vs-budget breakdown bars on the review page. */
.phase-breakdown {
  list-style: none;
  padding: 0;
  margin: 0;
}
.phase-breakdown__row {
  display: grid;
  grid-template-columns: 100px 1fr 220px;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--border);
}
.phase-breakdown__row:last-child { border-bottom: none; }
.phase-breakdown__phase {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
  color: var(--text);
  font-weight: 600;
}
.phase-breakdown__bars {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.phase-breakdown__bar {
  height: 6px;
  border-radius: var(--radius-pill);
  min-width: 2px;
}
.phase-breakdown__bar--actual { background: var(--accent); }
.phase-breakdown__bar--budget { background: var(--accent-dim); border: 1px solid var(--accent-dim); }
.phase-breakdown__row--over   .phase-breakdown__bar--actual { background: var(--err); }
.phase-breakdown__row--under  .phase-breakdown__bar--actual { background: var(--info); }
.phase-breakdown__nums {
  display: flex;
  gap: var(--space-2);
  align-items: baseline;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
  justify-content: flex-end;
}
.phase-breakdown__elapsed { color: var(--text); font-weight: 600; }
.phase-breakdown__divider { color: var(--text-faint); }
.phase-breakdown__status {
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-pill);
}
.phase-breakdown__status--on_budget { color: var(--ok);    background: var(--ok-dim); }
.phase-breakdown__status--over      { color: var(--err);   background: var(--err-dim); }
.phase-breakdown__status--under     { color: var(--info);  background: var(--info-dim); }

@media (max-width: 600px) {
  .phase-breakdown__row {
    grid-template-columns: 1fr;
    gap: var(--space-2);
  }
  .phase-breakdown__nums {
    justify-content: flex-start;
  }
}

/* ── Mira — research-mentor chat surface (MIRA Phase 1a) ──────────────
   Reuses .page / .form-field / .btn wholesale; the only surface-specific
   pieces are the scrolling transcript and the two message-bubble variants.
   Every value is a token. The composer is a plain .form-field, so it
   inherits the app's label + focus-ring a11y treatment for free. */
/* 5a Mira console — a three-column workspace (session rail · streaming
   transcript · agenda/memory rail) inside one framed surface. Every value
   is a token, so the console themes itself in both the dark default and the
   HTC pearl skin; a few HTC-only flourishes (glass frame, drift) live in the
   themed block further down. */
.mira-console-main { max-width: 1120px; }
.mira-console { width: 100%; }
.mira-console__frame {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.mira-console__grid {
  display: grid;
  grid-template-columns: 1fr;
}
@media (min-width: 960px) {
  .mira-console__grid {
    grid-template-columns: 210px minmax(0, 1fr) 276px;
    min-height: 560px;
  }
}

/* ── rails ─────────────────────────────────────────────────────────── */
.mira-rail {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-3);
  background: var(--surface-recessed, var(--surface-raised));
}
@media (min-width: 960px) {
  .mira-rail--sessions { border-right: 1px solid var(--border-color); }
  .mira-rail--context  { border-left: 1px solid var(--border-color); gap: var(--space-5); }
}
.mira-rail__label {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-alt-color);
  padding: 0 var(--space-2);
}
.mira-newconv {
  display: block;
  text-align: center;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 700;
  /* D6 — was a gold gradient: the only gold in a magenta-accent app, and
     an unsanctioned gradient besides (Law 3). */
  color: var(--on-accent, var(--bg));
  background: var(--accent);
  box-shadow: var(--shadow-1);
  margin-bottom: var(--space-2);
  text-decoration: none;
  border-bottom: none;
}
.mira-sess {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  text-decoration: none;
  border-bottom: none;
  border: 1px solid transparent;
}
.mira-sess__title {
  display: block;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.mira-sess__meta {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-faint);
  margin-top: 2px;
}
.mira-sess:hover { background: var(--surface-raised); }
.mira-sess.is-active {
  background: var(--accent-dim);
  border-color: var(--accent);
}
.mira-sess.is-active .mira-sess__title { color: var(--text-color); font-weight: 600; }

/* ── center: conversation ──────────────────────────────────────────── */
.mira-conv {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.mira-conv__head { padding: var(--space-5) var(--space-6) var(--space-3); }
.mira-conv__title-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-1);
}
.mira-conv__title { margin: 0; font-size: var(--text-3xl); letter-spacing: -0.02em; }
.mira-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ok, var(--mint-ink));
  box-shadow: 0 0 0 3px var(--mint-dim, transparent);
}
.mira-status {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--ok, var(--mint-ink));
}
.mira-conv__sub {
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.mira-conv .warmup-banner { margin: 0 var(--space-6) var(--space-2); }
.mira-conv__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  padding: var(--space-3) var(--space-6) var(--space-5);
}

/* ── transcript + bubbles ──────────────────────────────────────────── */
.mira-transcript {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  flex: 1;
  /* D7 — min-height was the whole bug: a scroll child in a flex column that
     refuses to shrink spills under the composer and clips its last line
     mid-glyph. max-height stays; it is what makes the transcript scroll
     internally instead of growing the console frame without bound. */
  min-height: 0;
  max-height: 56vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-padding-block-end: var(--space-6);
  padding-bottom: var(--space-3);
}
.mira-empty {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  max-width: 48ch;
}
.mira-msg { display: flex; flex-direction: column; gap: var(--space-1); max-width: 82%; }
.mira-msg--user { align-self: flex-end; align-items: flex-end; }
.mira-msg__who {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--accent);
}
.mira-msg--user .mira-msg__who { color: var(--text-alt-color); }
.mira-msg__body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed, 1.6);
  color: var(--text-color);
  padding: var(--space-3) var(--space-4);
}
.mira-msg__body--plain { white-space: pre-wrap; }
.mira-msg--assistant .mira-msg__body {
  background: var(--glass-fill-raised, var(--surface-raised));
  border: 1px solid var(--border-color);
  border-radius: var(--radius) var(--radius) var(--radius) 4px;
}
.mira-msg--user .mira-msg__body {
  background: var(--accent-dim);
  border: 1px solid var(--accent);
  border-radius: var(--radius) var(--radius) 4px var(--radius);
}
.mira-msg__body > :first-child { margin-top: 0; }
.mira-msg__body > :last-child { margin-bottom: 0; }

/* ── composer ──────────────────────────────────────────────────────── */
.mira-composer {
  margin-top: var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  background: var(--input-bg, var(--surface-raised));
  box-shadow: var(--inset-hi, none);
  padding: var(--space-3);
}
.mira-composer textarea {
  width: 100%;
  border: none;
  background: transparent;
  resize: vertical;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--text-color);
  padding: 0;
}
.mira-composer textarea:focus { outline: none; }
.mira-composer__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-2);
}
.mira-composer__hint {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-faint);
}

/* Voice affordances (v2.1 PTT). The dictation button is injected by
   voice-note.js after the textarea; scoped compact styling here so it
   reads as part of the composer chrome, not a form control. */
.mira-composer .voice-note-btn {
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  padding: var(--space-1) var(--space-3);
}
.mira-composer .voice-note-status { font-size: var(--text-2xs); }
.mira-speak { white-space: nowrap; }

/* ── right rail: agenda + memory ───────────────────────────────────── */
.mira-ctx { display: flex; flex-direction: column; gap: var(--space-2); }
.mira-ctx__list { display: flex; flex-direction: column; gap: var(--space-2); }
.mira-ctx__empty { margin: 0; font-size: var(--text-sm); color: var(--text-muted); }
.mira-ctx-card {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  border: 1px solid var(--border-color);
}
.mira-ctx-card__title {
  display: block;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-color);
}
.mira-ctx-card__meta {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-alt-color);
  margin-top: 2px;
}
.mira-ctx-item {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  border: 1px solid var(--border-color);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--text-muted);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* 6a/6b/6d Mira sub-surfaces — the agenda / memory / evals pages, each a
   framed card with a breadcrumb, the section tab bar, a title row, and a
   list of item cards. Token-based so it themes in both dark + HTC. */
.mira-surface {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  background: var(--surface-color);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.mira-surface__head { padding: var(--space-4) var(--space-5) 0; }
.mira-surface__crumb {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-wide);
  color: var(--text-alt-color);
  margin-bottom: var(--space-3);
}
/* Tab bar restyle, scoped to the surface (the shared .fb-tabs grammar keeps
   its inbox styling everywhere else). */
.mira-surface .fb-tabs {
  gap: var(--space-4);
  border-bottom: 1px solid var(--border-color);
  margin: 0;
}
.mira-surface .fb-tab {
  padding: 0 0 var(--space-2);
  border: none;
  border-bottom: 2px solid transparent;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-muted);
  border-radius: 0;
  background: none;
}
.mira-surface .fb-tab.is-active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  background: none;
}
.mira-surface__body { padding: var(--space-5); }
.mira-surface__title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.mira-surface__title { margin: 0; font-size: var(--text-2xl); letter-spacing: -0.02em; }
.mira-surface__sub {
  margin: calc(var(--space-2) * -1) 0 var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.mira-addbtn {
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius);
  font-size: var(--text-sm);
  font-weight: 700;
  /* D6 — was a gold gradient: the only gold in a magenta-accent app, and
     an unsanctioned gradient besides (Law 3). */
  color: var(--on-accent, var(--bg));
  background: var(--accent);
  box-shadow: var(--shadow-1);
  border: none;
  text-decoration: none;
  border-bottom: none;
  cursor: pointer;
  white-space: nowrap;
}

/* item cards */
.mira-cardlist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.mira-card {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius);
  background: var(--surface-raised);
  border: 1px solid var(--border-color);
}
.mira-card__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.mira-card__title { font-size: var(--text-md); font-weight: 600; color: var(--text-color); }
.mira-card__desc { margin: var(--space-2) 0 var(--space-2); font-size: var(--text-sm); line-height: var(--leading-normal); color: var(--text-muted); }
.mira-card__meta {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-alt-color);
}
.mira-card__foot { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-2); }

/* pills + chips */
.mira-pill {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: 2px var(--space-2);
  border-radius: 999px;
  border: 1px solid var(--border-color);
  color: var(--text-muted);
  background: var(--surface-color);
}
.mira-pill--active { color: var(--warn); background: var(--gold-dim); border-color: transparent; }
.mira-pill--done   { color: var(--ok);   background: var(--mint-dim); border-color: transparent; }
.mira-pill--open   { color: var(--info); background: var(--sky-dim);  border-color: transparent; }
.mira-chip {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-color);
  color: var(--text-alt-color);
  background: var(--surface-color);
}
.mira-chip--mira { color: var(--plum); background: var(--plum-dim); border-color: transparent; }

/* group label (memory) */
.mira-group {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--warn);
  margin: var(--space-4) 0 var(--space-2);
}
.mira-group:first-of-type { margin-top: 0; }

/* the add-item form, tucked under a details disclosure so the card leads
   with the list, not a form (matches the design's '+ Add' affordance). */
.mira-add { margin-top: var(--space-4); border-top: 1px solid var(--border-color); padding-top: var(--space-3); }
.mira-add > summary {
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--accent);
  list-style: none;
}
.mira-add > summary::-webkit-details-marker { display: none; }
.mira-add[open] > summary { margin-bottom: var(--space-3); }

/* Proposed-eval cards (6d): each eval is a small card with a provenance
   chip, hypothesis/falsifier lines, and the A/B/C condition table. */
.mira-evals {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.mira-eval {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.mira-eval__prov {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.mira-eval__title {
  margin: 0;
  font-size: var(--text-lg);
}
.mira-eval__line { margin: 0; }
.mira-eval__conditions {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.mira-eval__conditions th {
  text-align: left;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-alt-color);
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--border);
}
.mira-eval__conditions td {
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.mira-eval__conditions td:first-child { white-space: nowrap; }
.mira-eval__inspect { font-size: var(--text-sm); }

/* BEN-135 recitation loop. Missed ≠ red: a gap gets the SAME neutral surface
   as "not yet reviewed", because its only consequence is that it returns
   sooner — never a failure signal. No score, percentage, or trend anywhere,
   by design. */
.recite__audio { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-3); }
.recite__mode { border: none; padding: 0; margin: 0 0 var(--space-2); display: flex; gap: var(--space-4); flex-wrap: wrap; }
.recite__mode label { font-size: var(--text-sm); color: var(--text-muted); display: flex; gap: var(--space-1); align-items: center; }
.recite__pretest-note { margin: 0 0 var(--space-3); }
.recite__controls { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-4); }
.recite__results { display: flex; flex-direction: column; gap: var(--space-3); }
.recite__return { font-weight: 600; color: var(--text-color); margin: 0; }
.recite__group { display: flex; flex-direction: column; gap: var(--space-2); }
.recite__h {
  font-family: var(--font-mono); font-size: var(--text-2xs);
  letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--text-alt-color); margin: 0;
}
.recite__chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.recite__chip {
  font-size: var(--text-sm); padding: 2px var(--space-2); border-radius: var(--radius-sm);
  background: var(--surface-raised); border: 1px solid var(--border-color); color: var(--text-muted);
}
.recite__miss {
  padding: var(--space-3); border-radius: var(--radius-sm);
  background: var(--surface-raised); border: 1px solid var(--border-color);
  display: flex; flex-direction: column; gap: var(--space-1);
}
.recite__miss-concept { font-weight: 600; color: var(--text-color); }
.recite__miss-where {
  font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-alt-color);
}
.recite__actually { color: var(--text-color); }
.recite__oq { font-style: italic; color: var(--text-muted); margin: var(--space-2) 0 0; }

/* ==========================================================================
   Landing page (templates/landing.html) — the logged-out front door.

   Token-only per docs/STYLEGUIDE.md: no literal colours, no invented
   shadows, no gradients, every motion a --duration/--ease pair. The two
   audience cards read --panel-* so they are glass in the chamber and flat
   in dark without a second copy of the rule.
   ========================================================================== */

.container--landing { max-width: var(--maxw-wide); }

.lp-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 var(--space-4);
}

.lp-hero { padding-block: var(--space-7) var(--space-8); max-width: 46rem; }

.lp-hero__title {
  font-size: var(--text-5xl, var(--text-4xl));
  line-height: var(--leading-tight);
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-5);
  color: var(--heading-color);
}

.lp-hero__lede {
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--text-color);
  margin: 0 0 var(--space-6);
}

.lp-hero__note {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin: var(--space-5) 0 0;
}

.lp-cta { display: flex; flex-wrap: wrap; gap: var(--space-3); }

.lp-btn {
  display: inline-flex;
  align-items: center;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: 600;
  text-decoration: none;
  border-bottom: none;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    transform var(--duration-instant) var(--ease-out);
}
.lp-btn:active { transform: translateY(1px); }

.lp-btn--primary { background: var(--accent); color: var(--bg); border: 1px solid var(--accent); }
.lp-btn--primary:hover { background: var(--brand-color-strong, var(--accent)); }

.lp-btn--ghost { background: transparent; color: var(--text-color); border: 1px solid var(--border-color); }
.lp-btn--ghost:hover { border-color: var(--accent); }

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

.lp-h2 {
  font-size: var(--text-2xl);
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-5);
  color: var(--heading-color);
}

.lp-prose {
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text-color);
  margin: 0 0 var(--space-4);
  max-width: 42rem;
}
.lp-prose--muted { color: var(--text-muted); font-size: var(--text-sm); }

.lp-problem { padding-block: var(--space-7); border-top: 1px solid var(--border-color); }

.lp-phases {
  list-style: none;
  counter-reset: lp-phase;
  margin: var(--space-6) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
  max-width: 42rem;
}
.lp-phases li {
  counter-increment: lp-phase;
  display: grid;
  grid-template-columns: auto auto 1fr;
  align-items: baseline;
  gap: var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.lp-phases li::before {
  content: counter(lp-phase);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.lp-phases__name { font-weight: 600; color: var(--text-color); }

/* --- the two-audience split ------------------------------------------- */
.lp-split {
  display: grid;
  gap: var(--space-5);
  padding-block: var(--space-7);
  border-top: 1px solid var(--border-color);
}
@media (min-width: 60rem) {
  .lp-split { grid-template-columns: 1fr 1fr; gap: var(--space-6); }
}

.lp-card {
  background: var(--panel-fill-raised);
  -webkit-backdrop-filter: var(--panel-blur);
  backdrop-filter: var(--panel-blur);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-2);
  padding: var(--space-6);
}

.lp-card__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 var(--space-3);
}

.lp-card__title {
  font-size: var(--text-xl);
  line-height: var(--leading-snug);
  margin: 0 0 var(--space-4);
  color: var(--heading-color);
}

.lp-list { margin: var(--space-5) 0 0; padding: 0; list-style: none; display: grid; gap: var(--space-4); }
.lp-list li {
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--text-muted);
  padding-left: var(--space-4);
  border-left: 2px solid var(--border-color);
}
.lp-list strong { color: var(--text-color); font-weight: 600; }

/* --- inventory --------------------------------------------------------- */
.lp-inventory { padding-block: var(--space-7); border-top: 1px solid var(--border-color); }

.lp-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: var(--space-4);
  margin: 0 0 var(--space-5);
}
.lp-stat {
  background: var(--surface-2);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  padding: var(--space-4);
}
.lp-stat dt {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-2);
}
.lp-stat dd {
  margin: 0;
  font-size: var(--text-3xl);
  font-weight: 600;
  color: var(--heading-color);
  font-variant-numeric: tabular-nums;
}

.lp-close { padding-block: var(--space-7) var(--space-8); border-top: 1px solid var(--border-color); }

/* ==========================================================================
   Folded in from hyperbolic-fixes.css — rules with no existing counterpart.
   See docs/UI-AUDIT.md for the defect each one closes.
   ========================================================================== */

/* D8 — `.container` already had `margin: 0 auto`; the ~100px off-centre the
   audit measured was the scrollbar eating one side. */
html { scrollbar-gutter: stable both-edges; }

/* D3 — content should never be a direct child of the void. `main.container`
   is the page column (base.html); the header's inner `.container` is a
   different element and is deliberately not matched. Theme-neutral rule
   reading tokens (Law 4) — dark resolves every one to nothing, so it stays
   pixel-identical there. */
main.container {
  background: var(--page-fill);
  -webkit-backdrop-filter: var(--panel-blur);
  backdrop-filter: var(--panel-blur);
  border: 1px solid var(--page-border);
  border-radius: var(--radius-card);
  box-shadow: var(--page-shadow);
  padding-block: var(--page-pad-block);
  margin-block-end: var(--space-7);
}

/* D7 — the flex ancestors have to be able to shrink too, or the scroll
   child never gets the chance to. */
.mira-conv,
.mira-conv__body { min-height: 0; }

/* D11 — two radii, not three: --radius-card for panels, --radius for inner
   blocks and controls, --radius-pill for chips. */
.mira-console__frame,
.mira-rail { border-radius: var(--radius-card); }
.mira-sess,
.mira-newconv { border-radius: var(--radius); }

/* D12 — a not-yet-live control should not look clickable. */
[aria-disabled="true"] {
  color: var(--text-faint, var(--text-muted));
  cursor: not-allowed;
}
.fb-tab[aria-disabled="true"] .tag {
  background: var(--surface-2, var(--surface-raised));
  color: var(--text-faint, var(--text-muted));
  border-color: transparent;
}

/* ==========================================================================
   Hyperfocus (BEN-142) — one decision at a time.

   Subtraction only. Every rule here hides something or quiets something; none
   of it moves layout, so a page looks the same minus the noise rather than
   reflowed into a different design. The exit control is deliberately outside
   this block's reach — a stripped shell you cannot leave is a trap.
   ========================================================================== */

:root[data-hyperfocus] .nav__group,
:root[data-hyperfocus] .header-nav__link,
:root[data-hyperfocus] .nav__palette-hint,
:root[data-hyperfocus] .alpha-pill,
:root[data-hyperfocus] .header-icon--has-badge .header-icon__badge {
  display: none;
}

/* The inbox and feedback affordances stay reachable but stop advertising.
   Removing them entirely would mean a user in hyperfocus cannot report the
   bug they just hit. */
:root[data-hyperfocus] .header-icon {
  opacity: 0.35;
  transition: opacity var(--duration-fast) var(--ease-out);
}
:root[data-hyperfocus] .header-icon:hover,
:root[data-hyperfocus] .header-icon:focus-visible { opacity: 1; }

/* News is the single loudest source of drift on a long-form reading day. */
:root[data-hyperfocus] .news-strip,
:root[data-hyperfocus] .today-block--news { display: none; }

/* The exit affordance. Reads as chrome, not as a primary action — it should
   be findable without competing with the work. */
.hyperfocus-exit { margin-left: auto; }
.hyperfocus-exit__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: transparent;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wider);
  cursor: pointer;
  transition:
    color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out);
}
.hyperfocus-exit__btn:hover { color: var(--text-color); border-color: var(--accent); }
.hyperfocus-exit__btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.hyperfocus-exit__dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--accent);
}


/* ===================================================================
   ONBOARDING BUBBLES — the first-run strip (design handoff 1b)
   ===================================================================
   A tip that occupies layout space directly above the element it
   annotates. Not a popover: nothing floats, nothing is positioned at
   runtime, nothing can cover its own anchor at 200% zoom. Tokens live
   in the :root block up top; keyframes live in motion.css.
   =================================================================== */

/* The slot. Always rendered, usually empty. Empty = zero box, so an
   unconfigured surface costs nothing visually. */
.ob-bubble-slot:empty { display: none; }

.ob-bubble {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  max-width: var(--bubble-maxw);
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--bubble-fill);
  -webkit-backdrop-filter: var(--bubble-blur);
  backdrop-filter: var(--bubble-blur);
  border: 1px solid var(--bubble-border);
  border-left: 3px solid var(--bubble-rule);
  border-radius: 0 var(--radius-input) var(--radius-input) 0;
  box-shadow: var(--bubble-shadow);
}

.ob-bubble__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Kicker carries the tip label and the counter, so the accent rule is
   never the only thing distinguishing a tip from page content. */
.ob-bubble__kicker {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
  color: var(--accent);
}

.ob-bubble__text {
  margin: 0;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--text-color);
  text-wrap: pretty;
}

.ob-bubble__actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-1);
  flex-wrap: wrap;
}

/* Advance — reads as the primary move but carries no button chrome; a
   filled amber button here would outweigh the page's own CTA. */
.ob-bubble__next {
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}
.ob-bubble__next:hover { color: var(--accent-hover); }

.ob-bubble__skip {
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  font-size: var(--text-sm);
  color: var(--text-alt-color);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.ob-bubble__skip:hover { color: var(--accent-hover); }

.ob-bubble__close {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 0 2px;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1;
  color: var(--text-faint);
  cursor: pointer;
}
.ob-bubble__close:hover { color: var(--text-color); }

.ob-bubble__next:focus-visible,
.ob-bubble__skip:focus-visible,
.ob-bubble__close:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* No-JS fallback: the forms are plain POSTs, so nothing to hide. The
   inline form must not introduce a line box of its own. */
.ob-bubble form { display: contents; }

/* Shared reading-first curriculum outline. Inherits all accessibility scales. */
.learning-page { max-width: var(--maxw); overflow-wrap: anywhere; }
.learning-page p, .learning-page .md, .learning-section__body { font-family: var(--font-sans); font-size: var(--text-base); line-height: var(--leading-normal); }
.learning-outline { list-style: none; padding: 0; margin: 0; }
.learning-section { padding: var(--space-5); margin-bottom: var(--space-4); border: var(--border-thin) solid var(--border-color); border-radius: var(--radius-card); }
.learning-section > details > summary { font-size: var(--text-lg); font-weight: var(--weight-semibold); color: var(--heading-color); }
:where(.learning-section) summary:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.learning-section__body summary { cursor: pointer; padding-block: var(--space-2); }
.learning-section > details > summary { cursor: pointer; line-height: var(--leading-snug); }
.learning-section__body { padding-top: var(--space-4); }
.learning-section__body h3 { margin-top: var(--space-5); }
.saved-prose { white-space: pre-wrap; overflow-wrap: anywhere; }

/* Shared reader keeps the source beside its context and inherits accessibility tokens. */
.resource-reader { margin-block: var(--space-4); padding: var(--space-4); border: var(--border-thin) solid var(--border-color); border-radius: var(--radius-card); background: var(--surface); }
/* Reclaim the card inset for reading without widening the surrounding notes. */
.learning-section__body > .resource-reader { margin-inline: calc(-1 * var(--space-5)); padding-inline: var(--space-3); }
.resource-reader[hidden] { display: none; }
.resource-reader__frame { display: block; width: 100%; height: var(--resource-reader-height); border: var(--border-thin) solid var(--border-color); border-radius: var(--radius-sm); }
[data-resource-heading]:focus, [data-resource-reflection]:focus { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }
