    :root {
      /* ── font families (raw, theme-independent) ──
         These never change per theme — they're the raw building blocks
         that theme blocks compose into role tokens (--font-chrome etc.). */
      --display: "Fraunces", Georgia, serif;
      --body: "Manrope", ui-sans-serif, system-ui, sans-serif;
      --mono: "JetBrains Mono", ui-monospace, monospace;
      --radius-pill: 999px;
    }

    /* ── LIGHT theme (also the default) ──
       All theme-dependent values live INSIDE the [data-theme="..."]
       blocks — including light — so they cascade correctly when a
       theme attribute is set on any nested element (e.g. the chooser
       modal's .theme-preview div, which sets its own data-theme to
       show the user a real-look preview while the rest of the page
       stays on a different theme).

       Element styles reference design tokens (--font-chrome,
       --radius-card, --body-gradient, etc.) instead of hardcoded
       values, so adding a theme = override these tokens, not chase
       individual rules. */
    [data-theme="light"] {
      /* palette — clean cool day */
      --bg:        #f7f8fb;
      --surface: #ffffff;
      --surface-2:   #f1f4f9;
      --border:        #dde3ed;
      --border-strong: #c7d0de;
      --text:         #0d1c2e;
      --text-dim:     #475569;
      --text-faint:   #94a3b8;
      --accent:         #0ea5e9;
      --accent-deep:    #0369a1;
      --accent-soft:    #e0f2fe;
      --danger:        #e11d48;
      --warning:       #f59e0b;
      --success:        #15803d;

      /* font role tokens (chrome = nav/labels, meta = tiny chrome,
         input = composer). Code blocks always use --mono regardless. */
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);

      /* radii */
      --radius-chip:   8px;         /* buttons, badges, inputs */
      --radius-card:   12px;        /* cards, modals, composer, panels */
      --radius-bubble: 14px;        /* message bubbles */

      /* CRT scanline overlay — 0 hides it entirely */
      --scanline-opacity: 0;

      /* atmospheric body gradient */
      --body-gradient:
        radial-gradient(80vw 55vh at 18% -2%, rgba(14, 165, 233, 0.10), transparent 65%),
        radial-gradient(85vw 60vh at 80% -6%, rgba(56, 189, 248, 0.08), transparent 70%),
        radial-gradient(95vw 65vh at 50% -12%, rgba(147, 197, 253, 0.06), transparent 60%),
        var(--bg);

      /* elevation — soft layered shadows */
      --elev-1: 0 1px 2px rgba(13, 28, 46, 0.04);
      --elev-2: 0 4px 16px -4px rgba(13, 28, 46, 0.08);
      --elev-3: 0 12px 32px -12px rgba(13, 28, 46, 0.12);

      /* glass surfaces */
      --glass-bg:    rgba(255, 255, 255, 0.78);
      --glass-inset: rgba(255, 255, 255, 0.85);
      --glass-shadow:0 1px 2px rgba(13, 28, 46, 0.03), 0 24px 56px -22px rgba(13, 28, 46, 0.14);
      --glass-border:rgba(199, 208, 222, 0.55);

      /* ── STRUCTURAL TOKENS — let themes differ in more than color ──
         These are the dimensions that make a theme actually FEEL
         different vs just look different. Defaults below = Light's
         baseline; themes with strong opinions (Atrium spacious, Pitch
         tight, Terminal dense, Glass slow, etc.) override these. */

      /* spacing scale — Atrium goes bigger, Pitch/Slate/Terminal go tighter */
      --space-xs:    0.25rem;
      --space-sm:    0.5rem;
      --space-md:    0.85rem;
      --space-lg:    1.25rem;
      --space-xl:    2rem;

      /* border treatment — Inkwell wants 1.5px hand-drawn, Terminal 2px sharp */
      --border-width: 1px;

      /* motion — Pitch/Slate/Terminal snappy, Glass/Cosmic/Editorial soft */
      --transition-fast: 80ms;
      --transition-base: 160ms;
      --transition-slow: 280ms;
      --ease-base: ease;

      /* backdrop blur — Glass/Cosmic heavy, Pitch/Slate/Terminal off */
      --backdrop-blur: 20px;
      --backdrop-saturate: 140%;

      /* interactive brand details — themes can own selection / scrollbar
         / focus to express identity even in micro-moments */
      --selection-bg: color-mix(in srgb, var(--accent) 80%, transparent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--text) 18%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--text) 32%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 55%, transparent);

      /* link decoration — Editorial/Vellum could go wavy; Pitch solid-2px */
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 2px;
    }

    [data-theme="terminal"] {
      /* "black ice" — deepest blue-black with no actual navy in it.
         A tight luminance ladder (snow → snow-bright → snow-cool) so
         surfaces stack legibly without ever feeling like flat boxes. */
      --bg:        #08090d;       /* the lake at twilight */
      --surface: #11141c;       /* surface lift, ~ 2% luminance step */
      --surface-2:   #161a24;
      --border:        #1f242f;
      --border-strong: #2d3340;
      --text:         #f1f5f9;       /* near-white, slight cool */
      --text-dim:     #94a3b8;
      --text-faint:   #64748b;

      /* arctic cyan — not Tailwind sky-blue. This is the color of
         aurora and light through ice; it reads as "ice" not "primary". */
      --accent:         #67e8f9;
      --accent-deep:    #22d3ee;
      --accent-soft:    rgba(103, 232, 249, 0.18);

      --danger:        #fb7185;
      --warning:       #fbbf24;
      --success:        #34d399;

      /* Frost surfaces on near-black: slightly tinted, soft top highlight
         that catches the eye like real frosted glass under low light. */
      --glass-bg:    rgba(17, 20, 28, 0.55);
      --glass-inset: rgba(255, 255, 255, 0.07);
      --glass-shadow:0 1px 2px rgba(0, 0, 0, 0.35), 0 24px 56px -22px rgba(0, 0, 0, 0.7);
      --glass-border:rgba(45, 51, 64, 0.7);

      /* ── TERMINAL design-token overrides ──
         The terminal aesthetic: mono chrome, sharp corners, CRT scanlines,
         hairline borders instead of shadows. Switching to this theme flips
         every element using the tokens — no per-rule edits needed. */
      --font-chrome: var(--mono);
      --font-meta:   var(--mono);
      --font-input:  var(--mono);
      --radius-chip:   2px;
      --radius-card:   2px;
      --radius-bubble: 2px;
      --scanline-opacity: 1;
      --elev-1: none;
      --elev-2: none;
      --elev-3: none;
      /* Richer aurora gradient — terminal reads best with stronger atmosphere. */
      --body-gradient:
        radial-gradient(80vw 55vh at 18% -2%, rgba(34, 211, 238, 0.19), transparent 65%),
        radial-gradient(85vw 60vh at 80% -6%, rgba(14, 165, 233, 0.16), transparent 70%),
        radial-gradient(95vw 65vh at 50% -12%, rgba(96, 165, 250, 0.13), transparent 60%),
        var(--bg);

      /* Terminal opinions: dense, snappy, sharp, no blur, block-style chrome. */
      --space-xs:    0.18rem;
      --space-sm:    0.4rem;
      --space-md:    0.7rem;
      --space-lg:    1rem;
      --space-xl:    1.6rem;
      --border-width: 2px;
      --transition-fast: 30ms;
      --transition-base: 60ms;
      --transition-slow: 120ms;
      --ease-base: linear;
      --backdrop-blur: 0px;
      --backdrop-saturate: 100%;
      --selection-bg: var(--accent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 40%, transparent);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 2px;
      --link-underline-offset: 3px;
    }

    /* ── DARK theme ──
       Neutral standard dark — no color cast (vs Midnight's cool slate or
       Dusk's warm aubergine). Reads like macOS dark / GitHub dark / Linear
       dark — the "default expected" dark mode. Cyan accent for brand
       continuity. */
    [data-theme="dark"] {
      /* neutral gray ladder — warm-neutral, no blue cast */
      --bg:        #131418;       /* near-black, faint warm cast */
      --surface: #1c1d22;       /* surface lift */
      --surface-2:   #23252b;       /* card surfaces */
      --border:        #2e3038;
      --border-strong: #3a3d47;

      --text:         #ececef;       /* warm off-white */
      --text-dim:     #a1a4ad;
      --text-faint:   #6f7280;

      /* same cyan accent family — brand continuity across themes */
      --accent:         #38bdf8;
      --accent-deep:    #0ea5e9;
      --accent-soft:    rgba(56, 189, 248, 0.18);

      --danger:        #fb7185;
      --warning:       #fbbf24;
      --success:        #34d399;

      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   8px;
      --radius-card:   12px;
      --radius-bubble: 14px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 2px rgba(0, 0, 0, 0.40);
      --elev-2: 0 8px 24px -8px rgba(0, 0, 0, 0.50);
      --elev-3: 0 16px 48px -16px rgba(0, 0, 0, 0.60);

      --glass-bg:    rgba(28, 29, 34, 0.65);
      --glass-inset: rgba(255, 255, 255, 0.04);
      --glass-shadow:0 1px 2px rgba(0, 0, 0, 0.45), 0 24px 56px -22px rgba(0, 0, 0, 0.7);
      --glass-border:rgba(56, 189, 248, 0.14);

      /* very restrained gradient — neutral gray ground shouldn't tint */
      --body-gradient:
        radial-gradient(80vw 55vh at 18% -2%, rgba(56, 189, 248, 0.06), transparent 65%),
        radial-gradient(85vw 60vh at 80% -6%, rgba(255, 255, 255, 0.03), transparent 70%),
        var(--bg);

      /* Dark inherits Light's structural defaults (no strong opinion). */
      --space-xs:    0.25rem;
      --space-sm:    0.5rem;
      --space-md:    0.85rem;
      --space-lg:    1.25rem;
      --space-xl:    2rem;
      --border-width: 1px;
      --transition-fast: 80ms;
      --transition-base: 160ms;
      --transition-slow: 280ms;
      --ease-base: ease;
      --backdrop-blur: 20px;
      --backdrop-saturate: 140%;
      --selection-bg: color-mix(in srgb, var(--accent) 80%, transparent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--text) 22%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--text) 40%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 55%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 2px;
    }
    [data-theme="dark"] .wordmark .y { color: var(--accent); }
    [data-theme="dark"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(56, 189, 248, 0.28); }
      50%      { text-shadow: 0 0 0.55em rgba(56, 189, 248, 0.48); }
    }
    [data-theme="dark"] .cursor { background: var(--accent); }

    /* ── BLACK theme ──
       True #000000 ground — AMOLED-friendly, maximum contrast. Surface
       lifts kept very subtle so depth still reads without muddying the
       black. No aurora gradient on the body (gradients smear true-black
       into gray); contrast comes from typography + surface chips. */
    [data-theme="black"] {
      --bg:        #000000;       /* true black */
      --surface: #0a0a0c;       /* minimal lift */
      --surface-2:   #131316;       /* card surfaces */
      --border:        #1f1f24;
      --border-strong: #2a2a30;

      --text:         #fafafa;       /* pure near-white for max contrast */
      --text-dim:     #a0a0a8;
      --text-faint:   #6b6b75;

      /* brighter cyan to pop against true black */
      --accent:         #67e8f9;
      --accent-deep:    #22d3ee;
      --accent-soft:    rgba(103, 232, 249, 0.16);

      --danger:        #fb7185;
      --warning:       #fbbf24;
      --success:        #34d399;

      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   8px;
      --radius-card:   12px;
      --radius-bubble: 14px;
      --scanline-opacity: 0;
      /* shadows don't render on pure black — substitute with subtle ring
         borders for surface elevation cues */
      --elev-1: 0 0 0 1px rgba(255, 255, 255, 0.04);
      --elev-2: 0 0 0 1px rgba(255, 255, 255, 0.06);
      --elev-3: 0 0 0 1px rgba(255, 255, 255, 0.08);

      --glass-bg:    rgba(10, 10, 12, 0.72);
      --glass-inset: rgba(255, 255, 255, 0.03);
      --glass-shadow:0 0 0 1px rgba(255, 255, 255, 0.05);
      --glass-border:rgba(103, 232, 249, 0.18);

      /* no gradient — true black IS the aesthetic; only --bg */
      --body-gradient: var(--bg);

      /* Black: defaults mostly, but scrollbar uses white (not ink-mix
         since ink=white here, which would be invisible). */
      --space-xs:    0.25rem;
      --space-sm:    0.5rem;
      --space-md:    0.85rem;
      --space-lg:    1.25rem;
      --space-xl:    2rem;
      --border-width: 1px;
      --transition-fast: 80ms;
      --transition-base: 160ms;
      --transition-slow: 280ms;
      --ease-base: ease;
      --backdrop-blur: 20px;
      --backdrop-saturate: 140%;
      --selection-bg: var(--accent);
      --selection-fg: #000000;
      --scrollbar-thumb: rgba(255, 255, 255, 0.18);
      --scrollbar-thumb-hover: rgba(255, 255, 255, 0.35);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 2px;
    }
    [data-theme="black"] .wordmark .y { color: var(--accent); }
    [data-theme="black"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(103, 232, 249, 0.32); }
      50%      { text-shadow: 0 0 0.55em rgba(103, 232, 249, 0.55); }
    }
    [data-theme="black"] .cursor { background: var(--accent); }

    /* ── MIDNIGHT theme ──
       Cool dark cousin of Light. Same DNA — Manrope sans, rounded corners,
       cyan accent — just on a deep cool slate ground. No scanlines, no
       cyberpunk grit. Sits in the "clean modern dark" slot between Light
       (clean cool day) and Terminal (utility cool dark). */
    [data-theme="midnight"] {
      /* ocean-midnight blue — deeper + more saturated than slate, so
         Midnight has a distinct identity vs Dark (warm neutral) and
         doesn't read as "the same dark with a tint." */
      --bg:        #0a1733;       /* saturated navy ground */
      --surface: #122247;       /* surface lift */
      --surface-2:   #1a2d5a;       /* card surfaces */
      --border:        #2a3a66;
      --border-strong: #3a4d80;

      /* cool off-white text */
      --text:         #e6edf6;
      --text-dim:     #9aa8bd;
      --text-faint:   #6b7891;

      /* "moonlit" cyan — brighter + colder than Light's #38bdf8.
         Reads as moonlight on water against the deep navy. */
      --accent:         #67e8f9;
      --accent-deep:    #22d3ee;
      --accent-soft:    rgba(103, 232, 249, 0.20);

      --danger:        #fb7185;
      --warning:       #fbbf24;
      --success:        #34d399;

      /* tokens — sans chrome, rounded, no scanlines, soft cool shadows */
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   8px;
      --radius-card:   12px;
      --radius-bubble: 14px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 2px rgba(0, 0, 0, 0.35);
      --elev-2: 0 8px 24px -8px rgba(0, 0, 0, 0.45);
      --elev-3: 0 16px 48px -16px rgba(0, 0, 0, 0.55);

      /* glass — cool tinted frost over slate */
      --glass-bg:    rgba(19, 28, 46, 0.65);
      --glass-inset: rgba(255, 255, 255, 0.04);
      --glass-shadow:0 1px 2px rgba(0, 0, 0, 0.45), 0 24px 56px -22px rgba(0, 0, 0, 0.7);
      --glass-border:rgba(56, 189, 248, 0.16);

      /* soft cool aurora — restrained, lets the slate ground breathe */
      --body-gradient:
        radial-gradient(80vw 55vh at 18% -2%, rgba(56, 189, 248, 0.10), transparent 65%),
        radial-gradient(85vw 60vh at 80% -6%, rgba(96, 165, 250, 0.08), transparent 70%),
        radial-gradient(95vw 65vh at 50% -12%, rgba(147, 197, 253, 0.05), transparent 60%),
        var(--bg);

      /* Midnight inherits structural defaults. */
      --space-xs:    0.25rem;
      --space-sm:    0.5rem;
      --space-md:    0.85rem;
      --space-lg:    1.25rem;
      --space-xl:    2rem;
      --border-width: 1px;
      --transition-fast: 80ms;
      --transition-base: 160ms;
      --transition-slow: 280ms;
      --ease-base: ease;
      --backdrop-blur: 20px;
      --backdrop-saturate: 140%;
      --selection-bg: color-mix(in srgb, var(--accent) 80%, transparent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--text) 22%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--accent) 50%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 55%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 2px;
    }
    [data-theme="midnight"] .wordmark .y { color: var(--accent); }
    [data-theme="midnight"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(103, 232, 249, 0.30); }
      50%      { text-shadow: 0 0 0.55em rgba(103, 232, 249, 0.55); }
    }
    [data-theme="midnight"] .cursor { background: var(--accent); }
    /* MIDNIGHT signature — actual stars. A tiled 220px pattern of seven
       1–1.5px white dots at varying low opacities, fixed to viewport so
       they don't scroll. No other theme has texture like this; the
       moment you switch to Midnight you're looking up at a night sky. */
    [data-theme="midnight"] body::after {
      content: "";
      position: fixed; inset: 0;
      pointer-events: none;
      z-index: 0;
      background-image:
        radial-gradient(1px 1px at 23px 45px,    rgba(255, 255, 255, 0.85), transparent 50%),
        radial-gradient(1px 1px at 89px 12px,    rgba(255, 255, 255, 0.55), transparent 50%),
        radial-gradient(1.5px 1.5px at 145px 67px,  rgba(255, 255, 255, 0.45), transparent 50%),
        radial-gradient(1px 1px at 178px 134px,  rgba(255, 255, 255, 0.75), transparent 50%),
        radial-gradient(1px 1px at 56px 156px,   rgba(255, 255, 255, 0.40), transparent 50%),
        radial-gradient(1.5px 1.5px at 134px 178px, rgba(255, 255, 255, 0.65), transparent 50%),
        radial-gradient(1px 1px at 12px 187px,   rgba(255, 255, 255, 0.50), transparent 50%);
      background-repeat: repeat;
      background-size: 220px 220px;
    }

    /* ── DUSK theme ──
       Warm dark cozy — the third emotional register. Aubergine ground +
       ember accent, soft glow instead of CRT scanlines, rounded corners
       like light (not sharp like terminal). Note: `--accent` is the
       semantic "primary accent" across themes; in Dusk it's warm amber
       instead of cyan, so all existing `var(--accent)` references
       automatically follow without per-rule edits. */
    [data-theme="dusk"] {
      /* aubergine ladder — deep wine purple, three luminance steps */
      --bg:        #1a1020;       /* deepest aubergine */
      --surface: #251530;       /* surface lift */
      --surface-2:   #2f1d3a;       /* card surfaces */
      --border:        #3a2548;
      --border-strong: #4a3258;

      /* warm off-white text — slight peach to avoid cool cast on warm ground */
      --text:         #f5ecd9;
      --text-dim:     #c9b7a1;
      --text-faint:   #8a7a6c;

      /* ember accent — replaces cyan as primary. */
      --accent:         #fbbf24;       /* warm amber, the new "accent" */
      --accent-deep:    #f59e0b;
      --accent-soft:    rgba(251, 191, 36, 0.18);

      --danger:        #fb7185;       /* coral for destructive */
      --warning:       #fde047;       /* even warmer highlight */
      --success:        #a7f3d0;

      /* tokens — sans chrome, rounded corners, no scanlines, soft warm shadows */
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   10px;
      --radius-card:   14px;
      --radius-bubble: 16px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 2px rgba(0, 0, 0, 0.35);
      --elev-2: 0 8px 24px -8px rgba(0, 0, 0, 0.45);
      --elev-3: 0 16px 48px -16px rgba(0, 0, 0, 0.55);

      /* glass — warm-tinted frost over aubergine */
      --glass-bg:    rgba(37, 21, 48, 0.65);
      --glass-inset: rgba(253, 224, 71, 0.05);
      --glass-shadow:0 1px 2px rgba(0, 0, 0, 0.45), 0 24px 56px -22px rgba(0, 0, 0, 0.7);
      --glass-border:rgba(251, 191, 36, 0.18);

      /* atmospheric warm radial gradients — amber + rose plumes on deep aubergine */
      --body-gradient:
        radial-gradient(80vw 55vh at 18% -2%, rgba(251, 146, 60, 0.16), transparent 65%),
        radial-gradient(85vw 60vh at 80% -6%, rgba(244, 114, 182, 0.12), transparent 70%),
        radial-gradient(95vw 65vh at 50% -12%, rgba(251, 191, 36, 0.10), transparent 60%),
        var(--bg);

      /* Dusk inherits defaults; amber-tinted selection feels right. */
      --space-xs:    0.25rem;
      --space-sm:    0.5rem;
      --space-md:    0.85rem;
      --space-lg:    1.25rem;
      --space-xl:    2rem;
      --border-width: 1px;
      --transition-fast: 100ms;
      --transition-base: 200ms;
      --transition-slow: 320ms;
      --ease-base: ease-out;
      --backdrop-blur: 20px;
      --backdrop-saturate: 140%;
      --selection-bg: color-mix(in srgb, var(--accent) 65%, transparent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 25%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--accent) 50%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 55%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 2px;
    }
    /* Dusk-specific overrides where keyframes / SVG strokes have
       hardcoded color values that --accent alone can't reach. */
    [data-theme="dusk"] .wordmark .y { color: var(--accent); }
    [data-theme="dusk"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(251, 191, 36, 0.32); }
      50%      { text-shadow: 0 0 0.55em rgba(251, 191, 36, 0.55); }
    }
    [data-theme="dusk"] .cursor { background: var(--accent); }

    /* ── EDITORIAL theme ──
       Refined magazine — the only theme using Fraunces (variable serif)
       for chrome. Warm paper cream ground, espresso ink, burgundy accent.
       Hairline rules everywhere instead of shadows; generous card radii;
       oldstyle figures via OpenType. Reads as Bookforum / The Browser /
       a thoughtful Sunday-supplement aesthetic. */
    [data-theme="editorial"] {
      /* paper ladder — warm cream with subtle tonal steps */
      --bg:        #faf7f2;       /* warm paper */
      --surface: #ffffff;       /* surface lift, pure white */
      --surface-2:   #f0ebe0;       /* card / hover surfaces */
      --border:        #d8cfbf;       /* warm hairline */
      --border-strong: #b8ad97;

      /* espresso ink — warm dark, not pure black */
      --text:         #231914;
      --text-dim:     #5a4a3d;
      --text-faint:   #8a7d6e;

      /* burgundy accent — deep, considered, not bright */
      --accent:         #9b2545;
      --accent-deep:    #6e1730;
      --accent-soft:    rgba(155, 37, 69, 0.12);

      --danger:        #c8344c;       /* destructive — coral-burgundy variant */
      --warning:       #c79b3e;       /* muted gold — used for highlights/warmth */
      --success:        #4a6c3a;       /* muted forest — for success states */

      /* THE signature move — Fraunces for chrome. Manrope stays for body
         message text (long-form reading), JetBrains Mono for code. */
      --font-chrome: var(--display);
      --font-meta:   var(--display);
      --font-input:  var(--body);

      /* radii — tight refined buttons, generous cards/bubbles */
      --radius-chip:   6px;
      --radius-card:   16px;
      --radius-bubble: 18px;
      --scanline-opacity: 0;

      /* elevation = hairline rules, not shadows. This is the editorial
         signature — every surface boundary is a 1px line, never a blur. */
      --elev-1: 0 1px 0 var(--border);
      --elev-2: 0 1px 0 var(--border);
      --elev-3: 0 2px 0 var(--border);

      /* glass — warm paper-tinted frost */
      --glass-bg:    rgba(255, 253, 248, 0.85);
      --glass-inset: rgba(255, 255, 255, 0.9);
      --glass-shadow:0 1px 0 var(--border);
      --glass-border:rgba(216, 207, 191, 0.7);

      /* Editorial commits to STILL PAGES — no atmospheric mesh, no
         radial plumes. Real magazines and books don't have glowing
         backdrops; the white space IS the page. This is the editorial
         move: stillness as confidence. */
      --body-gradient: var(--bg);

      /* Editorial opinions: calm reading rhythm, slow ease, light blur. */
      --space-xs:    0.3rem;
      --space-sm:    0.6rem;
      --space-md:    1rem;
      --space-lg:    1.5rem;
      --space-xl:    2.25rem;
      --border-width: 1px;
      --transition-fast: 120ms;
      --transition-base: 220ms;
      --transition-slow: 380ms;
      --ease-base: cubic-bezier(0.25, 0.1, 0.25, 1);
      --backdrop-blur: 12px;
      --backdrop-saturate: 110%;
      --selection-bg: color-mix(in srgb, var(--accent) 25%, transparent);
      --selection-fg: var(--text);
      --scrollbar-thumb: color-mix(in srgb, var(--text) 16%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--text) 32%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 50%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 4px;
    }
    /* Editorial-specific tweaks where Fraunces' typographic features
       earn their slot. Oldstyle figures + ligatures + contextual
       alternates give the magazine character. Applied broadly so any
       text rendered in --font-chrome (sidebar nav, labels, buttons,
       headers) gets the proper editorial typesetting. */
    [data-theme="editorial"] {
      font-feature-settings: "onum" 1, "liga" 1, "calt" 1;
    }
    [data-theme="editorial"] .wordmark .y { color: var(--accent); }
    [data-theme="editorial"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(155, 37, 69, 0.28); }
      50%      { text-shadow: 0 0 0.55em rgba(155, 37, 69, 0.48); }
    }
    [data-theme="editorial"] .cursor { background: var(--accent); }
    /* Editorial signature — burgundy DROP CAP on the first letter of
       every assistant message's first paragraph. Textbook magazine
       move; only renders when the first child is a real paragraph (not
       a code block, list, etc.), and gracefully no-ops on short
       single-word replies. */
    [data-theme="editorial"] .msg.assistant .msg-body > p:first-child::first-letter {
      font-family: var(--display);
      font-weight: 600;
      font-size: 3.4em;
      line-height: 0.82;
      float: left;
      margin: 0.08em 0.12em 0 0;
      padding-top: 0.04em;
      color: var(--accent);
      /* slight optical alignment — drop caps look "off" without negative
         text-indent compensation for serif side-bearings */
      text-indent: -0.04em;
    }

    /* ── EDITORIAL — STRUCTURAL OVERRIDES ──
       This is where Editorial stops being "Light with a serif font" and
       becomes an actual magazine. Bubble paradigm gone — messages are
       indented paragraphs with serif attribution. Hairline section
       breaks between turns. Composer is a flat writing field with a
       single hairline above, no box. Narrower reading column. Reads
       as a long-form document, not a chat. */

    /* Tighter reading column + more vertical breathing */
    [data-theme="editorial"] .conv {
      max-width: 720px;
      padding: 2.4rem 1.8rem 8rem;     /* extra bottom for composer overlap */
      gap: 2rem;
    }

    /* User turn — strip bubble entirely. Just attribution + body. */
    [data-theme="editorial"] .msg.user {
      align-self: stretch;
      background: transparent;
      border: none;
      border-right: none;
      border-radius: 0;
      padding: 0;
      max-width: 100%;
    }
    [data-theme="editorial"] .msg.user::before {
      content: "You";
      font-family: var(--display);
      font-weight: 500;
      font-size: 0.85rem;
      font-style: italic;
      letter-spacing: 0;
      text-transform: none;
      text-align: left;
      margin-bottom: 0.35rem;
      color: var(--text-dim);
    }
    /* User preview (live transcription) keeps the dashed indicator
       since it's a real "still recording" state. */
    [data-theme="editorial"] .msg.user.preview {
      background: transparent;
      border: none;
      border-left: 2px dashed var(--border);
      padding: 0 0 0 0.9rem;
    }
    [data-theme="editorial"] .msg.user.preview::before { content: "Drafting"; }

    /* Assistant turn — strip bubble. Wider reading. */
    [data-theme="editorial"] .msg.assistant {
      align-self: stretch;
      background: transparent;
      border: none;
      border-left: none;
      border-radius: 0;
      padding: 0;
      max-width: 100%;
    }
    [data-theme="editorial"] .msg.assistant::before {
      content: "Alyx";
      font-family: var(--display);
      font-weight: 500;
      font-size: 0.85rem;
      font-style: italic;
      letter-spacing: 0;
      text-transform: none;
      margin-bottom: 0.35rem;
      color: var(--accent);
    }

    /* SECTION BREAK between turns — a hairline rule with breathing space.
       Skip on the first msg (no need for a rule at the top). */
    [data-theme="editorial"] .msg + .msg {
      padding-top: 2rem;
      border-top: 1px solid color-mix(in srgb, var(--text) 12%, transparent);
    }

    /* Wider message body — generous line-height for editorial reading */
    [data-theme="editorial"] .msg-body {
      font-size: 1rem;
      line-height: 1.65;
    }

    /* COMPOSER — flat writing field, hairline above, no box. */
    [data-theme="editorial"] .composer-wrap {
      background: linear-gradient(to bottom,
        transparent 0%,
        color-mix(in srgb, var(--bg) 60%, transparent) 40%,
        var(--bg) 100%);
      padding: 1.2rem 1.8rem 1.2rem;
    }
    [data-theme="editorial"] .composer {
      max-width: 720px;
      background: transparent;
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
      border: none;
      border-top: 1px solid var(--border);
      border-radius: 0;
      padding: 0.95rem 0.4rem 0.4rem;
      box-shadow: none;
    }
    /* Voice-mode field — replace ring/halo with a top-edge accent. */
    [data-theme="editorial"] .composer.voice-on {
      border-top: 1.5px solid var(--accent-deep);
      border-left: none;
      border-right: none;
      border-bottom: none;
      box-shadow: none;
      animation: none;
    }
    [data-theme="editorial"] .composer.voice-on.muted {
      border-top: 1.5px solid color-mix(in srgb, var(--danger) 60%, transparent);
      box-shadow: none;
      animation: composer-muted-breath-soft 4s ease-in-out infinite;
    }
    /* Dragging state — solid burgundy top-edge accent */
    [data-theme="editorial"] .composer.dragging {
      border-top: 2px solid var(--accent);
      box-shadow: none;
    }
    [data-theme="editorial"] .composer.dragging::before {
      background: color-mix(in srgb, var(--bg) 92%, transparent);
      backdrop-filter: blur(4px);
      border-radius: 0;
      letter-spacing: 0.12em;
      font-family: var(--display);
      font-style: italic;
      text-transform: none;
      font-size: 0.95rem;
      content: "Drop files to attach";
      color: var(--accent);
    }

    /* ── PITCH theme ──
       Extreme minimalism. Pure black ground, white as the "accent" —
       interactive states flip to inverted color (the existing chrome
       rules use var(--accent) as the hover/active fill, so when --accent is
       white, hovers naturally invert). JetBrains Mono editorial-style
       (not cyberpunk — no scanlines, no rings). Tight 4-6px radii.
       Hairline borders, no shadows. Reads as severe + considered. */
    [data-theme="pitch"] {
      --bg:        #000000;
      --surface: #0a0a0a;
      --surface-2:   #141414;
      --border:        #2a2a2a;
      --border-strong: #3a3a3a;

      --text:         #ffffff;
      --text-dim:     #b0b0b0;
      --text-faint:   #707070;

      /* "ice" = white — the inversion accent. Hover states naturally
         flip to white-on-black because the existing chrome rules use
         var(--accent) as the active background. */
      --accent:         #ffffff;
      --accent-deep:    #e6e6e6;
      --accent-soft:    rgba(255, 255, 255, 0.10);

      --danger:        #ff5577;       /* destructive — one of two non-grayscale colors */
      --warning:       #ffaa33;       /* warm warn — kept for status */
      --success:        #66dd99;

      /* Mono everywhere — the editorial-mono treatment, not Terminal's
         cyberpunk-mono. The geometric tightness reinforces minimalism. */
      --font-chrome: var(--mono);
      --font-meta:   var(--mono);
      --font-input:  var(--mono);

      --radius-chip:   4px;
      --radius-card:   6px;
      --radius-bubble: 8px;
      --scanline-opacity: 0;

      /* Hairline 1px borders for elevation — never shadows. */
      --elev-1: 0 0 0 1px var(--border);
      --elev-2: 0 0 0 1px var(--border);
      --elev-3: 0 0 0 1px var(--border-strong);

      --glass-bg:    rgba(10, 10, 10, 0.85);
      --glass-inset: rgba(255, 255, 255, 0.04);
      --glass-shadow:0 0 0 1px var(--border);
      --glass-border:rgba(255, 255, 255, 0.10);

      /* no gradient — black is the aesthetic */
      --body-gradient: var(--bg);

      /* Pitch opinions: tight, instant, no blur, full inversion on selection. */
      --space-xs:    0.2rem;
      --space-sm:    0.4rem;
      --space-md:    0.7rem;
      --space-lg:    1rem;
      --space-xl:    1.6rem;
      --border-width: 1px;
      --transition-fast: 0ms;
      --transition-base: 50ms;
      --transition-slow: 100ms;
      --ease-base: linear;
      --backdrop-blur: 0px;
      --backdrop-saturate: 100%;
      --selection-bg: #ffffff;
      --selection-fg: #000000;
      --scrollbar-thumb: rgba(255, 255, 255, 0.3);
      --scrollbar-thumb-hover: rgba(255, 255, 255, 0.55);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 1px #000, 0 0 0 3px #ffffff;
      --link-decoration-style: solid;
      --link-decoration-thickness: 2px;
      --link-underline-offset: 3px;
    }
    [data-theme="pitch"] .wordmark .y { color: var(--accent); }
    [data-theme="pitch"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(255, 255, 255, 0.20); }
      50%      { text-shadow: 0 0 0.55em rgba(255, 255, 255, 0.45); }
    }
    [data-theme="pitch"] .cursor { background: var(--accent); }

    /* ── PITCH — STRUCTURAL OVERRIDES ──
       Extreme minimalism. Messages have NO containers — just text with
       a single-character margin marker (A for Alyx, U for You). Composer
       is a hairline-underlined text field, no border on the sides, no
       radius. Brutalist commitment: only content remains. */
    [data-theme="pitch"] .conv {
      max-width: 760px;
      padding: 2.5rem 1.6rem 7rem;
      gap: 1.4rem;
    }
    /* User — single-char margin marker, no bubble */
    [data-theme="pitch"] .msg.user {
      align-self: stretch;
      background: transparent;
      border: none;
      border-right: none;
      border-radius: 0;
      padding: 0 0 0 2.4rem;
      position: relative;
      max-width: 100%;
    }
    [data-theme="pitch"] .msg.user::before {
      content: "U";
      position: absolute;
      left: 0; top: 0.1em;
      width: 1.5rem;
      font-family: var(--mono);
      font-weight: 500;
      font-size: 0.78rem;
      letter-spacing: 0;
      text-transform: none;
      text-align: left;
      color: var(--text-dim);
      margin: 0;
    }
    /* Assistant — same treatment, "A" marker */
    [data-theme="pitch"] .msg.assistant {
      align-self: stretch;
      background: transparent;
      border: none;
      border-left: none;
      border-radius: 0;
      padding: 0 0 0 2.4rem;
      position: relative;
      max-width: 100%;
    }
    [data-theme="pitch"] .msg.assistant::before {
      content: "A";
      position: absolute;
      left: 0; top: 0.1em;
      width: 1.5rem;
      font-family: var(--mono);
      font-weight: 700;
      font-size: 0.78rem;
      letter-spacing: 0;
      text-transform: none;
      text-align: left;
      color: var(--accent);
      margin: 0;
    }
    [data-theme="pitch"] .msg-body {
      font-family: var(--mono);
      font-size: 0.85rem;
      line-height: 1.55;
    }
    /* Preview state: dashed border above to indicate "still recording" */
    [data-theme="pitch"] .msg.user.preview {
      background: transparent;
      border: none;
      border-left: 1px dashed var(--border);
      padding: 0 0 0 1rem;
    }
    [data-theme="pitch"] .msg.user.preview::before { content: "U·"; }
    /* COMPOSER — hairline underline only, nothing else */
    [data-theme="pitch"] .composer-wrap {
      background: linear-gradient(to bottom,
        transparent 0%,
        color-mix(in srgb, var(--bg) 70%, transparent) 50%,
        var(--bg) 100%);
      padding: 0.9rem 1.6rem 0.9rem;
    }
    [data-theme="pitch"] .composer {
      max-width: 760px;
      background: transparent;
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
      border: none;
      border-top: 1px solid var(--border-strong);
      border-radius: 0;
      padding: 0.7rem 0;
      box-shadow: none;
    }
    [data-theme="pitch"] .composer.voice-on {
      border: none;
      border-top: 1px solid var(--accent);
      box-shadow: none;
      animation: none;
    }
    [data-theme="pitch"] .composer.voice-on.muted {
      border: none;
      border-top: 1px solid color-mix(in srgb, var(--danger) 60%, transparent);
    }
    [data-theme="pitch"] .composer.dragging {
      border: none;
      border-top: 2px solid var(--accent);
    }
    [data-theme="pitch"] .composer.dragging::before {
      background: rgba(0, 0, 0, 0.88);
      backdrop-filter: none;
      border-radius: 0;
      letter-spacing: 0.22em;
      color: var(--accent);
    }

    /* ── GLASS theme ──
       Atmospheric frosted dark. Deep navy ground + LARGE vibrant aurora
       mesh (violet + pink + blue) that surfaces refract through their
       existing backdrop-filter blur. Lavender accent — distinct from
       any other theme's color. Generous 12-20px radii (the softest
       theme). The signature is depth: every surface visibly carries
       the aurora behind it through the frost. */
    [data-theme="glass"] {
      /* deep navy ground — the "behind" layer */
      --bg:        #0a0f1c;
      /* translucent surface lifts — let the aurora show through under
         the per-element backdrop-filter. */
      --surface: rgba(19, 26, 46, 0.55);
      --surface-2:   rgba(29, 38, 64, 0.50);
      --border:        rgba(167, 139, 250, 0.20);
      --border-strong: rgba(167, 139, 250, 0.35);

      --text:         #f0eef8;
      --text-dim:     #b0aecd;
      --text-faint:   #7a7895;

      /* lavender accent — uniquely Glass's color. Distinct from every
         other theme (cyan/amber/burgundy/white are all taken). */
      --accent:         #a78bfa;
      --accent-deep:    #8b5cf6;
      --accent-soft:    rgba(167, 139, 250, 0.18);

      --danger:        #fb7185;
      --warning:       #fbbf24;
      --success:        #34d399;

      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);

      /* the most generous radii of any theme — reinforces "soft glass" */
      --radius-chip:   12px;
      --radius-card:   18px;
      --radius-bubble: 20px;
      --scanline-opacity: 0;

      --elev-1: 0 1px 2px rgba(0, 0, 0, 0.40);
      --elev-2: 0 12px 32px -8px rgba(0, 0, 0, 0.45);
      --elev-3: 0 24px 64px -16px rgba(0, 0, 0, 0.55);

      --glass-bg:    rgba(19, 26, 46, 0.45);
      --glass-inset: rgba(255, 255, 255, 0.06);
      --glass-shadow:0 8px 32px -8px rgba(0, 0, 0, 0.55);
      --glass-border:rgba(167, 139, 250, 0.25);

      /* THE signature — large vibrant aurora plumes that the frost
         refracts. Four radials at different positions = mesh feel. */
      --body-gradient:
        radial-gradient(70vw 60vh at 15% 5%, rgba(167, 139, 250, 0.32), transparent 60%),
        radial-gradient(75vw 55vh at 85% 0%, rgba(244, 114, 182, 0.22), transparent 65%),
        radial-gradient(80vw 65vh at 50% -8%, rgba(96, 165, 250, 0.18), transparent 60%),
        radial-gradient(60vw 50vh at 50% 100%, rgba(167, 139, 250, 0.16), transparent 70%),
        var(--bg);

      /* Glass opinions: airy spacing, slow-glide motion, heavy frost. */
      --space-xs:    0.3rem;
      --space-sm:    0.6rem;
      --space-md:    1rem;
      --space-lg:    1.5rem;
      --space-xl:    2.25rem;
      --border-width: 1px;
      --transition-fast: 140ms;
      --transition-base: 280ms;
      --transition-slow: 460ms;
      --ease-base: cubic-bezier(0.4, 0, 0.2, 1);
      --backdrop-blur: 32px;
      --backdrop-saturate: 180%;
      --selection-bg: color-mix(in srgb, var(--accent) 60%, transparent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 28%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--accent) 55%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 4px color-mix(in srgb, var(--accent) 30%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    [data-theme="glass"] .wordmark .y { color: var(--accent); }
    [data-theme="glass"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(167, 139, 250, 0.32); }
      50%      { text-shadow: 0 0 0.55em rgba(167, 139, 250, 0.55); }
    }
    [data-theme="glass"] .cursor { background: var(--accent); }
    /* GLASS signature — slow aurora drift. The aurora is Glass's whole
       point; static atmosphere is dead atmosphere. Background-position
       shifts by ~8% over 90s in an ease-in-out alternate loop. Slow
       enough to be imperceptible second-to-second; visible over minutes.
       Respect prefers-reduced-motion. */
    @keyframes glass-aurora-drift {
      0%   { background-position: 0% 0%; }
      100% { background-position: 8% 5%; }
    }
    [data-theme="glass"] body {
      animation: glass-aurora-drift 90s ease-in-out infinite alternate;
    }
    @media (prefers-reduced-motion: reduce) {
      [data-theme="glass"] body { animation: none; }
    }

    /* ── GLASS — STRUCTURAL OVERRIDES ──
       Floating chrome. The sidebar detaches from the viewport edges
       (margin + rounded on all 4 corners). Messages float as cards
       with depth shadows. The composer floats with breathing space
       below it. Every surface visibly hovers over the body aurora —
       the whole UI looks like glass plates resting on light. */

    /* Sidebar floats with margin from all edges */
    [data-theme="glass"] .sidebar {
      margin: 14px 0 14px 14px;
      height: calc(100vh - 28px);
      border-radius: var(--radius-card);
      border: 1px solid var(--border-strong);
      box-shadow: var(--elev-3);
      overflow: hidden;
    }
    /* Mobile drawer is already inset — leave default. */

    /* Messages render as floating cards with depth */
    [data-theme="glass"] .msg.user,
    [data-theme="glass"] .msg.assistant {
      box-shadow: var(--elev-2);
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
    }
    /* Composer wrap: more bottom breathing space */
    [data-theme="glass"] .composer-wrap {
      padding: 1.6rem 1.6rem 1.8rem;
    }
    /* Composer floats higher off the bottom edge with stronger shadow */
    [data-theme="glass"] .composer {
      box-shadow:
        var(--elev-3),
        0 0 0 1px color-mix(in srgb, var(--accent) 20%, transparent);
    }

    /* ── SAGE — calm forest light ── */
    [data-theme="sage"] {
      --bg:        #f7f5ee;
      --surface: #ffffff;
      --surface-2:   #ede9dc;
      --border:        #d4cdb8;
      --border-strong: #b8b09b;
      --text:         #3a4a3d;
      --text-dim:     #6b7a6d;
      --text-faint:   #95a397;
      --accent:         #6b8a6f;       /* sage green accent */
      --accent-deep:    #4a6c4d;
      --accent-soft:    rgba(107, 138, 111, 0.16);
      --danger:        #b85c5c;
      --warning:       #c47a4a;       /* terracotta */
      --success:        #4a6c3a;
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   8px;
      --radius-card:   14px;
      --radius-bubble: 16px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 0 var(--border);
      --elev-2: 0 1px 0 var(--border);
      --elev-3: 0 2px 0 var(--border);
      --glass-bg:    rgba(247, 245, 238, 0.85);
      --glass-inset: rgba(255, 255, 255, 0.9);
      --glass-shadow:0 1px 0 var(--border);
      --glass-border:rgba(212, 205, 184, 0.7);
      --body-gradient:
        radial-gradient(80vw 55vh at 18% -2%, rgba(107, 138, 111, 0.10), transparent 65%),
        radial-gradient(85vw 60vh at 80% -6%, rgba(196, 122, 74, 0.06), transparent 70%),
        var(--bg);

      /* Sage: calm, slightly slower than default. Hairline blur. */
      --space-xs:    0.28rem;
      --space-sm:    0.55rem;
      --space-md:    0.95rem;
      --space-lg:    1.4rem;
      --space-xl:    2.1rem;
      --border-width: 1px;
      --transition-fast: 100ms;
      --transition-base: 200ms;
      --transition-slow: 360ms;
      --ease-base: ease-in-out;
      --backdrop-blur: 12px;
      --backdrop-saturate: 110%;
      --selection-bg: color-mix(in srgb, var(--accent) 35%, transparent);
      --selection-fg: var(--text);
      --scrollbar-thumb: color-mix(in srgb, var(--text) 16%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--text) 32%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 60%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    [data-theme="sage"] .wordmark .y { color: var(--accent); }
    [data-theme="sage"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(107, 138, 111, 0.30); }
      50%      { text-shadow: 0 0 0.55em rgba(107, 138, 111, 0.55); }
    }
    [data-theme="sage"] .cursor { background: var(--accent); }
    /* SAGE signature — leaf-veining via two diagonal hairline grids at
       very low opacity. Tiles seamlessly; only catches the eye when you
       look for it. */
    [data-theme="sage"] body::after {
      content: "";
      position: fixed; inset: 0;
      pointer-events: none;
      z-index: 0;
      background-image:
        repeating-linear-gradient( 45deg,
          transparent 0, transparent 30px,
          rgba(107, 138, 111, 0.028) 30px, rgba(107, 138, 111, 0.028) 31px),
        repeating-linear-gradient(-45deg,
          transparent 0, transparent 80px,
          rgba(107, 138, 111, 0.022) 80px, rgba(107, 138, 111, 0.022) 81px);
    }

    /* ── VELLUM — aged manuscript light ── */
    [data-theme="vellum"] {
      --bg:        #f0e6d2;       /* deep cream, older than Editorial's */
      --surface: #f8efd8;
      --surface-2:   #e6dac0;
      --border:        #c9b894;
      --border-strong: #a89870;
      --text:         #3d2f1f;       /* sepia */
      --text-dim:     #6b5742;
      --text-faint:   #9a8567;
      --accent:         #7a1a2e;       /* deep burgundy, darker than Editorial's */
      --accent-deep:    #5a0e1f;
      --accent-soft:    rgba(122, 26, 46, 0.10);
      --danger:        #b8344c;
      --warning:       #a07a30;
      --success:        #5a6c3a;
      /* Fraunces for EVERYTHING — body too, not just chrome */
      --font-chrome: var(--display);
      --font-meta:   var(--display);
      --font-input:  var(--display);
      --radius-chip:   4px;
      --radius-card:   8px;
      --radius-bubble: 10px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 0 var(--border);
      --elev-2: 0 1px 0 var(--border);
      --elev-3: 0 2px 0 var(--border);
      --glass-bg:    rgba(248, 239, 216, 0.85);
      --glass-inset: rgba(255, 255, 255, 0.9);
      --glass-shadow:0 1px 0 var(--border);
      --glass-border:rgba(201, 184, 148, 0.7);
      --body-gradient: var(--bg);

      /* Vellum opinions: calm reading like Editorial; DOTTED link decoration
         for the antique-manuscript feel where references were dotted lines. */
      --space-xs:    0.3rem;
      --space-sm:    0.6rem;
      --space-md:    1rem;
      --space-lg:    1.5rem;
      --space-xl:    2.25rem;
      --border-width: 1px;
      --transition-fast: 120ms;
      --transition-base: 220ms;
      --transition-slow: 380ms;
      --ease-base: cubic-bezier(0.25, 0.1, 0.25, 1);
      --backdrop-blur: 10px;
      --backdrop-saturate: 110%;
      --selection-bg: color-mix(in srgb, var(--accent) 22%, transparent);
      --selection-fg: var(--text);
      --scrollbar-thumb: color-mix(in srgb, var(--text) 16%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--text) 32%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 50%, transparent);
      --link-decoration-style: dotted;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 4px;
    }
    /* Vellum opts into all Fraunces typographic features */
    [data-theme="vellum"] {
      font-feature-settings: "onum" 1, "liga" 1, "calt" 1, "hist" 1;
    }
    [data-theme="vellum"] .wordmark .y { color: var(--accent); }
    [data-theme="vellum"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(122, 26, 46, 0.26); }
      50%      { text-shadow: 0 0 0.55em rgba(122, 26, 46, 0.46); }
    }
    [data-theme="vellum"] .cursor { background: var(--accent); }
    /* VELLUM signature — regional color variation, like genuinely aged
       paper. Four soft radial blooms in slightly different sepia tones. */
    [data-theme="vellum"] body::after {
      content: "";
      position: fixed; inset: 0;
      pointer-events: none;
      z-index: 0;
      background-image:
        radial-gradient(circle at 25% 30%, rgba(160, 122, 48, 0.06), transparent 40%),
        radial-gradient(circle at 75% 70%, rgba(122, 26, 46, 0.045), transparent 40%),
        radial-gradient(circle at 50% 15%, rgba( 89,  64, 27, 0.04), transparent 40%),
        radial-gradient(circle at 15% 85%, rgba(122, 26, 46, 0.035), transparent 40%);
    }

    /* ── MARIGOLD — golden-hour light ── */
    [data-theme="marigold"] {
      --bg:        #fef3e4;       /* warm peach paper */
      --surface: #fff8ed;
      --surface-2:   #fae3c4;
      --border:        #f3d3a8;
      --border-strong: #e0b87a;
      --text:         #3d2817;       /* warm dark */
      --text-dim:     #6b4a2e;
      --text-faint:   #8a6f4e;
      --accent:         #d97706;       /* deep ember */
      --accent-deep:    #b85a00;
      --accent-soft:    rgba(217, 119, 6, 0.14);
      --danger:        #b85c5c;
      --warning:       #f59e0b;
      --success:        #4a6c3a;
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   8px;
      --radius-card:   12px;
      --radius-bubble: 14px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 2px rgba(61, 40, 23, 0.05);
      --elev-2: 0 4px 16px -4px rgba(61, 40, 23, 0.08);
      --elev-3: 0 12px 32px -12px rgba(61, 40, 23, 0.12);
      --glass-bg:    rgba(255, 248, 237, 0.85);
      --glass-inset: rgba(255, 255, 255, 0.9);
      --glass-shadow:0 1px 2px rgba(61, 40, 23, 0.05), 0 16px 48px -16px rgba(61, 40, 23, 0.12);
      --glass-border:rgba(243, 211, 168, 0.7);
      /* SIGNATURE — horizon gradient. All radials anchored low (95-110%
         from top) so the warm light pools at the bottom like late
         afternoon sun through a west-facing window. */
      --body-gradient:
        radial-gradient(120vw 40vh at 30% 105%, rgba(217, 119, 6, 0.22), transparent 65%),
        radial-gradient(130vw 50vh at 75% 110%, rgba(245, 158, 11, 0.18), transparent 70%),
        radial-gradient(100vw 35vh at 50%  95%, rgba(251, 191, 36, 0.12), transparent 60%),
        var(--bg);

      /* Marigold: warm-light defaults, ember selection. */
      --space-xs:    0.25rem;
      --space-sm:    0.5rem;
      --space-md:    0.85rem;
      --space-lg:    1.25rem;
      --space-xl:    2rem;
      --border-width: 1px;
      --transition-fast: 100ms;
      --transition-base: 200ms;
      --transition-slow: 340ms;
      --ease-base: ease-out;
      --backdrop-blur: 16px;
      --backdrop-saturate: 130%;
      --selection-bg: color-mix(in srgb, var(--accent) 40%, transparent);
      --selection-fg: var(--text);
      --scrollbar-thumb: color-mix(in srgb, var(--text) 16%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--accent) 50%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 55%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    [data-theme="marigold"] .wordmark .y { color: var(--accent); }
    [data-theme="marigold"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(217, 119, 6, 0.30); }
      50%      { text-shadow: 0 0 0.55em rgba(217, 119, 6, 0.50); }
    }
    [data-theme="marigold"] .cursor { background: var(--accent); }

    /* ── MARINER — classic nautical dark ── */
    [data-theme="mariner"] {
      --bg:        #0f1e35;       /* deep navy */
      --surface: #182943;
      --surface-2:   #213354;
      --border:        #2a3d60;
      --border-strong: #3a5078;
      --text:         #f0f1f5;       /* crisp white */
      --text-dim:     #a4b1c8;
      --text-faint:   #6b7a98;
      --accent:         #c89832;       /* brass — distinct from cyan family */
      --accent-deep:    #a67822;
      --accent-soft:    rgba(200, 152, 50, 0.18);
      --danger:        #d4646e;
      --warning:       #e8b96e;
      --success:        #5cb380;
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   6px;
      --radius-card:   10px;
      --radius-bubble: 12px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 2px rgba(0, 0, 0, 0.30);
      --elev-2: 0 8px 24px -8px rgba(0, 0, 0, 0.40);
      --elev-3: 0 16px 48px -16px rgba(0, 0, 0, 0.50);
      --glass-bg:    rgba(24, 41, 67, 0.65);
      --glass-inset: rgba(255, 255, 255, 0.04);
      --glass-shadow:0 1px 2px rgba(0, 0, 0, 0.40);
      --glass-border:rgba(200, 152, 50, 0.18);
      --body-gradient:
        radial-gradient(80vw 55vh at 18% -2%, rgba(200, 152, 50, 0.08), transparent 65%),
        radial-gradient(85vw 60vh at 80% -6%, rgba(255, 255, 255, 0.03), transparent 70%),
        var(--bg);

      /* Mariner: cabin-rhythm defaults, brass selection. */
      --space-xs:    0.25rem;
      --space-sm:    0.5rem;
      --space-md:    0.85rem;
      --space-lg:    1.25rem;
      --space-xl:    2rem;
      --border-width: 1px;
      --transition-fast: 100ms;
      --transition-base: 180ms;
      --transition-slow: 320ms;
      --ease-base: ease-out;
      --backdrop-blur: 18px;
      --backdrop-saturate: 130%;
      --selection-bg: var(--accent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 30%, transparent);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    [data-theme="mariner"] .wordmark .y { color: var(--accent); }
    [data-theme="mariner"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(200, 152, 50, 0.28); }
      50%      { text-shadow: 0 0 0.55em rgba(200, 152, 50, 0.50); }
    }
    [data-theme="mariner"] .cursor { background: var(--accent); }
    /* MARINER signature — small-caps treatment on chrome labels (cabin
       brass plate feel). Tightens to the nautical/ship-log aesthetic. */
    [data-theme="mariner"] .sidebar-section-label,
    [data-theme="mariner"] .account-item-label,
    [data-theme="mariner"] .theme-list-label {
      font-variant-caps: all-small-caps;
      letter-spacing: 0.16em;
    }

    /* ── SYNTHWAVE — retro 80s neon ── */
    [data-theme="synthwave"] {
      --bg:        #0a0418;       /* deep purple-black */
      --surface: #1a0a2e;
      --surface-2:   #2a1245;
      --border:        #3a1d5a;
      --border-strong: #4d2870;
      --text:         #f5e5fa;
      --text-dim:     #b890c8;
      --text-faint:   #806a90;
      --accent:         #ff2e7e;       /* hot pink */
      --accent-deep:    #d91860;
      --accent-soft:    rgba(255, 46, 126, 0.16);
      --danger:        #ff2e7e;
      --warning:       #fbbf24;
      --success:        #34d399;
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   8px;
      --radius-card:   14px;
      --radius-bubble: 16px;
      --scanline-opacity: 0;
      --elev-1: 0 0 0 1px rgba(255, 46, 126, 0.10);
      --elev-2: 0 0 24px -4px rgba(255, 46, 126, 0.20);
      --elev-3: 0 0 48px -8px rgba(255, 46, 126, 0.30);
      --glass-bg:    rgba(26, 10, 46, 0.60);
      --glass-inset: rgba(255, 46, 126, 0.08);
      --glass-shadow:0 8px 24px -8px rgba(217, 24, 96, 0.40);
      --glass-border:rgba(255, 46, 126, 0.25);
      /* Magenta + cyan duotone aurora */
      --body-gradient:
        radial-gradient(80vw 55vh at 15% -8%, rgba(255, 46, 126, 0.26), transparent 60%),
        radial-gradient(85vw 60vh at 85% -10%, rgba(34, 211, 238, 0.22), transparent 65%),
        radial-gradient(70vw 50vh at 50% 110%, rgba(255, 46, 126, 0.20), transparent 65%),
        var(--bg);

      /* Synthwave opinions: bouncy back-out easing, neon focus glow,
         medium blur, hot-pink selection. */
      --space-xs:    0.25rem;
      --space-sm:    0.5rem;
      --space-md:    0.85rem;
      --space-lg:    1.25rem;
      --space-xl:    2rem;
      --border-width: 1px;
      --transition-fast: 100ms;
      --transition-base: 200ms;
      --transition-slow: 400ms;
      --ease-base: cubic-bezier(0.68, -0.55, 0.265, 1.55);
      --backdrop-blur: 16px;
      --backdrop-saturate: 160%;
      --selection-bg: var(--accent);
      --selection-fg: #ffffff;
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 50%, transparent);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent), 0 0 14px rgba(255, 46, 126, 0.45);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    [data-theme="synthwave"] .wordmark .y { color: var(--accent); }
    /* Synthwave wordmark glow uses BOTH accents for the duotone outline */
    [data-theme="synthwave"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(255, 46, 126, 0.32),
                              0 0 0.40em rgba( 34, 211, 238, 0.18); }
      50%      { text-shadow: 0 0 0.55em rgba(255, 46, 126, 0.55),
                              0 0 0.80em rgba( 34, 211, 238, 0.30); }
    }
    [data-theme="synthwave"] .cursor { background: var(--accent); }
    /* SYNTHWAVE signature — perspective grid horizon (Drive / Vice City).
       Two repeating linear-gradients form a square grid; perspective
       transform tilts it into the floor. Mask fades both edges so the
       grid emerges from black and disappears at the horizon. */
    [data-theme="synthwave"] body::after {
      content: "";
      position: fixed;
      left: 0; right: 0; bottom: 0;
      height: 55vh;
      pointer-events: none;
      z-index: 0;
      background-image:
        linear-gradient(rgba(255, 46, 126, 0.32) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 46, 126, 0.26) 1px, transparent 1px);
      background-size: 48px 48px;
      transform: perspective(420px) rotateX(72deg);
      transform-origin: center top;
      opacity: 0.7;
      -webkit-mask-image: linear-gradient(to bottom,
        transparent 0%, black 22%, black 78%, transparent 100%);
              mask-image: linear-gradient(to bottom,
        transparent 0%, black 22%, black 78%, transparent 100%);
    }

    /* ── LO-FI — chill warm dark ── */
    [data-theme="lofi"] {
      --bg:        #2a1f17;       /* warm brown ground */
      --surface: #3a2e26;
      --surface-2:   #463730;
      --border:        #5a4a3f;
      --border-strong: #6e5d50;
      --text:         #f5e8d8;       /* warm cream text */
      --text-dim:     #c9b9a8;
      --text-faint:   #8a7d6e;
      --accent:         #f5b888;       /* peach accent */
      --accent-deep:    #d99868;
      --accent-soft:    rgba(245, 184, 136, 0.18);
      --danger:        #d97070;
      --warning:       #f5b888;
      --success:        #8aa78a;       /* soft sage */
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   12px;
      --radius-card:   18px;
      --radius-bubble: 20px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 2px rgba(0, 0, 0, 0.30);
      --elev-2: 0 8px 24px -8px rgba(0, 0, 0, 0.35);
      --elev-3: 0 16px 48px -16px rgba(0, 0, 0, 0.45);
      --glass-bg:    rgba(58, 46, 38, 0.65);
      --glass-inset: rgba(255, 255, 255, 0.04);
      --glass-shadow:0 1px 2px rgba(0, 0, 0, 0.40);
      --glass-border:rgba(245, 184, 136, 0.18);
      --body-gradient:
        radial-gradient(80vw 55vh at 18% -2%, rgba(245, 184, 136, 0.14), transparent 65%),
        radial-gradient(85vw 60vh at 80% -6%, rgba(138, 167, 138, 0.08), transparent 70%),
        var(--bg);

      /* Lo-fi opinions: chill rhythm, ease-in-out, medium blur. */
      --space-xs:    0.3rem;
      --space-sm:    0.6rem;
      --space-md:    1rem;
      --space-lg:    1.5rem;
      --space-xl:    2.25rem;
      --border-width: 1px;
      --transition-fast: 120ms;
      --transition-base: 240ms;
      --transition-slow: 400ms;
      --ease-base: ease-in-out;
      --backdrop-blur: 16px;
      --backdrop-saturate: 120%;
      --selection-bg: color-mix(in srgb, var(--accent) 60%, transparent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 28%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--accent) 55%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    [data-theme="lofi"] .wordmark .y { color: var(--accent); }
    [data-theme="lofi"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(245, 184, 136, 0.28); }
      50%      { text-shadow: 0 0 0.55em rgba(245, 184, 136, 0.50); }
    }
    [data-theme="lofi"] .cursor { background: var(--accent); }
    /* LO-FI signature — film grain via tiled 0.5px dot pattern at
       very low opacity. Reads as warm analog noise on a tape transfer. */
    [data-theme="lofi"] body::after {
      content: "";
      position: fixed; inset: 0;
      pointer-events: none;
      z-index: 0;
      opacity: 0.10;
      background-image:
        radial-gradient(circle at 23% 17%, white 0.5px, transparent 0.5px),
        radial-gradient(circle at 67% 53%, white 0.5px, transparent 0.5px),
        radial-gradient(circle at 14% 73%, white 0.5px, transparent 0.5px),
        radial-gradient(circle at 89% 31%, white 0.5px, transparent 0.5px),
        radial-gradient(circle at 47% 89%, white 0.5px, transparent 0.5px),
        radial-gradient(circle at 78% 11%, white 0.5px, transparent 0.5px),
        radial-gradient(circle at 35% 41%, white 0.5px, transparent 0.5px),
        radial-gradient(circle at 91% 79%, white 0.5px, transparent 0.5px);
      background-size: 5px 5px;
    }

    /* ── INKWELL — handcrafted notebook light ── */
    [data-theme="inkwell"] {
      --bg:        #f6f1e7;       /* cream paper */
      --surface: #fcf8ef;
      --surface-2:   #ede5d2;
      --border:        #2a2a2a;       /* dark borders for ink-on-paper feel */
      --border-strong: #0a0a0a;
      --text:         #0a0a0a;       /* true black ink */
      --text-dim:     #4a4a4a;
      --text-faint:   #888888;
      --accent:         #4338ca;       /* indigo splash */
      --accent-deep:    #3730a3;
      --accent-soft:    rgba(67, 56, 202, 0.12);
      --danger:        #c0392b;
      --warning:       #d4942f;
      --success:        #4a6c3a;
      /* Fraunces for chrome — handwritten/personal feel */
      --font-chrome: var(--display);
      --font-meta:   var(--display);
      --font-input:  var(--body);
      /* SIGNATURE — OFF-AXIS radii. Each corner different, giving every
         surface a subtle "hand-drawn" wobble. The 4-value border-radius
         shorthand reads TL TR BR BL. */
      --radius-chip:   7px 5px 8px 6px;
      --radius-card:   13px 16px 12px 15px;
      --radius-bubble: 18px 14px 17px 15px;
      --scanline-opacity: 0;
      /* Slightly thicker 1.5px hairlines — feel pen-drawn */
      --elev-1: 0 1.5px 0 var(--border);
      --elev-2: 0 1.5px 0 var(--border);
      --elev-3: 0 2px 0 var(--border);
      --glass-bg:    rgba(252, 248, 239, 0.88);
      --glass-inset: rgba(255, 255, 255, 0.92);
      --glass-shadow:0 1.5px 0 var(--border);
      --glass-border:rgba(42, 42, 42, 0.85);
      --body-gradient: var(--bg);

      /* Inkwell opinions: 1.5px hand-drawn borders, natural motion. */
      --space-xs:    0.25rem;
      --space-sm:    0.5rem;
      --space-md:    0.85rem;
      --space-lg:    1.25rem;
      --space-xl:    2rem;
      --border-width: 1.5px;
      --transition-fast: 100ms;
      --transition-base: 180ms;
      --transition-slow: 320ms;
      --ease-base: cubic-bezier(0.4, 0, 0.2, 1);
      --backdrop-blur: 8px;
      --backdrop-saturate: 110%;
      --selection-bg: color-mix(in srgb, var(--accent) 35%, transparent);
      --selection-fg: var(--text);
      --scrollbar-thumb: rgba(42, 42, 42, 0.32);
      --scrollbar-thumb-hover: rgba(42, 42, 42, 0.6);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1.5px;
      --link-underline-offset: 3px;
    }
    [data-theme="inkwell"] .wordmark .y { color: var(--accent); font-style: italic; }
    [data-theme="inkwell"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(67, 56, 202, 0.25); }
      50%      { text-shadow: 0 0 0.55em rgba(67, 56, 202, 0.45); }
    }
    [data-theme="inkwell"] .cursor { background: var(--accent); }

    /* ── ATRIUM — gallery architectural light ── */
    [data-theme="atrium"] {
      --bg:        #fafafa;       /* pure off-white */
      --surface: #ffffff;
      --surface-2:   #f0f0f0;
      --border:        #d4d4d4;
      --border-strong: #a8a8a8;
      --text:         #0a0a0f;
      --text-dim:     #3a3a45;
      --text-faint:   #7a7a85;
      --accent:         #1e3a8a;       /* deep ultramarine */
      --accent-deep:    #1e2870;
      --accent-soft:    rgba(30, 58, 138, 0.10);
      --danger:        #b91c1c;
      --warning:       #92400e;
      --success:        #166534;
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      /* SIGNATURE — Fibonacci radii: 8, 13, 21. Golden-ratio
         progression. The mathematical hierarchy reads as
         architectural intent vs arbitrary pixel choices. */
      --radius-chip:   8px;
      --radius-card:   13px;
      --radius-bubble: 21px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 2px rgba(10, 10, 15, 0.04);
      --elev-2: 0 4px 16px -4px rgba(10, 10, 15, 0.06);
      --elev-3: 0 12px 32px -12px rgba(10, 10, 15, 0.10);
      --glass-bg:    rgba(255, 255, 255, 0.82);
      --glass-inset: rgba(255, 255, 255, 0.90);
      --glass-shadow:0 1px 2px rgba(10, 10, 15, 0.04), 0 16px 48px -16px rgba(10, 10, 15, 0.12);
      --glass-border:rgba(212, 212, 212, 0.60);
      --body-gradient: var(--bg);    /* still gallery walls */

      /* Atrium opinions: SPACIOUS gallery rhythm, soft slow motion,
         minimal blur. Everything breathes. Largest spacing of any theme. */
      --space-xs:    0.35rem;
      --space-sm:    0.7rem;
      --space-md:    1.15rem;
      --space-lg:    1.75rem;
      --space-xl:    2.5rem;
      --border-width: 1px;
      --transition-fast: 120ms;
      --transition-base: 240ms;
      --transition-slow: 400ms;
      --ease-base: cubic-bezier(0.34, 0, 0.16, 1);
      --backdrop-blur: 14px;
      --backdrop-saturate: 120%;
      --selection-bg: color-mix(in srgb, var(--accent) 70%, transparent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--text) 12%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--text) 24%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    [data-theme="atrium"] .wordmark .y { color: var(--accent); }
    [data-theme="atrium"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(30, 58, 138, 0.18); }
      50%      { text-shadow: 0 0 0.55em rgba(30, 58, 138, 0.32); }
    }
    [data-theme="atrium"] .cursor { background: var(--accent); }

    /* ── SLATE — industrial brutalist dark ── */
    [data-theme="slate"] {
      --bg:        #1f2024;       /* concrete grey */
      --surface: #292a30;
      --surface-2:   #34353c;
      --border:        #44454e;
      --border-strong: #58596a;
      --text:         #ececef;
      --text-dim:     #a4a4ad;
      --text-faint:   #6a6a73;
      --accent:         #d4ff00;       /* acid yellow — Bauhaus poster */
      --accent-deep:    #a8cc00;
      --accent-soft:    rgba(212, 255, 0, 0.18);
      --danger:        #fb7185;
      --warning:       #fbbf24;
      --success:        #34d399;
      /* JetBrains Mono — third mono theme, BUT industrial/engineering
         intent (not Terminal's cyberpunk, not Pitch's minimalism) */
      --font-chrome: var(--mono);
      --font-meta:   var(--mono);
      --font-input:  var(--mono);
      --radius-chip:   4px;
      --radius-card:   4px;
      --radius-bubble: 4px;
      --scanline-opacity: 0;
      --elev-1: 0 0 0 1px var(--border);
      --elev-2: 0 0 0 1px var(--border);
      --elev-3: 0 0 0 1px var(--border-strong);
      --glass-bg:    rgba(41, 42, 48, 0.80);
      --glass-inset: rgba(255, 255, 255, 0.04);
      --glass-shadow:0 0 0 1px var(--border);
      --glass-border:rgba(212, 255, 0, 0.18);
      --body-gradient: var(--bg);

      /* Slate opinions: dense, snappy, acid selection. Industrial. */
      --space-xs:    0.18rem;
      --space-sm:    0.4rem;
      --space-md:    0.7rem;
      --space-lg:    1rem;
      --space-xl:    1.6rem;
      --border-width: 1px;
      --transition-fast: 60ms;
      --transition-base: 100ms;
      --transition-slow: 180ms;
      --ease-base: ease;
      --backdrop-blur: 4px;
      --backdrop-saturate: 110%;
      --selection-bg: var(--accent);
      --selection-fg: #000000;
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 45%, transparent);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    [data-theme="slate"] .wordmark .y { color: var(--accent); }
    [data-theme="slate"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(212, 255, 0, 0.32); }
      50%      { text-shadow: 0 0 0.55em rgba(212, 255, 0, 0.50); }
    }
    [data-theme="slate"] .cursor { background: var(--accent); }
    /* SLATE signature — engineering-blueprint dot grid. 16px spacing,
       white dots at 6% opacity. Reads as Swiss/Bauhaus utility paper. */
    [data-theme="slate"] body::after {
      content: "";
      position: fixed; inset: 0;
      pointer-events: none;
      z-index: 0;
      background-image: radial-gradient(circle, rgba(255, 255, 255, 0.06) 0.7px, transparent 0.7px);
      background-size: 16px 16px;
    }

    /* ── COSMIC — deep space dark ── */
    [data-theme="cosmic"] {
      --bg:        #0d0418;       /* purple-black void */
      --surface: #1a0a2e;
      --surface-2:   #261245;
      --border:        #361a5a;
      --border-strong: #482370;
      --text:         #f5edff;
      --text-dim:     #b89adc;
      --text-faint:   #7a6090;
      --accent:         #e879f9;       /* electric magenta */
      --accent-deep:    #c026d3;
      --accent-soft:    rgba(232, 121, 249, 0.18);
      --danger:        #fb7185;
      --warning:       #fbbf24;
      --success:        #34d399;
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   12px;
      --radius-card:   18px;
      --radius-bubble: 20px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 2px rgba(0, 0, 0, 0.40);
      --elev-2: 0 12px 32px -8px rgba(0, 0, 0, 0.50);
      --elev-3: 0 24px 64px -16px rgba(0, 0, 0, 0.60);
      --glass-bg:    rgba(26, 10, 46, 0.55);
      --glass-inset: rgba(255, 255, 255, 0.06);
      --glass-shadow:0 8px 32px -8px rgba(0, 0, 0, 0.60);
      --glass-border:rgba(232, 121, 249, 0.25);
      /* Nebula mesh — magenta + violet + teal swirls. Brighter & more
         saturated than Glass's lavender; this one wants to feel
         vibrant-deep-space, not refined-frost. */
      --body-gradient:
        radial-gradient(70vw 60vh at 15%   5%, rgba(232, 121, 249, 0.28), transparent 60%),
        radial-gradient(75vw 55vh at 85%  10%, rgba( 96, 165, 250, 0.22), transparent 65%),
        radial-gradient(80vw 65vh at 50%  80%, rgba( 34, 211, 238, 0.20), transparent 60%),
        radial-gradient(60vw 50vh at 30% 110%, rgba(232, 121, 249, 0.18), transparent 70%),
        var(--bg);

      /* Cosmic opinions: airy + heavy blur like Glass, even slower motion. */
      --space-xs:    0.3rem;
      --space-sm:    0.6rem;
      --space-md:    1rem;
      --space-lg:    1.5rem;
      --space-xl:    2.25rem;
      --border-width: 1px;
      --transition-fast: 160ms;
      --transition-base: 320ms;
      --transition-slow: 520ms;
      --ease-base: cubic-bezier(0.4, 0, 0.2, 1);
      --backdrop-blur: 36px;
      --backdrop-saturate: 180%;
      --selection-bg: color-mix(in srgb, var(--accent) 65%, transparent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 28%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--accent) 55%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 4px color-mix(in srgb, var(--accent) 30%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    [data-theme="cosmic"] .wordmark .y { color: var(--accent); }
    [data-theme="cosmic"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(232, 121, 249, 0.36); }
      50%      { text-shadow: 0 0 0.55em rgba(232, 121, 249, 0.60); }
    }
    [data-theme="cosmic"] .cursor { background: var(--accent); }
    /* COSMIC signature — slow nebula drift (120s, slower than Glass's
       90s — cosmos moves at its own pace). Respects reduced-motion. */
    @keyframes cosmic-nebula-drift {
      0%   { background-position:   0% 0%; }
      100% { background-position: -10% 8%; }
    }
    [data-theme="cosmic"] body {
      animation: cosmic-nebula-drift 120s ease-in-out infinite alternate;
    }
    @media (prefers-reduced-motion: reduce) {
      [data-theme="cosmic"] body { animation: none; }
    }

    /* ── CANVAS — distraction-free writing layout ──
       Architectural shift: sidebar HIDDEN by default. Wide centered
       reading column, no chrome competing for attention. Composer
       floats with margin from the edges. The show-sidebar button stays
       visible so users can still get to conversation history when
       they want it, but the default mode is "just you and the page."

       Visually warmer than Light — cream paper, deep ink. Manrope. */
    [data-theme="canvas"] {
      --bg:        #fafaf6;        /* paper-warm off-white */
      --surface: #ffffff;
      --surface-2:   #f1efe7;
      --border:        #d8d3c4;
      --border-strong: #b8b09b;
      --text:         #1a1814;        /* warm dark, not pure black */
      --text-dim:     #4a443d;
      --text-faint:   #8a8275;
      --accent:         #0891b2;        /* teal — calmer than sky cyan */
      --accent-deep:    #0e7490;
      --accent-soft:    rgba(8, 145, 178, 0.12);
      --danger:        #c0392b;
      --warning:       #b8762a;
      --success:        #4a6c3a;
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   10px;
      --radius-card:   14px;
      --radius-bubble: 16px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 2px rgba(26, 24, 20, 0.04);
      --elev-2: 0 8px 28px -8px rgba(26, 24, 20, 0.10);
      --elev-3: 0 24px 64px -16px rgba(26, 24, 20, 0.15);
      --glass-bg:    rgba(255, 255, 255, 0.88);
      --glass-inset: rgba(255, 255, 255, 0.94);
      --glass-shadow:0 8px 32px -8px rgba(26, 24, 20, 0.12);
      --glass-border:rgba(216, 211, 196, 0.7);
      --body-gradient: var(--bg);    /* still page, no aurora */

      --space-xs:    0.3rem;
      --space-sm:    0.6rem;
      --space-md:    1rem;
      --space-lg:    1.5rem;
      --space-xl:    2.25rem;
      --border-width: 1px;
      --transition-fast: 120ms;
      --transition-base: 220ms;
      --transition-slow: 400ms;
      --ease-base: cubic-bezier(0.4, 0, 0.2, 1);
      --backdrop-blur: 8px;
      --backdrop-saturate: 110%;
      --selection-bg: color-mix(in srgb, var(--accent) 30%, transparent);
      --selection-fg: var(--text);
      --scrollbar-thumb: color-mix(in srgb, var(--text) 12%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--text) 24%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 50%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    [data-theme="canvas"] .wordmark .y { color: var(--accent); }
    [data-theme="canvas"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(8, 145, 178, 0.22); }
      50%      { text-shadow: 0 0 0.55em rgba(8, 145, 178, 0.38); }
    }
    [data-theme="canvas"] .cursor { background: var(--accent); }

    /* CANVAS structural shift — hide sidebar, force show-button visible,
       widen and center the conv area, float the composer. */
    [data-theme="canvas"] .sidebar {
      display: none;
    }
    [data-theme="canvas"] .sidebar-show {
      display: inline-flex;
    }
    [data-theme="canvas"] .conv {
      max-width: 720px;
      padding: 3rem 1.8rem 9rem;
      gap: 2rem;
    }
    /* Composer floats centered with margin — not edge-to-edge */
    [data-theme="canvas"] .composer-wrap {
      padding: 1.6rem 1.6rem 1.8rem;
    }
    [data-theme="canvas"] .composer {
      max-width: 720px;
      box-shadow: var(--elev-2);
    }
    /* Strip message bubbles to match the writing-app vibe */
    [data-theme="canvas"] .msg.user,
    [data-theme="canvas"] .msg.assistant {
      align-self: stretch;
      background: transparent;
      border: none;
      border-left: none;
      border-right: none;
      border-radius: 0;
      padding: 0;
      max-width: 100%;
    }
    [data-theme="canvas"] .msg.user::before,
    [data-theme="canvas"] .msg.assistant::before {
      font-family: var(--body);
      font-weight: 600;
      font-size: 0.7rem;
      letter-spacing: 0.14em;
      text-transform: uppercase;
      margin-bottom: 0.4rem;
      color: var(--text-faint);
      text-align: left;
    }
    [data-theme="canvas"] .msg.assistant::before { color: var(--accent); content: "Alyx"; }
    [data-theme="canvas"] .msg.user::before { content: "You"; }
    [data-theme="canvas"] .msg + .msg {
      padding-top: 1.8rem;
      border-top: 1px solid color-mix(in srgb, var(--text) 8%, transparent);
    }
    [data-theme="canvas"] .msg-body {
      font-size: 1rem;
      line-height: 1.7;
    }

    /* ── WORKSHOP — sidebar on the RIGHT ──
       Single architectural flip via flex-direction. Sidebar moves to
       the right edge; the brand/wordmark, conv list, account menu all
       sit on the right. Composer stays centered. Border-side swaps
       from right to left. Subtle warm-charcoal palette so it doesn't
       just feel like "Dark mirrored." */
    [data-theme="workshop"] {
      --bg:        #1a1a1d;
      --surface: #232328;
      --surface-2:   #2c2c33;
      --border:        #36363f;
      --border-strong: #44444f;
      --text:         #ebebee;
      --text-dim:     #a0a0a8;
      --text-faint:   #6f6f78;
      --accent:         #f97316;        /* burnt orange — workshop tool color */
      --accent-deep:    #c2410c;
      --accent-soft:    rgba(249, 115, 22, 0.16);
      --danger:        #fb7185;
      --warning:       #fbbf24;
      --success:        #34d399;
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   6px;
      --radius-card:   10px;
      --radius-bubble: 12px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 2px rgba(0, 0, 0, 0.40);
      --elev-2: 0 8px 24px -8px rgba(0, 0, 0, 0.50);
      --elev-3: 0 16px 48px -16px rgba(0, 0, 0, 0.60);
      --glass-bg:    rgba(35, 35, 40, 0.65);
      --glass-inset: rgba(255, 255, 255, 0.04);
      --glass-shadow:0 1px 2px rgba(0, 0, 0, 0.45);
      --glass-border:rgba(249, 115, 22, 0.18);
      --body-gradient:
        radial-gradient(80vw 55vh at 82% -2%, rgba(249, 115, 22, 0.10), transparent 65%),
        radial-gradient(85vw 60vh at 20% -6%, rgba(251, 191, 36, 0.06), transparent 70%),
        var(--bg);

      --space-xs:    0.25rem;
      --space-sm:    0.5rem;
      --space-md:    0.85rem;
      --space-lg:    1.25rem;
      --space-xl:    2rem;
      --border-width: 1px;
      --transition-fast: 80ms;
      --transition-base: 140ms;
      --transition-slow: 240ms;
      --ease-base: ease-out;
      --backdrop-blur: 16px;
      --backdrop-saturate: 130%;
      --selection-bg: var(--accent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 30%, transparent);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 2px;
    }
    [data-theme="workshop"] .wordmark .y { color: var(--accent); }
    [data-theme="workshop"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(249, 115, 22, 0.30); }
      50%      { text-shadow: 0 0 0.55em rgba(249, 115, 22, 0.50); }
    }
    [data-theme="workshop"] .cursor { background: var(--accent); }

    /* WORKSHOP structural shift — body's flex order is reversed so the
       sidebar moves to the right side. Border flips from right→left. */
    [data-theme="workshop"] body {
      flex-direction: row-reverse;
    }
    [data-theme="workshop"] .sidebar {
      border-right: none;
      border-left: var(--border-width) solid var(--border);
    }
    /* Sidebar-toggle (collapse) currently anchored top-right of brand;
       in workshop it should still be reachable — top-left of brand
       makes more sense since the sidebar is now on the right. */
    [data-theme="workshop"] .sidebar-toggle {
      right: auto;
      left: 0.55rem;
    }
    /* The show-sidebar button (visible when sidebar is collapsed) lives
       at the left edge by default; in workshop it should move to right. */
    [data-theme="workshop"] .sidebar-show {
      left: auto;
      right: 0.55rem;
    }

    /* ════════════════════════════════════════════════════════════════
       ALTERNATE-ARCHITECTURE THEMES — entirely different component
       vocabulary. Not just colors/positions; actually reshaped chrome.
       Each one is a small product unto itself, sharing the same backend.
       ════════════════════════════════════════════════════════════════ */

    /* ── LANTERN — single glowing orb, no sidebar, halo messages ── */
    [data-theme="lantern"] {
      --bg:        #120a0f;        /* deep wine-black, like a dim room */
      --surface: #1a1015;
      --surface-2:   #251a20;
      --border:        #3a2530;
      --border-strong: #4d3340;
      --text:         #f8ede0;        /* warm cream — candlelit text */
      --text-dim:     #c9b8a8;
      --text-faint:   #8a7d70;
      --accent:         #ffb968;        /* warm lantern amber */
      --accent-deep:    #d98a3a;
      --accent-soft:    rgba(255, 185, 104, 0.18);
      --danger:        #fb7185;
      --warning:       #ffd793;
      --success:        #a7e3b0;
      --font-chrome: var(--body);
      --font-meta:   var(--body);
      --font-input:  var(--body);
      --radius-chip:   999px;        /* everything is round in Lantern */
      --radius-card:   999px;
      --radius-bubble: 28px;
      --scanline-opacity: 0;
      --elev-1: 0 0 30px color-mix(in srgb, var(--accent) 12%, transparent);
      --elev-2: 0 0 60px color-mix(in srgb, var(--accent) 20%, transparent);
      --elev-3: 0 0 100px color-mix(in srgb, var(--accent) 28%, transparent);
      --glass-bg:    rgba(26, 16, 21, 0.65);
      --glass-inset: rgba(255, 185, 104, 0.05);
      --glass-shadow:0 0 40px color-mix(in srgb, var(--accent) 18%, transparent);
      --glass-border:rgba(255, 185, 104, 0.18);
      /* Warm light pools at center-bottom (where the orb sits) */
      --body-gradient:
        radial-gradient(60vw 60vh at 50% 100%, rgba(255, 185, 104, 0.22), transparent 60%),
        radial-gradient(80vw 70vh at 50% 110%, rgba(217, 138, 58, 0.18), transparent 65%),
        var(--bg);

      --space-xs:    0.3rem;
      --space-sm:    0.6rem;
      --space-md:    1rem;
      --space-lg:    1.5rem;
      --space-xl:    2.25rem;
      --border-width: 1px;
      --transition-fast: 200ms;
      --transition-base: 380ms;
      --transition-slow: 600ms;
      --ease-base: cubic-bezier(0.4, 0, 0.2, 1);
      --backdrop-blur: 24px;
      --backdrop-saturate: 140%;
      --selection-bg: color-mix(in srgb, var(--accent) 40%, transparent);
      --selection-fg: var(--text);
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 20%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--accent) 40%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 4px color-mix(in srgb, var(--accent) 30%, transparent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 3px;
    }
    /* Wordmark = ONLY a glowing orb, no letters. We hide the "Alyx" text
       and turn the wordmark into a pulsing circle. */
    [data-theme="lantern"] .wordmark {
      font-size: 0; line-height: 0;          /* hide text */
      width: 1.4rem; height: 1.4rem;
      border-radius: 50%;
      background: var(--accent);
      box-shadow:
        0 0 16px var(--accent),
        0 0 32px color-mix(in srgb, var(--accent) 50%, transparent);
      animation: lantern-orb-breathe 4s ease-in-out infinite;
    }
    @keyframes lantern-orb-breathe {
      0%, 100% { transform: scale(0.92); opacity: 0.85; }
      50%      { transform: scale(1.05); opacity: 1; }
    }
    [data-theme="lantern"] .cursor { background: var(--accent); }

    /* SIDEBAR — hidden by default. The show-sidebar floating button is
       the only way back. When it IS shown, it floats with rounded
       corners and warm glow. */
    [data-theme="lantern"] .sidebar { display: none; }
    [data-theme="lantern"] .sidebar-show {
      display: inline-flex;
      box-shadow: 0 0 24px color-mix(in srgb, var(--accent) 30%, transparent);
    }

    /* Conv area — bottom-anchored (composer is in middle-bottom orb),
       messages flow UPWARD from there */
    [data-theme="lantern"] .conv {
      max-width: 640px;
      padding: 3rem 1.6rem 16rem;       /* extra bottom for the orb */
      gap: 1.5rem;
    }

    /* Messages — soft circular halos, no harsh edges. User warmer, assistant cooler. */
    [data-theme="lantern"] .msg.user,
    [data-theme="lantern"] .msg.assistant {
      align-self: stretch;
      background: radial-gradient(
        ellipse 80% 100% at 50% 50%,
        color-mix(in srgb, var(--surface) 70%, transparent),
        transparent 80%
      );
      border: none;
      border-radius: 28px;
      padding: 1rem 1.5rem;
      max-width: 78%;
      box-shadow: 0 0 40px color-mix(in srgb, var(--accent) 6%, transparent);
    }
    [data-theme="lantern"] .msg.assistant {
      align-self: flex-start;
      background: radial-gradient(
        ellipse 80% 100% at 50% 50%,
        color-mix(in srgb, #67e8f9 8%, var(--surface)),
        transparent 80%
      );
    }
    [data-theme="lantern"] .msg.user::before,
    [data-theme="lantern"] .msg.assistant::before {
      font-family: var(--body);
      font-weight: 600;
      font-size: 0.65rem;
      letter-spacing: 0.18em;
      text-transform: uppercase;
      color: var(--text-faint);
      margin-bottom: 0.3rem;
      text-align: center;
    }
    [data-theme="lantern"] .msg.user::before { content: "·  you  ·"; }
    [data-theme="lantern"] .msg.assistant::before {
      content: "·  alyx  ·";
      color: var(--accent);
    }

    /* COMPOSER — round orb at center-bottom, fixed position. Text input
       lives inside; the rectangular textarea is masked into the circle
       via overflow + flex centering. */
    [data-theme="lantern"] .composer-wrap {
      position: fixed;
      bottom: 0; left: 0; right: 0; top: auto;
      padding: 0;
      pointer-events: none;
      background: none;
    }
    [data-theme="lantern"] .composer-wrap > * { pointer-events: auto; }
    [data-theme="lantern"] .composer {
      position: fixed;
      bottom: 3rem;
      left: 50%;
      transform: translateX(-50%);
      width: 240px; height: 240px;
      max-width: none;
      margin: 0;
      border-radius: 50%;
      padding: 2.4rem;
      background:
        radial-gradient(circle at 50% 40%, color-mix(in srgb, var(--accent) 12%, var(--surface)), var(--surface-2) 80%);
      backdrop-filter: blur(20px) saturate(140%);
      -webkit-backdrop-filter: blur(20px) saturate(140%);
      border: 1px solid var(--border);
      box-shadow:
        0 0 40px color-mix(in srgb, var(--accent) 30%, transparent),
        0 0 80px color-mix(in srgb, var(--accent) 18%, transparent),
        inset 0 0 30px color-mix(in srgb, var(--accent) 8%, transparent);
      display: flex; align-items: center; justify-content: center;
      animation: lantern-composer-breathe 4s ease-in-out infinite;
      transition: box-shadow 280ms ease;
    }
    @keyframes lantern-composer-breathe {
      0%, 100% { box-shadow:
        0 0 30px color-mix(in srgb, var(--accent) 22%, transparent),
        0 0 60px color-mix(in srgb, var(--accent) 12%, transparent),
        inset 0 0 30px color-mix(in srgb, var(--accent) 6%, transparent);
      }
      50%      { box-shadow:
        0 0 50px color-mix(in srgb, var(--accent) 38%, transparent),
        0 0 100px color-mix(in srgb, var(--accent) 22%, transparent),
        inset 0 0 36px color-mix(in srgb, var(--accent) 10%, transparent);
      }
    }
    /* Input row inside the orb — stack vertically */
    [data-theme="lantern"] .input-row {
      width: 100%;
      flex-direction: column;
      gap: 0.5rem;
    }
    /* The textarea fills the orb's interior */
    [data-theme="lantern"] .composer textarea {
      flex: 1;
      width: 100%;
      min-height: 80px;
      background: transparent;
      border: none;
      resize: none;
      text-align: center;
      font-size: 1rem;
      line-height: 1.4;
      color: var(--text);
    }
    /* Send/attach/mic appear as small satellite circles */
    [data-theme="lantern"] .composer .send,
    [data-theme="lantern"] .composer .attach,
    [data-theme="lantern"] .composer .mute-btn {
      width: 36px; height: 36px;
      border-radius: 50%;
      background: color-mix(in srgb, var(--accent) 24%, transparent);
      border: 1px solid var(--border);
    }
    [data-theme="lantern"] .composer.voice-on {
      animation: lantern-composer-breathe 1.6s ease-in-out infinite;
    }

    /* ── SPOOL — receipt-paper conversation, perforated edges, mono ── */
    [data-theme="spool"] {
      --bg:        #f8f4e6;        /* cream receipt paper */
      --surface: #ffffff;
      --surface-2:   #ebe5d2;
      --border:        #d0c8b0;
      --border-strong: #a89a78;
      --text:         #1a1612;        /* near-black ink */
      --text-dim:     #4a4338;
      --text-faint:   #8a7d6a;
      --accent:         #b22020;        /* cash-register red */
      --accent-deep:    #7a1010;
      --accent-soft:    rgba(178, 32, 32, 0.10);
      --danger:        #b22020;
      --warning:       #a07a30;
      --success:        #4a6c3a;
      --font-chrome: var(--mono);
      --font-meta:   var(--mono);
      --font-input:  var(--mono);
      --radius-chip:   0;
      --radius-card:   0;
      --radius-bubble: 0;
      --scanline-opacity: 0;
      --elev-1: 0 1px 0 var(--border);
      --elev-2: 0 2px 0 var(--border);
      --elev-3: 0 3px 0 var(--border);
      --glass-bg:    rgba(248, 244, 230, 0.92);
      --glass-inset: rgba(255, 255, 255, 0.95);
      --glass-shadow:0 1px 0 var(--border-strong);
      --glass-border:rgba(208, 200, 176, 0.85);
      /* Paper texture — very faint diagonal fiber lines */
      --body-gradient:
        repeating-linear-gradient(
          90deg,
          transparent 0, transparent 60px,
          rgba(26, 22, 18, 0.012) 60px, rgba(26, 22, 18, 0.012) 61px
        ),
        var(--bg);

      --space-xs:    0.2rem;
      --space-sm:    0.4rem;
      --space-md:    0.7rem;
      --space-lg:    1rem;
      --space-xl:    1.6rem;
      --border-width: 1px;
      --transition-fast: 0ms;
      --transition-base: 0ms;
      --transition-slow: 50ms;
      --ease-base: steps(1);
      --backdrop-blur: 0px;
      --backdrop-saturate: 100%;
      --selection-bg: var(--text);
      --selection-fg: var(--bg);
      --scrollbar-thumb: var(--text-dim);
      --scrollbar-thumb-hover: var(--text);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 1px var(--accent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 2px;
    }
    [data-theme="spool"] .wordmark {
      font-family: var(--mono);
      font-weight: 700;
      letter-spacing: 0.15em;
      transform: rotate(-2deg);
      display: inline-block;
      text-shadow: 0 0 1px currentColor;     /* ink-bleed */
    }
    [data-theme="spool"] .wordmark .y {
      color: var(--accent);
      font-style: normal;
    }
    [data-theme="spool"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 1px currentColor; }
      50%      { text-shadow: 0 0 2px currentColor; }
    }
    [data-theme="spool"] .cursor { background: var(--text); }

    /* SIDEBAR — narrow paper roll on the left. Conv items as receipt stubs. */
    [data-theme="spool"] .sidebar {
      width: 13rem;
      background: var(--surface);
      border-right: 1px dashed var(--border-strong);
    }
    [data-theme="spool"] .conv-item-wrap {
      background: var(--surface-2);
      margin: 0.4rem 0.5rem;
      padding-bottom: 0;
      position: relative;
      clip-path: polygon(
        0 0, 100% 0, 100% calc(100% - 6px),
        96% 100%, 92% calc(100% - 6px), 88% 100%,
        84% calc(100% - 6px), 80% 100%, 76% calc(100% - 6px),
        72% 100%, 68% calc(100% - 6px), 64% 100%,
        60% calc(100% - 6px), 56% 100%, 52% calc(100% - 6px),
        48% 100%, 44% calc(100% - 6px), 40% 100%,
        36% calc(100% - 6px), 32% 100%, 28% calc(100% - 6px),
        24% 100%, 20% calc(100% - 6px), 16% 100%,
        12% calc(100% - 6px), 8% 100%, 4% calc(100% - 6px),
        0 100%
      );
      padding-bottom: 0.7rem;
    }

    /* MESSAGES — full-width receipt strips with perforated top + bottom */
    [data-theme="spool"] .msg.user,
    [data-theme="spool"] .msg.assistant {
      align-self: stretch;
      max-width: 100%;
      background: var(--surface);
      border: none;
      border-left: none;
      border-right: none;
      border-radius: 0;
      padding: 1rem 1.5rem 1rem 4rem;
      position: relative;
      /* Perforated top + bottom edges via clip-path */
      clip-path: polygon(
        0 6px, 4% 0, 8% 6px, 12% 0, 16% 6px, 20% 0, 24% 6px, 28% 0,
        32% 6px, 36% 0, 40% 6px, 44% 0, 48% 6px, 52% 0, 56% 6px, 60% 0,
        64% 6px, 68% 0, 72% 6px, 76% 0, 80% 6px, 84% 0, 88% 6px, 92% 0,
        96% 6px, 100% 0,
        100% calc(100% - 6px), 96% 100%, 92% calc(100% - 6px),
        88% 100%, 84% calc(100% - 6px), 80% 100%, 76% calc(100% - 6px),
        72% 100%, 68% calc(100% - 6px), 64% 100%, 60% calc(100% - 6px),
        56% 100%, 52% calc(100% - 6px), 48% 100%, 44% calc(100% - 6px),
        40% 100%, 36% calc(100% - 6px), 32% 100%, 28% calc(100% - 6px),
        24% 100%, 20% calc(100% - 6px), 16% 100%, 12% calc(100% - 6px),
        8% 100%, 4% calc(100% - 6px), 0 100%
      );
    }
    /* Rubber-stamp attribution in the left margin */
    [data-theme="spool"] .msg.user::before,
    [data-theme="spool"] .msg.assistant::before {
      position: absolute;
      left: 0.6rem; top: 1rem;
      width: 2.8rem;
      padding: 0.15rem 0.3rem;
      border: 1.5px solid var(--border-strong);
      color: var(--accent);
      font-family: var(--mono);
      font-weight: 700;
      font-size: 0.55rem;
      letter-spacing: 0.18em;
      text-align: center;
      transform: rotate(-3deg);
      margin: 0;
      text-shadow: 0 0 1px currentColor;
    }
    [data-theme="spool"] .msg.user::before { content: "YOU"; }
    [data-theme="spool"] .msg.assistant::before { content: "ALYX"; }
    [data-theme="spool"] .msg-body {
      font-family: var(--mono);
      font-size: 0.85rem;
      line-height: 1.6;
    }

    /* COMPOSER — printer feed at the bottom with perforated top edge */
    [data-theme="spool"] .composer-wrap {
      padding: 0;
      background: linear-gradient(to bottom,
        transparent 0%, var(--bg) 30%, var(--bg) 100%);
    }
    [data-theme="spool"] .composer {
      max-width: 100%;
      margin: 0;
      background: var(--surface);
      border: none;
      border-radius: 0;
      padding: 1rem 1.5rem;
      box-shadow: none;
      clip-path: polygon(
        0 8px, 3% 0, 6% 8px, 9% 0, 12% 8px, 15% 0, 18% 8px, 21% 0,
        24% 8px, 27% 0, 30% 8px, 33% 0, 36% 8px, 39% 0, 42% 8px, 45% 0,
        48% 8px, 51% 0, 54% 8px, 57% 0, 60% 8px, 63% 0, 66% 8px, 69% 0,
        72% 8px, 75% 0, 78% 8px, 81% 0, 84% 8px, 87% 0, 90% 8px, 93% 0,
        96% 8px, 100% 0,
        100% 100%, 0 100%
      );
    }
    [data-theme="spool"] .composer textarea {
      font-family: var(--mono);
    }

    /* ── POLAROID — corkboard with pinned polaroids ── */
    [data-theme="polaroid"] {
      --bg:        #b88a5a;        /* warm cork brown */
      --surface: #fdfaf3;        /* polaroid white */
      --surface-2:   #f5efde;        /* slight cream */
      --border:        #8a6240;
      --border-strong: #6e4a30;
      --text:         #2a1f15;
      --text-dim:     #5a4a3d;
      --text-faint:   #8a7d70;
      --accent:         #c0392b;        /* push-pin red */
      --accent-deep:    #8a1a10;
      --accent-soft:    rgba(192, 57, 43, 0.16);
      --danger:        #c0392b;
      --warning:       #d4942f;
      --success:        #4a6c3a;
      --font-chrome: var(--display);
      --font-meta:   var(--display);
      --font-input:  var(--body);
      --radius-chip:   0;            /* polaroids are squared */
      --radius-card:   0;
      --radius-bubble: 0;
      --scanline-opacity: 0;
      --elev-1: 0 3px 6px rgba(0, 0, 0, 0.20);
      --elev-2: 0 8px 18px rgba(0, 0, 0, 0.25);
      --elev-3: 0 16px 32px rgba(0, 0, 0, 0.35);
      --glass-bg:    rgba(253, 250, 243, 0.92);
      --glass-inset: rgba(255, 255, 255, 0.95);
      --glass-shadow:0 8px 24px rgba(0, 0, 0, 0.25);
      --glass-border:rgba(138, 98, 64, 0.5);
      /* Cork texture — multi-radial brown specks */
      --body-gradient:
        radial-gradient(circle at 12% 18%, rgba(110, 74, 48, 0.30) 0.6px, transparent 1px),
        radial-gradient(circle at 67% 53%, rgba(110, 74, 48, 0.20) 0.5px, transparent 1px),
        radial-gradient(circle at 23% 73%, rgba(110, 74, 48, 0.25) 0.7px, transparent 1px),
        radial-gradient(circle at 89% 31%, rgba(110, 74, 48, 0.30) 0.5px, transparent 1px),
        radial-gradient(circle at 47% 89%, rgba(110, 74, 48, 0.20) 0.6px, transparent 1px),
        radial-gradient(ellipse at 50% 0%, rgba(160, 110, 70, 0.5), transparent 70%),
        var(--bg);

      --space-xs:    0.3rem;
      --space-sm:    0.6rem;
      --space-md:    1rem;
      --space-lg:    1.5rem;
      --space-xl:    2.25rem;
      --border-width: 0;
      --transition-fast: 120ms;
      --transition-base: 220ms;
      --transition-slow: 380ms;
      --ease-base: cubic-bezier(0.34, 1.56, 0.64, 1);  /* slight overshoot — bouncy like pinning */
      --backdrop-blur: 0px;
      --backdrop-saturate: 100%;
      --selection-bg: var(--accent);
      --selection-fg: var(--surface);
      --scrollbar-thumb: rgba(110, 74, 48, 0.5);
      --scrollbar-thumb-hover: rgba(110, 74, 48, 0.8);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 2px;
    }
    [data-theme="polaroid"] .wordmark {
      font-family: var(--display);
      font-style: italic;
      font-weight: 500;
      color: var(--surface);
    }
    [data-theme="polaroid"] .wordmark .y { color: var(--accent); font-style: italic; }
    [data-theme="polaroid"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.2em rgba(192, 57, 43, 0.20); }
      50%      { text-shadow: 0 0 0.4em rgba(192, 57, 43, 0.40); }
    }
    [data-theme="polaroid"] .cursor { background: var(--accent); }

    /* SIDEBAR — stack of slightly-fanned polaroid cards. Conv items have
       white polaroid frame + handwritten caption + small rotation. */
    [data-theme="polaroid"] .sidebar {
      background: transparent;
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
      border: none;
      padding: 1rem 0.5rem;
    }
    [data-theme="polaroid"] .conv-list {
      gap: 0.4rem;
    }
    [data-theme="polaroid"] .conv-item-wrap {
      background: var(--surface);
      border-radius: 0;
      padding: 0.6rem 0.6rem 1.4rem;
      box-shadow: var(--elev-1);
      transform: rotate(-1.2deg);
      transition: transform 220ms cubic-bezier(0.34, 1.56, 0.64, 1);
    }
    [data-theme="polaroid"] .conv-item-wrap:nth-child(even) {
      transform: rotate(1.4deg);
    }
    [data-theme="polaroid"] .conv-item-wrap:hover {
      transform: rotate(0deg) scale(1.05);
      box-shadow: var(--elev-2);
    }
    /* Each conv-item-wrap gets a pin at its top-center */
    [data-theme="polaroid"] .conv-item-wrap::after {
      content: "";
      position: absolute;
      top: -4px; left: 50%;
      transform: translateX(-50%);
      width: 10px; height: 10px;
      background: var(--accent);
      border-radius: 50%;
      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4),
                  inset -1px -1px 2px rgba(0, 0, 0, 0.3);
      z-index: 2;
    }

    /* MESSAGES — individual polaroids floating on the corkboard */
    [data-theme="polaroid"] .msg.user,
    [data-theme="polaroid"] .msg.assistant {
      background: var(--surface);
      border: none;
      border-radius: 0;
      padding: 1rem 1.2rem 2rem;
      max-width: 70%;
      box-shadow: var(--elev-2);
      position: relative;
    }
    [data-theme="polaroid"] .msg.user { transform: rotate(-1.8deg); }
    [data-theme="polaroid"] .msg.assistant { transform: rotate(1.6deg); }
    /* Pin */
    [data-theme="polaroid"] .msg.user::after,
    [data-theme="polaroid"] .msg.assistant::after {
      content: "";
      position: absolute;
      top: -5px; left: 50%;
      transform: translateX(-50%);
      width: 12px; height: 12px;
      background: var(--accent);
      border-radius: 50%;
      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4),
                  inset -1px -1px 2px rgba(0, 0, 0, 0.3);
    }
    [data-theme="polaroid"] .msg.user::before,
    [data-theme="polaroid"] .msg.assistant::before {
      position: absolute;
      bottom: 0.5rem; left: 0; right: 0;
      font-family: var(--display);
      font-style: italic;
      font-size: 0.78rem;
      color: var(--text-faint);
      text-transform: none;
      letter-spacing: 0;
      text-align: center;
      margin: 0;
    }
    [data-theme="polaroid"] .msg.user::before { content: "you"; }
    [data-theme="polaroid"] .msg.assistant::before { content: "alyx"; color: var(--accent); }

    /* COMPOSER — square polaroid frame at bottom-center */
    [data-theme="polaroid"] .composer-wrap {
      padding: 1.4rem;
      background: transparent;
    }
    [data-theme="polaroid"] .composer {
      max-width: 380px;
      aspect-ratio: 1 / 1;
      background: var(--surface);
      border: none;
      border-radius: 0;
      padding: 1.2rem 1.2rem 2.5rem;
      box-shadow: var(--elev-2);
      transform: rotate(-1deg);
    }
    [data-theme="polaroid"] .composer.voice-on,
    [data-theme="polaroid"] .composer.voice-on.muted {
      box-shadow: var(--elev-3), 0 0 0 2px var(--accent);
    }

    /* ── COMPENDIUM — leather-bound codex, vertical spine sidebar ── */
    [data-theme="compendium"] {
      --bg:        #f5ecd9;        /* parchment cream */
      --surface: #faf3e0;
      --surface-2:   #ede0c4;
      --border:        #c9b894;
      --border-strong: #a89870;
      --text:         #2a1a10;
      --text-dim:     #5a4030;
      --text-faint:   #8a6e5a;
      --accent:         #5a1a1a;        /* oxblood */
      --accent-deep:    #3a0a0a;
      --accent-soft:    rgba(90, 26, 26, 0.10);
      --danger:        #8a2818;
      --warning:       #b88848;        /* gold-foil */
      --success:        #4a6c3a;
      --font-chrome: var(--display);
      --font-meta:   var(--display);
      --font-input:  var(--display);
      --radius-chip:   3px;
      --radius-card:   4px;
      --radius-bubble: 4px;
      --scanline-opacity: 0;
      --elev-1: 0 1px 0 var(--border);
      --elev-2: 0 2px 0 var(--border);
      --elev-3: 0 3px 0 var(--border-strong);
      --glass-bg:    rgba(250, 243, 224, 0.92);
      --glass-inset: rgba(255, 253, 245, 0.95);
      --glass-shadow:0 1px 0 var(--border-strong);
      --glass-border:rgba(201, 184, 148, 0.8);
      --body-gradient: var(--bg);

      --space-xs:    0.3rem;
      --space-sm:    0.6rem;
      --space-md:    1rem;
      --space-lg:    1.5rem;
      --space-xl:    2.25rem;
      --border-width: 1px;
      --transition-fast: 120ms;
      --transition-base: 220ms;
      --transition-slow: 400ms;
      --ease-base: cubic-bezier(0.25, 0.1, 0.25, 1);
      --backdrop-blur: 6px;
      --backdrop-saturate: 105%;
      --selection-bg: color-mix(in srgb, var(--accent) 25%, transparent);
      --selection-fg: var(--text);
      --scrollbar-thumb: var(--border-strong);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid;
      --link-decoration-thickness: 1px;
      --link-underline-offset: 4px;
    }
    [data-theme="compendium"] {
      font-feature-settings: "onum" 1, "liga" 1, "calt" 1, "hist" 1;
    }
    [data-theme="compendium"] .cursor { background: var(--accent); }

    /* SIDEBAR — book spine on the left. Leather color, vertical text. */
    [data-theme="compendium"] .sidebar {
      width: 11rem;
      background:
        linear-gradient(to right,
          rgba(0, 0, 0, 0.25), transparent 8%,
          transparent 92%, rgba(0, 0, 0, 0.15) 100%),
        var(--accent);
      border-right: 1px solid var(--warning);
      box-shadow:
        inset 0 0 0 1px rgba(184, 136, 72, 0.3),
        inset 0 0 30px rgba(0, 0, 0, 0.3);
      padding: 1rem 0.4rem;
    }
    /* Wordmark in the spine — vertical text, small-caps */
    [data-theme="compendium"] .sidebar-brand {
      writing-mode: vertical-rl;
      transform: rotate(180deg);
      padding: 1.5rem 0;
      border-bottom: none;
      text-align: center;
    }
    [data-theme="compendium"] .wordmark {
      font-family: var(--display);
      font-weight: 600;
      font-variant: small-caps;
      letter-spacing: 0.4em;
      color: var(--warning);
      font-size: 1.4rem;
      text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
    }
    [data-theme="compendium"] .wordmark .y { color: var(--warning); font-style: normal; }
    [data-theme="compendium"] @keyframes breathe {
      0%, 100% { text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4); }
      50%      { text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5), 0 0 8px rgba(184, 136, 72, 0.4); }
    }
    /* Conv items — chapter marks vertically along the spine */
    [data-theme="compendium"] .conv-item-wrap {
      background: transparent;
      border-bottom: 1px solid rgba(184, 136, 72, 0.25);
      padding: 0.5rem 0.3rem;
    }
    [data-theme="compendium"] .conv-item-wrap.active {
      background: rgba(184, 136, 72, 0.18);
      border-left: 3px solid var(--warning);
    }
    [data-theme="compendium"] .conv-item {
      color: var(--accent-fg);
      font-family: var(--display);
      font-variant: small-caps;
      letter-spacing: 0.08em;
    }

    /* MESSAGES — flow as paragraphs on the page; no bubbles. Pilcrow
       marks user turns in the left margin. */
    [data-theme="compendium"] .conv {
      max-width: 680px;
      padding: 3rem 2.5rem 8rem;
      background:
        repeating-linear-gradient(
          to bottom,
          transparent 0, transparent 27px,
          rgba(90, 26, 26, 0.07) 27px, rgba(90, 26, 26, 0.07) 28px
        ),
        var(--bg);
      gap: 1.5rem;
    }
    [data-theme="compendium"] .msg.user,
    [data-theme="compendium"] .msg.assistant {
      align-self: stretch;
      background: transparent;
      border: none;
      border-left: none;
      border-right: none;
      border-radius: 0;
      padding: 0 0 0 2rem;
      max-width: 100%;
      position: relative;
    }
    [data-theme="compendium"] .msg.user::before {
      content: "¶";
      position: absolute;
      left: 0; top: 0.1em;
      font-family: var(--display);
      font-size: 1.4rem;
      color: var(--accent);
      margin: 0;
    }
    [data-theme="compendium"] .msg.assistant::before {
      content: "§";
      position: absolute;
      left: 0; top: 0.1em;
      font-family: var(--display);
      font-size: 1.4rem;
      color: var(--warning);
      margin: 0;
    }
    [data-theme="compendium"] .msg-body {
      font-family: var(--display);
      font-size: 1.05rem;
      line-height: 1.65;
    }
    /* Drop cap on assistant first paragraph — same trick as Editorial */
    [data-theme="compendium"] .msg.assistant .msg-body > p:first-child::first-letter {
      font-family: var(--display);
      font-weight: 600;
      font-size: 3.4em;
      line-height: 0.82;
      float: left;
      margin: 0.08em 0.15em 0 0;
      padding-top: 0.04em;
      color: var(--accent);
    }

    /* COMPOSER — ruled writing pad at the bottom of the page */
    [data-theme="compendium"] .composer-wrap {
      padding: 1.4rem 2rem;
      background: linear-gradient(to bottom,
        transparent 0%, var(--bg) 50%, var(--bg) 100%);
    }
    [data-theme="compendium"] .composer {
      max-width: 680px;
      background:
        linear-gradient(to right,
          transparent 0, transparent 28px,
          rgba(90, 26, 26, 0.25) 28px, rgba(90, 26, 26, 0.25) 29px,
          transparent 29px),
        repeating-linear-gradient(
          to bottom,
          transparent 0, transparent 23px,
          rgba(90, 26, 26, 0.10) 23px, rgba(90, 26, 26, 0.10) 24px
        ),
        var(--surface);
      border: 1px solid var(--border);
      border-radius: 3px;
      padding: 0.8rem 1.2rem 0.8rem 2.3rem;
      box-shadow: var(--elev-1);
    }
    [data-theme="compendium"] .composer textarea {
      font-family: var(--display);
      font-size: 1rem;
    }

    /* ════════════════════════════════════════════════════════════════
       ALTERNATE-ARCHITECTURE THEMES — BATCH 2 (10 themes)
       Each one breaks component vocabulary. Different shapes, different
       materials, different metaphors. Built October 2026.
       ════════════════════════════════════════════════════════════════ */

    /* ──── 1. CASSETTE — magnetic tape deck ──── */
    [data-theme="cassette"] {
      --bg: #1a1612; --surface: #2a2520; --surface-2: #3a342e;
      --border: #3a342e; --border-strong: #5a5046;
      --text: #d0c8b8; --text-dim: #8a8070; --text-faint: #5a5044;
      --accent: #00ff88; --accent-deep: #00cc6a;
      --accent-soft: rgba(0, 255, 136, 0.18);
      --danger: #ff5577; --warning: #ffaa33; --success: #00ff88;
      --font-chrome: var(--mono); --font-meta: var(--mono); --font-input: var(--mono);
      --radius-chip: 4px; --radius-card: 6px; --radius-bubble: 4px;
      --scanline-opacity: 0;
      --elev-1: inset 0 1px 0 rgba(255,255,255,0.08), 0 1px 2px rgba(0,0,0,0.6);
      --elev-2: inset 0 1px 0 rgba(255,255,255,0.08), 0 2px 4px rgba(0,0,0,0.6);
      --elev-3: inset 0 1px 0 rgba(255,255,255,0.08), 0 4px 8px rgba(0,0,0,0.7);
      --glass-bg: rgba(42, 37, 32, 0.80);
      --glass-inset: rgba(255, 255, 255, 0.04);
      --glass-shadow: 0 2px 4px rgba(0, 0, 0, 0.6);
      --glass-border: rgba(90, 80, 70, 0.6);
      --body-gradient: var(--bg);
      --space-xs: 0.25rem; --space-sm: 0.5rem; --space-md: 0.85rem;
      --space-lg: 1.25rem; --space-xl: 2rem;
      --border-width: 1px;
      --transition-fast: 50ms; --transition-base: 100ms; --transition-slow: 180ms;
      --ease-base: ease-out;
      --backdrop-blur: 0px; --backdrop-saturate: 100%;
      --selection-bg: var(--accent); --selection-fg: #000;
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 40%, transparent);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid; --link-decoration-thickness: 1px; --link-underline-offset: 2px;
    }
    [data-theme="cassette"] .wordmark {
      font-family: var(--display); font-style: italic; font-weight: 500;
      background: #f0e8d8; color: #1a1612;
      padding: 0.05em 0.5em; border-radius: 2px;
      transform: rotate(-2deg);
      box-shadow: 0 1px 2px rgba(0,0,0,0.4);
    }
    [data-theme="cassette"] .wordmark .y { color: #b22020; font-style: italic; }
    [data-theme="cassette"] @keyframes breathe { 0%,100% { opacity:.95 } 50% { opacity:1 } }
    [data-theme="cassette"] .cursor { background: var(--accent); }
    [data-theme="cassette"] .sidebar {
      background: linear-gradient(180deg, #2a2520, #1a1612);
      border-right: 2px solid #3a342e;
    }
    [data-theme="cassette"] .conv-item-wrap {
      background: #f0e8d8; border: 1px solid #c8b8a0;
      margin: 0.4rem 0.5rem; padding: 0.5rem 0.7rem;
      border-radius: 3px; transform: rotate(-0.5deg);
    }
    [data-theme="cassette"] .conv-item-wrap:nth-child(even) { transform: rotate(0.5deg); }
    [data-theme="cassette"] .conv-item {
      color: #1a1612 !important;
      font-family: var(--display); font-style: italic;
    }
    [data-theme="cassette"] .msg.user, [data-theme="cassette"] .msg.assistant {
      background: #0a0805; border: 1px solid #2a2520; border-radius: 4px;
      padding: 1rem 1.2rem; max-width: 88%;
      box-shadow: inset 0 0 20px rgba(0,255,136,0.04);
    }
    [data-theme="cassette"] .msg-body {
      color: var(--accent); font-family: var(--mono); font-size: 0.85rem;
    }
    [data-theme="cassette"] .msg.user::before {
      content: "[USER] >>"; color: var(--warning);
      font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.15em;
      margin-bottom: 0.4rem; display: block; text-align: left;
    }
    [data-theme="cassette"] .msg.assistant::before {
      content: "[ALYX] >>"; color: var(--accent);
      font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.15em;
      margin-bottom: 0.4rem; display: block;
    }
    [data-theme="cassette"] .composer-wrap {
      padding: 1.5rem;
      background: linear-gradient(to bottom, transparent, var(--bg) 50%, var(--bg));
    }
    [data-theme="cassette"] .composer {
      max-width: 580px;
      background: linear-gradient(180deg, #3a342e 0%, #2a2520 60%, #1a1612 100%);
      border: 2px solid #5a5046; border-radius: 8px;
      padding: 56px 24px 16px;
      box-shadow: inset 0 2px 4px rgba(0,0,0,0.4), inset 0 -1px 2px rgba(255,255,255,0.05);
      position: relative;
    }
    [data-theme="cassette"] .composer::before, [data-theme="cassette"] .composer::after {
      content: ""; position: absolute; top: 10px;
      width: 38px; height: 38px; border-radius: 50%;
      background:
        radial-gradient(circle, #1a1612 0%, #1a1612 26%, transparent 26%),
        repeating-conic-gradient(#4a4238 0deg 30deg, #2a2520 30deg 60deg);
      border: 2px solid #5a5046;
      box-shadow: inset 0 0 4px rgba(0,0,0,0.6);
      animation: cassette-reel 4s linear infinite;
      animation-play-state: paused;
    }
    [data-theme="cassette"] .composer::before { left: 24px; }
    [data-theme="cassette"] .composer::after { right: 24px; }
    [data-theme="cassette"] .composer:focus-within::before,
    [data-theme="cassette"] .composer:focus-within::after { animation-play-state: running; }
    @keyframes cassette-reel { to { transform: rotate(360deg); } }
    [data-theme="cassette"] .composer textarea {
      background: transparent; color: var(--accent);
      font-family: var(--mono);
    }

    /* ──── 2. SWITCHBOARD — telephone operator panel ──── */
    [data-theme="switchboard"] {
      --bg: #1a1410; --surface: #251c15; --surface-2: #2e231a;
      --border: #3a2d20; --border-strong: #5a4a35;
      --text: #f0e0c0; --text-dim: #c0a878; --text-faint: #8a7858;
      --accent: #c89832; --accent-deep: #8a6818;
      --accent-soft: rgba(200, 152, 50, 0.18);
      --danger: #c0392b; --warning: #d4942f; --success: #5a8a4a;
      --font-chrome: var(--display); --font-meta: var(--mono); --font-input: var(--body);
      --radius-chip: 50%; --radius-card: 8px; --radius-bubble: 4px;
      --scanline-opacity: 0;
      --elev-1: inset 0 1px 0 rgba(200,152,50,0.15), 0 2px 4px rgba(0,0,0,0.6);
      --elev-2: inset 0 1px 0 rgba(200,152,50,0.15), 0 4px 8px rgba(0,0,0,0.7);
      --elev-3: inset 0 1px 0 rgba(200,152,50,0.15), 0 8px 16px rgba(0,0,0,0.8);
      --glass-bg: rgba(37, 28, 21, 0.85);
      --glass-inset: rgba(200, 152, 50, 0.08);
      --glass-shadow: 0 4px 8px rgba(0, 0, 0, 0.7);
      --glass-border: rgba(90, 74, 53, 0.7);
      --body-gradient:
        radial-gradient(ellipse at 50% 0%, rgba(200,152,50,0.06), transparent 60%),
        var(--bg);
      --space-xs: 0.25rem; --space-sm: 0.5rem; --space-md: 0.85rem;
      --space-lg: 1.25rem; --space-xl: 2rem;
      --border-width: 2px;
      --transition-fast: 100ms; --transition-base: 200ms; --transition-slow: 360ms;
      --ease-base: cubic-bezier(0.4, 0, 0.2, 1);
      --backdrop-blur: 8px; --backdrop-saturate: 120%;
      --selection-bg: var(--accent); --selection-fg: #000;
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 35%, transparent);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid; --link-decoration-thickness: 1px; --link-underline-offset: 2px;
    }
    [data-theme="switchboard"] .wordmark {
      font-family: var(--display); font-weight: 700; font-variant: small-caps;
      color: var(--accent);
      letter-spacing: 0.15em;
      text-shadow: 0 1px 2px rgba(0,0,0,0.6), 0 -1px 0 rgba(255,210,120,0.4);
    }
    [data-theme="switchboard"] .wordmark .y { color: var(--accent); font-style: normal; }
    [data-theme="switchboard"] @keyframes breathe {
      0%,100% { text-shadow: 0 1px 2px rgba(0,0,0,0.6), 0 0 6px rgba(200,152,50,0.3); }
      50% { text-shadow: 0 1px 2px rgba(0,0,0,0.6), 0 0 14px rgba(200,152,50,0.6); }
    }
    [data-theme="switchboard"] .cursor { background: var(--accent); }
    [data-theme="switchboard"] .sidebar {
      background:
        radial-gradient(circle at 50% 50%, #2e231a 0%, #1a1410 100%);
    }
    /* Sidebar conv items as plug sockets */
    [data-theme="switchboard"] .conv-item-wrap {
      background: radial-gradient(circle at 30% 30%, #3a2d20, #1a1410 70%);
      border: 2px solid #5a4a35;
      border-radius: 50%;
      width: 60px; height: 60px;
      display: inline-block;
      margin: 0.4rem;
      box-shadow: inset 0 2px 4px rgba(0,0,0,0.7);
      position: relative;
    }
    [data-theme="switchboard"] .conv-item-wrap.active {
      background: radial-gradient(circle at 30% 30%, var(--accent), var(--accent-deep) 70%);
      box-shadow: 0 0 12px var(--accent), inset 0 2px 4px rgba(0,0,0,0.5);
    }
    [data-theme="switchboard"] .conv-item {
      position: absolute; bottom: -1.4rem; left: 50%; transform: translateX(-50%);
      font-size: 0.55rem; white-space: nowrap;
      font-family: var(--mono); letter-spacing: 0.12em;
    }
    /* Messages — operator call-sheet format */
    [data-theme="switchboard"] .msg.user, [data-theme="switchboard"] .msg.assistant {
      background: #f0e4cc; color: #1a1410;
      border: 1px solid #c0a878; border-radius: 2px;
      padding: 0.8rem 1.2rem; max-width: 85%;
      box-shadow: 0 2px 4px rgba(0,0,0,0.4);
    }
    [data-theme="switchboard"] .msg-body { color: #1a1410; }
    [data-theme="switchboard"] .msg.user::before,
    [data-theme="switchboard"] .msg.assistant::before {
      font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.15em;
      color: #5a4a35; border-bottom: 1px dashed #c0a878;
      padding-bottom: 0.3rem; margin-bottom: 0.5rem; display: block;
    }
    [data-theme="switchboard"] .msg.user::before { content: "OP-U → LINE 01 — TX"; }
    [data-theme="switchboard"] .msg.assistant::before { content: "LINE 01 → OP-U — RX"; }
    /* Composer = brass plug panel */
    [data-theme="switchboard"] .composer {
      background: radial-gradient(circle at 50% 50%, #2e231a, #1a1410);
      border: 2px solid #5a4a35; border-radius: 12px;
      padding: 1rem 1.4rem;
      box-shadow: inset 0 2px 4px rgba(0,0,0,0.5), 0 0 0 1px var(--accent-deep);
    }
    [data-theme="switchboard"] .composer textarea {
      background: rgba(240, 224, 192, 0.92); color: #1a1410;
      border: 1px solid #5a4a35; border-radius: 4px;
      padding: 0.6rem 0.8rem;
    }

    /* ──── 3. BLUEPRINT — architectural schematic ──── */
    [data-theme="blueprint"] {
      --bg: #0a1e3a; --surface: #122845; --surface-2: #1a3258;
      --border: #2a4a78; --border-strong: #3a5e90;
      --text: #d0e8ff; --text-dim: #88b0d8; --text-faint: #5a7a98;
      --accent: #67e8f9; --accent-deep: #22d3ee;
      --accent-soft: rgba(103, 232, 249, 0.18);
      --danger: #fb7185; --warning: #fbbf24; --success: #4ade80;
      --font-chrome: var(--mono); --font-meta: var(--mono); --font-input: var(--mono);
      --radius-chip: 0; --radius-card: 0; --radius-bubble: 0;
      --scanline-opacity: 0;
      --elev-1: 0 0 0 1px var(--accent-deep);
      --elev-2: 0 0 0 1px var(--accent-deep);
      --elev-3: 0 0 0 1.5px var(--accent);
      --glass-bg: rgba(18, 40, 69, 0.85);
      --glass-inset: rgba(103, 232, 249, 0.04);
      --glass-shadow: 0 0 0 1px var(--accent-deep);
      --glass-border: var(--border-strong);
      /* Real blueprint grid */
      --body-gradient:
        repeating-linear-gradient(
          to right, transparent 0, transparent 23px,
          rgba(103, 232, 249, 0.08) 23px, rgba(103, 232, 249, 0.08) 24px),
        repeating-linear-gradient(
          to bottom, transparent 0, transparent 23px,
          rgba(103, 232, 249, 0.08) 23px, rgba(103, 232, 249, 0.08) 24px),
        repeating-linear-gradient(
          to right, transparent 0, transparent 119px,
          rgba(103, 232, 249, 0.16) 119px, rgba(103, 232, 249, 0.16) 120px),
        repeating-linear-gradient(
          to bottom, transparent 0, transparent 119px,
          rgba(103, 232, 249, 0.16) 119px, rgba(103, 232, 249, 0.16) 120px),
        var(--bg);
      --space-xs: 0.25rem; --space-sm: 0.5rem; --space-md: 0.85rem;
      --space-lg: 1.25rem; --space-xl: 2rem;
      --border-width: 1px;
      --transition-fast: 60ms; --transition-base: 120ms; --transition-slow: 220ms;
      --ease-base: linear;
      --backdrop-blur: 0px; --backdrop-saturate: 100%;
      --selection-bg: var(--accent); --selection-fg: var(--bg);
      --scrollbar-thumb: var(--accent-deep);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 1px var(--accent);
      --link-decoration-style: solid; --link-decoration-thickness: 1px; --link-underline-offset: 3px;
    }
    [data-theme="blueprint"] .wordmark {
      font-family: var(--mono); font-weight: 500; color: var(--accent);
      letter-spacing: 0.18em; text-transform: uppercase;
    }
    [data-theme="blueprint"] .wordmark::before { content: "|←  "; color: var(--text-faint); }
    [data-theme="blueprint"] .wordmark::after { content: "  →|"; color: var(--text-faint); }
    [data-theme="blueprint"] .wordmark .y { color: var(--accent); font-style: normal; }
    [data-theme="blueprint"] @keyframes breathe {
      0%,100% { text-shadow: 0 0 4px rgba(103,232,249,0.4); }
      50% { text-shadow: 0 0 10px rgba(103,232,249,0.7); }
    }
    [data-theme="blueprint"] .cursor { background: var(--accent); }
    [data-theme="blueprint"] .sidebar {
      background: rgba(10, 30, 58, 0.5);
      border-right: 1px solid var(--border-strong);
    }
    [data-theme="blueprint"] .conv-item-wrap {
      border: 1px solid var(--border-strong); padding: 0.5rem 0.7rem;
      margin: 0.3rem; position: relative;
    }
    /* CAD corner brackets on conv items */
    [data-theme="blueprint"] .conv-item-wrap::before, [data-theme="blueprint"] .conv-item-wrap::after {
      content: ""; position: absolute; width: 6px; height: 6px;
      border: 1px solid var(--border-strong);
    }
    [data-theme="blueprint"] .conv-item-wrap::before {
      top: -2px; left: -2px; border-right: none; border-bottom: none;
    }
    [data-theme="blueprint"] .conv-item-wrap::after {
      bottom: -2px; right: -2px; border-left: none; border-top: none;
    }
    [data-theme="blueprint"] .msg.user, [data-theme="blueprint"] .msg.assistant {
      background: rgba(10, 30, 58, 0.4); border: 1px solid var(--border-strong);
      padding: 0.8rem 1.2rem; max-width: 85%; position: relative;
    }
    [data-theme="blueprint"] .msg.user::before, [data-theme="blueprint"] .msg.assistant::before {
      font-family: var(--mono); font-size: 0.55rem; letter-spacing: 0.18em;
      color: var(--accent); margin-bottom: 0.4rem; display: block;
    }
    [data-theme="blueprint"] .msg.user::before { content: "→ USER_QUERY"; }
    [data-theme="blueprint"] .msg.assistant::before { content: "→ ASST_RESP"; }
    [data-theme="blueprint"] .composer {
      background: rgba(10, 30, 58, 0.7); border: 1px solid var(--border-strong);
      position: relative;
    }
    [data-theme="blueprint"] .composer::before {
      content: "INPUT_FIELD [USR.01]"; position: absolute;
      top: -0.7rem; left: 0.6rem;
      background: var(--bg); padding: 0 0.4rem;
      font-family: var(--mono); font-size: 0.55rem; letter-spacing: 0.18em;
      color: var(--accent);
    }

    /* ──── 4. STAINED GLASS — cathedral panes ──── */
    [data-theme="stained"] {
      --bg: #0a0a1a; --surface: #15152a; --surface-2: #1f1f38;
      --border: #000000; --border-strong: #000000;
      --text: #f5e8d0; --text-dim: #b8a888; --text-faint: #7a7060;
      --accent: #d4a800; --accent-deep: #8a6400;
      --accent-soft: rgba(212, 168, 0, 0.20);
      --danger: #b71c2f; --warning: #d4a800; --success: #2e7a4a;
      --font-chrome: var(--display); --font-meta: var(--display); --font-input: var(--display);
      --radius-chip: 0; --radius-card: 0; --radius-bubble: 0;
      --scanline-opacity: 0;
      --elev-1: 0 0 0 3px #000;
      --elev-2: 0 0 0 3px #000;
      --elev-3: 0 0 0 4px #000;
      --glass-bg: rgba(21, 21, 42, 0.9);
      --glass-inset: rgba(212, 168, 0, 0.08);
      --glass-shadow: 0 0 0 3px #000;
      --glass-border: #000;
      /* Warm light bleeding through */
      --body-gradient:
        radial-gradient(ellipse 80vw 80vh at 50% 50%, rgba(212, 168, 0, 0.12), transparent 70%),
        radial-gradient(ellipse 60vw 60vh at 50% 20%, rgba(180, 50, 60, 0.08), transparent 60%),
        var(--bg);
      --space-xs: 0.25rem; --space-sm: 0.5rem; --space-md: 0.85rem;
      --space-lg: 1.25rem; --space-xl: 2rem;
      --border-width: 3px;
      --transition-fast: 100ms; --transition-base: 200ms; --transition-slow: 380ms;
      --ease-base: cubic-bezier(0.25, 0.1, 0.25, 1);
      --backdrop-blur: 0px; --backdrop-saturate: 100%;
      --selection-bg: var(--warning); --selection-fg: #000;
      --scrollbar-thumb: var(--warning); --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: #000;
      --focus-ring: 0 0 0 3px #000, 0 0 0 5px var(--warning);
      --link-decoration-style: solid; --link-decoration-thickness: 2px; --link-underline-offset: 3px;
    }
    [data-theme="stained"] .wordmark {
      font-family: var(--display); font-weight: 800;
      color: var(--warning); letter-spacing: 0.02em;
      text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
    }
    [data-theme="stained"] .wordmark .y { color: var(--danger); }
    [data-theme="stained"] @keyframes breathe {
      0%,100% { text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000, 0 0 8px rgba(212,168,0,0.5); }
      50% { text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000, 0 0 20px rgba(212,168,0,0.8); }
    }
    [data-theme="stained"] .cursor { background: var(--warning); }
    [data-theme="stained"] .sidebar { background: transparent; border-right: 3px solid #000; }
    /* Conv items as jewel panes — rotating colors */
    [data-theme="stained"] .conv-item-wrap {
      background: rgba(183, 28, 47, 0.35); border: 3px solid #000;
      margin: 0; padding: 0.7rem 1rem;
    }
    [data-theme="stained"] .conv-item-wrap:nth-child(3n+1) { background: rgba(183, 28, 47, 0.35); }
    [data-theme="stained"] .conv-item-wrap:nth-child(3n+2) { background: rgba(46, 122, 74, 0.35); }
    [data-theme="stained"] .conv-item-wrap:nth-child(3n+3) { background: rgba(40, 80, 160, 0.35); }
    [data-theme="stained"] .conv-item-wrap.active { background: rgba(212, 168, 0, 0.45); }
    [data-theme="stained"] .msg.user, [data-theme="stained"] .msg.assistant {
      border: 3px solid #000; padding: 1rem 1.2rem; max-width: 80%;
    }
    [data-theme="stained"] .msg.user { background: rgba(183, 28, 47, 0.3); }
    [data-theme="stained"] .msg.assistant {
      background: rgba(40, 80, 160, 0.3);
      /* Gothic arch top edge */
      clip-path: polygon(0 12%, 8% 0, 92% 0, 100% 12%, 100% 100%, 0 100%);
    }
    [data-theme="stained"] .msg.user::before, [data-theme="stained"] .msg.assistant::before {
      font-family: var(--display); font-variant: small-caps; font-size: 0.78rem;
      letter-spacing: 0.15em; color: var(--warning);
      text-shadow: 0 1px 1px #000;
      display: block; margin-bottom: 0.4rem;
    }
    [data-theme="stained"] .msg.user::before { content: "Petitioner"; }
    [data-theme="stained"] .msg.assistant::before { content: "Oracle"; }
    [data-theme="stained"] .composer {
      background: rgba(15, 15, 26, 0.6);
      border: 3px solid #000;
      padding: 0.8rem 1.2rem;
    }
    [data-theme="stained"] .composer textarea { color: var(--text); font-family: var(--display); }

    /* ──── 5. TELEGRAPH — wire service ticker tape ──── */
    [data-theme="telegraph"] {
      --bg: #ebe0c5; --surface: #f5ecd5; --surface-2: #d8c9a5;
      --border: #a89870; --border-strong: #7a6840;
      --text: #2a1a0a; --text-dim: #5a4525; --text-faint: #8a7855;
      --accent: #8a3a18; --accent-deep: #5a2010;
      --accent-soft: rgba(138, 58, 24, 0.14);
      --danger: #8a3a18; --warning: #b88848; --success: #5a6c3a;
      --font-chrome: var(--mono); --font-meta: var(--mono); --font-input: var(--mono);
      --radius-chip: 0; --radius-card: 0; --radius-bubble: 0;
      --scanline-opacity: 0;
      --elev-1: 0 1px 0 var(--border);
      --elev-2: 0 1px 0 var(--border);
      --elev-3: 0 2px 0 var(--border);
      --glass-bg: rgba(245, 236, 213, 0.92);
      --glass-inset: rgba(255,255,255,0.5);
      --glass-shadow: 0 1px 0 var(--border);
      --glass-border: var(--border-strong);
      /* Aged paper — multi-radial sepia stains */
      --body-gradient:
        radial-gradient(circle at 25% 30%, rgba(138, 58, 24, 0.05), transparent 50%),
        radial-gradient(circle at 75% 70%, rgba(89, 64, 27, 0.04), transparent 50%),
        var(--bg);
      --space-xs: 0.18rem; --space-sm: 0.4rem; --space-md: 0.7rem;
      --space-lg: 1rem; --space-xl: 1.6rem;
      --border-width: 1px;
      --transition-fast: 30ms; --transition-base: 60ms; --transition-slow: 120ms;
      --ease-base: linear;
      --backdrop-blur: 4px; --backdrop-saturate: 100%;
      --selection-bg: var(--text); --selection-fg: var(--bg);
      --scrollbar-thumb: var(--border-strong);
      --scrollbar-thumb-hover: var(--text);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 1px var(--accent);
      --link-decoration-style: solid; --link-decoration-thickness: 1px; --link-underline-offset: 2px;
    }
    [data-theme="telegraph"] .wordmark {
      font-family: var(--mono); font-weight: 700;
      letter-spacing: 0.25em; color: var(--accent);
    }
    [data-theme="telegraph"] .wordmark::before { content: "·–·· · "; color: var(--text-faint); font-size: 0.7em; }
    [data-theme="telegraph"] .wordmark::after { content: " ·–·· ·"; color: var(--text-faint); font-size: 0.7em; }
    [data-theme="telegraph"] .wordmark .y { color: var(--accent); font-style: normal; }
    [data-theme="telegraph"] @keyframes breathe {
      0%,100% { opacity: 0.85; } 50% { opacity: 1; }
    }
    [data-theme="telegraph"] .cursor { background: var(--text); }
    [data-theme="telegraph"] .sidebar {
      background: var(--surface);
      border-right: 1px dashed var(--border-strong);
    }
    [data-theme="telegraph"] .conv-item-wrap {
      border-bottom: 1px dashed var(--border);
      padding: 0.5rem 0.6rem; margin: 0;
    }
    [data-theme="telegraph"] .conv-item {
      font-family: var(--mono); font-size: 0.7rem;
      letter-spacing: 0.12em; color: var(--text);
    }
    /* Messages as horizontal ticker strips */
    [data-theme="telegraph"] .msg.user, [data-theme="telegraph"] .msg.assistant {
      align-self: stretch; background: var(--surface);
      border: none; border-top: 1px dashed var(--border);
      border-bottom: 1px dashed var(--border);
      padding: 0.6rem 1rem; max-width: 100%;
    }
    [data-theme="telegraph"] .msg-body {
      font-family: var(--mono); font-size: 0.78rem;
      letter-spacing: 0.06em; line-height: 1.6;
    }
    [data-theme="telegraph"] .msg.user::before, [data-theme="telegraph"] .msg.assistant::before {
      font-family: var(--mono); font-size: 0.55rem;
      letter-spacing: 0.2em; color: var(--accent);
      display: inline-block; margin-right: 0.6rem;
      padding: 0.1rem 0.3rem; border: 1px solid var(--border-strong);
    }
    [data-theme="telegraph"] .msg.user::before { content: "·– "; }
    [data-theme="telegraph"] .msg.assistant::before { content: "–· "; }
    [data-theme="telegraph"] .composer {
      background: var(--surface);
      border: 1px solid var(--border-strong);
      /* Trapezoidal telegraph key shape */
      clip-path: polygon(2% 0, 98% 0, 100% 100%, 0 100%);
      padding: 0.8rem 1.5rem;
    }

    /* ──── 6. CONSTELLATION — star-map graph ──── */
    [data-theme="constellation"] {
      --bg: #060818; --surface: #0c1028; --surface-2: #14183c;
      --border: #1c2050; --border-strong: #2c3070;
      --text: #f0f0ff; --text-dim: #a8b0d8; --text-faint: #6a7098;
      --accent: #ffd966; --accent-deep: #ddb030;
      --accent-soft: rgba(255, 217, 102, 0.16);
      --danger: #ff7faa; --warning: #ffd966; --success: #88e8b0;
      --font-chrome: var(--body); --font-meta: var(--body); --font-input: var(--body);
      --radius-chip: 999px; --radius-card: 24px; --radius-bubble: 999px;
      --scanline-opacity: 0;
      --elev-1: 0 0 12px rgba(255, 217, 102, 0.12);
      --elev-2: 0 0 24px rgba(255, 217, 102, 0.16);
      --elev-3: 0 0 40px rgba(255, 217, 102, 0.20);
      --glass-bg: rgba(12, 16, 40, 0.65);
      --glass-inset: rgba(255, 217, 102, 0.04);
      --glass-shadow: 0 0 16px rgba(255, 217, 102, 0.10);
      --glass-border: rgba(255, 217, 102, 0.20);
      /* Star field */
      --body-gradient: var(--bg);
      --space-xs: 0.3rem; --space-sm: 0.6rem; --space-md: 1rem;
      --space-lg: 1.5rem; --space-xl: 2.25rem;
      --border-width: 1px;
      --transition-fast: 200ms; --transition-base: 400ms; --transition-slow: 700ms;
      --ease-base: cubic-bezier(0.4, 0, 0.2, 1);
      --backdrop-blur: 20px; --backdrop-saturate: 140%;
      --selection-bg: color-mix(in srgb, var(--accent) 60%, transparent);
      --selection-fg: var(--bg);
      --scrollbar-thumb: color-mix(in srgb, var(--accent) 25%, transparent);
      --scrollbar-thumb-hover: color-mix(in srgb, var(--accent) 50%, transparent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 3px color-mix(in srgb, var(--accent) 40%, transparent);
      --link-decoration-style: solid; --link-decoration-thickness: 1px; --link-underline-offset: 3px;
    }
    [data-theme="constellation"] .wordmark {
      font-family: var(--body); font-weight: 500;
      color: var(--accent); letter-spacing: 0.2em;
    }
    [data-theme="constellation"] .wordmark .y { color: var(--warning); }
    [data-theme="constellation"] @keyframes breathe {
      0%,100% { text-shadow: 0 0 8px rgba(255,217,102,0.3); }
      50% { text-shadow: 0 0 20px rgba(255,217,102,0.7); }
    }
    [data-theme="constellation"] .cursor { background: var(--accent); }
    /* Star field background */
    [data-theme="constellation"] body::after {
      content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
      background-image:
        radial-gradient(1px 1px at 23px 45px, rgba(255,255,255,0.9), transparent),
        radial-gradient(1px 1px at 89px 12px, rgba(255,255,255,0.5), transparent),
        radial-gradient(1.5px 1.5px at 145px 67px, rgba(255,217,102,0.7), transparent),
        radial-gradient(1px 1px at 178px 134px, rgba(255,255,255,0.7), transparent),
        radial-gradient(1px 1px at 56px 156px, rgba(255,255,255,0.4), transparent),
        radial-gradient(1.5px 1.5px at 134px 178px, rgba(255,217,102,0.6), transparent),
        radial-gradient(1px 1px at 12px 187px, rgba(255,255,255,0.5), transparent);
      background-repeat: repeat;
      background-size: 220px 220px;
    }
    /* Sidebar — invisible chrome, conv items as small dots */
    [data-theme="constellation"] .sidebar {
      background: rgba(12, 16, 40, 0.4);
      border-right: 1px solid rgba(255, 217, 102, 0.15);
    }
    [data-theme="constellation"] .conv-item-wrap {
      padding: 0.4rem 0.8rem 0.4rem 1.8rem; margin: 0.2rem 0.3rem;
      position: relative;
    }
    [data-theme="constellation"] .conv-item-wrap::before {
      content: ""; position: absolute; left: 0.6rem; top: 50%;
      transform: translateY(-50%);
      width: 6px; height: 6px; border-radius: 50%;
      background: var(--accent-deep);
      box-shadow: 0 0 6px var(--accent);
    }
    [data-theme="constellation"] .conv-item-wrap.active::before {
      width: 10px; height: 10px; background: var(--accent);
      box-shadow: 0 0 12px var(--accent), 0 0 24px var(--accent-deep);
    }
    /* Messages as glowing nodes */
    [data-theme="constellation"] .msg.user, [data-theme="constellation"] .msg.assistant {
      background: radial-gradient(ellipse 100% 100% at 50% 50%,
        color-mix(in srgb, var(--surface) 80%, transparent),
        transparent 80%);
      border: none; border-radius: 28px;
      padding: 1rem 1.5rem; max-width: 75%;
      box-shadow: 0 0 28px rgba(255, 217, 102, 0.08);
    }
    [data-theme="constellation"] .msg.user {
      background: radial-gradient(ellipse 100% 100% at 50% 50%,
        color-mix(in srgb, var(--accent) 14%, var(--surface)),
        transparent 80%);
      box-shadow: 0 0 28px rgba(255, 217, 102, 0.15);
    }
    [data-theme="constellation"] .msg.assistant {
      background: radial-gradient(ellipse 100% 100% at 50% 50%,
        color-mix(in srgb, #88e8b0 12%, var(--surface)),
        transparent 80%);
      box-shadow: 0 0 28px rgba(136, 232, 176, 0.12);
    }
    [data-theme="constellation"] .msg.user::before, [data-theme="constellation"] .msg.assistant::before {
      font-family: var(--body); font-size: 0.6rem; letter-spacing: 0.2em;
      text-align: center; margin-bottom: 0.4rem; display: block;
      color: var(--text-faint);
    }
    [data-theme="constellation"] .msg.user::before { content: "✦ you ✦"; }
    [data-theme="constellation"] .msg.assistant::before { content: "✦ alyx ✦"; color: var(--accent); }
    [data-theme="constellation"] .composer {
      background: rgba(12, 16, 40, 0.7); border: 1px solid var(--border-strong);
      border-radius: 24px;
      box-shadow: 0 0 24px rgba(255, 217, 102, 0.20);
    }

    /* ──── 7. MEMPHIS — 80s playful geometry ──── */
    [data-theme="memphis"] {
      --bg: #fefefe; --surface: #ffffff; --surface-2: #f5f5f5;
      --border: #1a1a1a; --border-strong: #000000;
      --text: #1a1a1a; --text-dim: #4a4a4a; --text-faint: #7a7a7a;
      --accent: #ff5e87;       /* hot pink primary */
      --accent-deep: #d63878;
      --accent-soft: rgba(255, 94, 135, 0.18);
      --danger: #ff5e87; --warning: #ffd23f; --success: #4ecdc4;
      --font-chrome: var(--body); --font-meta: var(--body); --font-input: var(--body);
      --radius-chip: 999px; --radius-card: 0; --radius-bubble: 28px;
      --scanline-opacity: 0;
      --elev-1: 3px 3px 0 var(--border);
      --elev-2: 5px 5px 0 var(--border);
      --elev-3: 8px 8px 0 var(--border);
      --glass-bg: var(--surface);
      --glass-inset: rgba(255,255,255,1);
      --glass-shadow: 4px 4px 0 var(--border);
      --glass-border: var(--border);
      /* Terrazzo confetti — scattered colorful dots */
      --body-gradient:
        radial-gradient(circle at 8% 12%, #ff5e87 4px, transparent 4px),
        radial-gradient(circle at 23% 45%, #4ecdc4 3px, transparent 3px),
        radial-gradient(circle at 67% 18%, #ffd23f 4px, transparent 4px),
        radial-gradient(circle at 81% 67%, #c39bd3 3px, transparent 3px),
        radial-gradient(circle at 34% 78%, #4ecdc4 4px, transparent 4px),
        radial-gradient(circle at 52% 32%, #ffd23f 3px, transparent 3px),
        var(--bg);
      --space-xs: 0.3rem; --space-sm: 0.6rem; --space-md: 1rem;
      --space-lg: 1.5rem; --space-xl: 2.25rem;
      --border-width: 3px;
      --transition-fast: 100ms; --transition-base: 200ms; --transition-slow: 360ms;
      --ease-base: cubic-bezier(0.68, -0.55, 0.265, 1.55);
      --backdrop-blur: 0; --backdrop-saturate: 100%;
      --selection-bg: var(--warning); --selection-fg: var(--text);
      --scrollbar-thumb: var(--accent); --scrollbar-thumb-hover: var(--accent-deep);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 3px var(--border);
      --link-decoration-style: solid; --link-decoration-thickness: 2px; --link-underline-offset: 3px;
    }
    [data-theme="memphis"] .wordmark {
      font-family: var(--body); font-weight: 900; font-size: 1.6rem;
      transform: rotate(-3deg); display: inline-block;
    }
    [data-theme="memphis"] .wordmark .y { color: var(--accent); font-style: normal; }
    [data-theme="memphis"] @keyframes breathe { 0%,100% { transform: rotate(-3deg) scale(1); } 50% { transform: rotate(-3deg) scale(1.04); } }
    [data-theme="memphis"] .cursor { background: var(--accent); }
    [data-theme="memphis"] .sidebar {
      background: var(--surface);
      border-right: 3px solid var(--border);
    }
    [data-theme="memphis"] .conv-item-wrap {
      background: #4ecdc4; border: 3px solid var(--border);
      margin: 0.4rem 0.5rem; padding: 0.6rem 0.9rem;
      border-radius: 30% 70% 65% 35% / 60% 40% 60% 40%;
      box-shadow: 3px 3px 0 var(--border);
    }
    [data-theme="memphis"] .conv-item-wrap:nth-child(2n) {
      background: #ffd23f;
      border-radius: 70% 30% 40% 60% / 35% 65% 35% 65%;
    }
    [data-theme="memphis"] .conv-item-wrap:nth-child(3n) {
      background: #c39bd3;
      border-radius: 50% 50% 30% 70% / 65% 35% 65% 35%;
    }
    [data-theme="memphis"] .conv-item-wrap:nth-child(4n) {
      background: var(--accent);
      border-radius: 40% 60% 50% 50% / 50% 50% 40% 60%;
    }
    [data-theme="memphis"] .conv-item { color: var(--text) !important; font-weight: 700; }
    /* Messages as blobs */
    [data-theme="memphis"] .msg.user {
      background: var(--border-strong); border: 3px solid var(--border);
      border-radius: 40% 60% 30% 70% / 60% 40% 60% 40%;
      padding: 1rem 1.5rem; max-width: 75%;
      box-shadow: 4px 4px 0 var(--border); color: var(--text);
    }
    [data-theme="memphis"] .msg.assistant {
      background: #4ecdc4; border: 3px solid var(--border);
      border-radius: 70% 30% 50% 50% / 35% 65% 35% 65%;
      padding: 1rem 1.5rem; max-width: 75%;
      box-shadow: -4px 4px 0 var(--border); color: var(--text);
    }
    [data-theme="memphis"] .msg.user::before, [data-theme="memphis"] .msg.assistant::before {
      font-weight: 900; font-size: 0.7rem; letter-spacing: 0.18em;
      text-transform: uppercase; color: var(--text);
      margin-bottom: 0.4rem; display: block;
    }
    [data-theme="memphis"] .msg.user::before { content: "~ you ~"; text-align: right; }
    [data-theme="memphis"] .msg.assistant::before { content: "~ alyx ~"; }
    [data-theme="memphis"] .composer {
      background: var(--warning); border: 3px solid var(--border);
      border-radius: 12px;
      box-shadow: 5px 5px 0 var(--border);
    }

    /* ──── 8. MONDRIAN — primary grid ──── */
    [data-theme="mondrian"] {
      --bg: #ffffff; --surface: #ffffff; --surface-2: #f5f5f5;
      --border: #000000; --border-strong: #000000;
      --text: #000000; --text-dim: #2a2a2a; --text-faint: #6a6a6a;
      --accent: #ffd700;
      --accent-deep: #d4af00;
      --accent-soft: rgba(255, 215, 0, 0.18);
      --danger: #d00000; --warning: #ffd700; --success: #0044cc;
      --font-chrome: var(--body); --font-meta: var(--body); --font-input: var(--body);
      --radius-chip: 0; --radius-card: 0; --radius-bubble: 0;
      --scanline-opacity: 0;
      --elev-1: 0 0 0 4px #000;
      --elev-2: 0 0 0 4px #000;
      --elev-3: 0 0 0 5px #000;
      --glass-bg: var(--surface);
      --glass-inset: rgba(255,255,255,1);
      --glass-shadow: 0 0 0 4px #000;
      --glass-border: #000;
      --body-gradient: var(--bg);
      --space-xs: 0.25rem; --space-sm: 0.5rem; --space-md: 0.85rem;
      --space-lg: 1.25rem; --space-xl: 2rem;
      --border-width: 4px;
      --transition-fast: 0; --transition-base: 0; --transition-slow: 80ms;
      --ease-base: steps(1);
      --backdrop-blur: 0; --backdrop-saturate: 100%;
      --selection-bg: var(--accent); --selection-fg: #000;
      --scrollbar-thumb: #000;
      --scrollbar-thumb-hover: var(--danger);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 4px var(--danger);
      --link-decoration-style: solid; --link-decoration-thickness: 2px; --link-underline-offset: 2px;
    }
    [data-theme="mondrian"] .wordmark {
      font-family: var(--body); font-weight: 900;
      background: #fff; color: #000;
      border: 4px solid #000;
      padding: 0.1em 0.5em;
      font-style: normal;
    }
    [data-theme="mondrian"] .wordmark .y { color: var(--danger); font-style: normal; }
    [data-theme="mondrian"] @keyframes breathe { 0%,100% { background: #fff; } 50% { background: var(--accent); } }
    [data-theme="mondrian"] .cursor { background: var(--danger); }
    [data-theme="mondrian"] .sidebar {
      background: #fff; border-right: 4px solid #000;
    }
    [data-theme="mondrian"] .conv-item-wrap {
      background: #fff; border: 4px solid #000;
      margin: 0; padding: 0.6rem 0.8rem;
    }
    [data-theme="mondrian"] .conv-item-wrap:nth-child(3n+1) { background: var(--accent); }
    [data-theme="mondrian"] .conv-item-wrap:nth-child(3n+2) { background: var(--success); color: #fff; }
    [data-theme="mondrian"] .conv-item-wrap:nth-child(3n+2) .conv-item { color: #fff !important; }
    [data-theme="mondrian"] .conv-item-wrap.active { background: var(--danger); color: #fff; }
    [data-theme="mondrian"] .conv-item-wrap.active .conv-item { color: #fff !important; }
    [data-theme="mondrian"] .msg.user {
      background: var(--border-strong); border: 4px solid #000;
      padding: 1rem 1.4rem; max-width: 75%;
    }
    [data-theme="mondrian"] .msg.assistant {
      background: var(--success); color: #fff; border: 4px solid #000;
      padding: 1rem 1.4rem; max-width: 75%;
    }
    [data-theme="mondrian"] .msg.assistant .msg-body { color: #fff; }
    [data-theme="mondrian"] .msg.user::before, [data-theme="mondrian"] .msg.assistant::before {
      font-weight: 900; font-size: 0.7rem; letter-spacing: 0.18em;
      text-transform: uppercase; margin-bottom: 0.4rem; display: block;
    }
    [data-theme="mondrian"] .msg.user::before { content: "YOU"; color: #000; }
    [data-theme="mondrian"] .msg.assistant::before { content: "ALYX"; color: var(--accent); }
    [data-theme="mondrian"] .composer {
      background: var(--danger); border: 4px solid #000;
    }
    [data-theme="mondrian"] .composer textarea {
      background: rgba(255,255,255,0.92); color: #000;
      border: 2px solid #000;
    }

    /* ──── 9. TACTICAL — military HUD ──── */
    [data-theme="tactical"] {
      --bg: #1a1f12; --surface: #232a18; --surface-2: #2d351e;
      --border: #3a4422; --border-strong: #4f5e2c;
      --text: #d0d8b8; --text-dim: #8a9468; --text-faint: #5a6248;
      --accent: #ffaa33;       /* amber phosphor */
      --accent-deep: #cc8810;
      --accent-soft: rgba(255, 170, 51, 0.18);
      --danger: #ff4040; --warning: #ffaa33; --success: #44dd44;
      --font-chrome: var(--mono); --font-meta: var(--mono); --font-input: var(--mono);
      --radius-chip: 0; --radius-card: 0; --radius-bubble: 0;
      --scanline-opacity: 1;
      --elev-1: 0 0 0 1px var(--border-strong);
      --elev-2: 0 0 0 1px var(--accent-deep);
      --elev-3: 0 0 0 2px var(--accent);
      --glass-bg: rgba(35, 42, 24, 0.85);
      --glass-inset: rgba(255, 170, 51, 0.04);
      --glass-shadow: 0 0 0 1px var(--accent-deep);
      --glass-border: var(--border-strong);
      --body-gradient:
        radial-gradient(ellipse 80vw 80vh at 50% 50%, rgba(255, 170, 51, 0.05), transparent 70%),
        var(--bg);
      --space-xs: 0.18rem; --space-sm: 0.4rem; --space-md: 0.7rem;
      --space-lg: 1rem; --space-xl: 1.6rem;
      --border-width: 1px;
      --transition-fast: 30ms; --transition-base: 60ms; --transition-slow: 120ms;
      --ease-base: steps(2, end);
      --backdrop-blur: 0; --backdrop-saturate: 100%;
      --selection-bg: var(--accent); --selection-fg: #000;
      --scrollbar-thumb: var(--accent-deep);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid; --link-decoration-thickness: 1px; --link-underline-offset: 3px;
    }
    [data-theme="tactical"] .wordmark {
      font-family: var(--mono); font-weight: 700; color: var(--accent);
      letter-spacing: 0.25em;
      text-shadow: 0 0 6px var(--accent-deep);
    }
    [data-theme="tactical"] .wordmark .y { color: var(--accent); font-style: normal; }
    [data-theme="tactical"] @keyframes breathe {
      0%,100% { text-shadow: 0 0 4px var(--accent-deep); }
      50% { text-shadow: 0 0 14px var(--accent); }
    }
    [data-theme="tactical"] .cursor { background: var(--accent); }
    /* Viewport-corner crosshairs */
    [data-theme="tactical"] body::after {
      content: "N 32°42′18″   W 117°09′46″   ALT 0023M   BRG 045°";
      position: fixed; bottom: 6px; left: 10px;
      font-family: var(--mono); font-size: 0.55rem;
      letter-spacing: 0.18em; color: var(--accent-deep);
      pointer-events: none; z-index: 0;
    }
    [data-theme="tactical"] .sidebar {
      background: rgba(35, 42, 24, 0.4);
      border-right: 1px solid var(--border-strong);
    }
    [data-theme="tactical"] .conv-item-wrap {
      border: 1px solid var(--border-strong);
      margin: 0.3rem; padding: 0.5rem 0.7rem;
    }
    [data-theme="tactical"] .conv-item-wrap.active {
      border-color: var(--border-strong);
      box-shadow: inset 0 0 12px rgba(255, 170, 51, 0.12);
    }
    [data-theme="tactical"] .conv-item-wrap::after {
      content: "ACTIVE"; display: block; margin-top: 0.2rem;
      font-family: var(--mono); font-size: 0.5rem; letter-spacing: 0.18em;
      color: var(--accent-deep);
    }
    [data-theme="tactical"] .conv-item-wrap:not(.active)::after { content: "STANDBY"; }
    [data-theme="tactical"] .conv-item {
      font-family: var(--mono); color: var(--accent); letter-spacing: 0.1em;
      text-transform: uppercase; font-weight: 600; font-size: 0.65rem;
    }
    [data-theme="tactical"] .msg.user, [data-theme="tactical"] .msg.assistant {
      background: rgba(45, 53, 30, 0.6); border: 1px solid var(--border-strong);
      padding: 0.6rem 1rem; max-width: 88%; position: relative;
    }
    [data-theme="tactical"] .msg-body { color: var(--accent); font-family: var(--mono); font-size: 0.78rem; }
    [data-theme="tactical"] .msg.user::before, [data-theme="tactical"] .msg.assistant::before {
      font-family: var(--mono); font-size: 0.55rem; letter-spacing: 0.18em;
      color: var(--accent); margin-bottom: 0.4rem; display: block;
      border-bottom: 1px dashed var(--border-strong); padding-bottom: 0.2rem;
    }
    [data-theme="tactical"] .msg.user::before { content: "[TX] OP-USR  ::  TS 14:32Z"; }
    [data-theme="tactical"] .msg.assistant::before { content: "[RX] ALYX-1  ::  TS 14:32Z"; }
    [data-theme="tactical"] .composer {
      background: rgba(35, 42, 24, 0.85);
      border: 1px solid var(--border-strong);
      position: relative; padding-top: 1.4rem;
    }
    [data-theme="tactical"] .composer::before {
      content: "INPUT [SECURE]   ::   STATUS: READY";
      position: absolute; top: 0.3rem; left: 0.8rem;
      font-family: var(--mono); font-size: 0.55rem; letter-spacing: 0.18em;
      color: var(--accent);
    }

    /* ──── 10. MUSEUM — bronze exhibit plaques ──── */
    [data-theme="museum"] {
      --bg: #efe8d8; --surface: #f7f1e1; --surface-2: #e0d5b8;
      --border: #b89a6a; --border-strong: #8a6a40;
      --text: #1a1408; --text-dim: #4a3818; --text-faint: #8a7448;
      --accent: #8a6a30;       /* bronze */
      --accent-deep: #5a4520;
      --accent-soft: rgba(138, 106, 48, 0.14);
      --danger: #a83a18; --warning: #c08840; --success: #4a6c3a;
      --font-chrome: var(--display); --font-meta: var(--display); --font-input: var(--body);
      --radius-chip: 2px; --radius-card: 3px; --radius-bubble: 3px;
      --scanline-opacity: 0;
      --elev-1: 0 2px 4px rgba(26, 20, 8, 0.20), inset 0 1px 0 rgba(255, 240, 200, 0.5);
      --elev-2: 0 6px 12px rgba(26, 20, 8, 0.25), inset 0 1px 0 rgba(255, 240, 200, 0.5);
      --elev-3: 0 12px 24px rgba(26, 20, 8, 0.35), inset 0 1px 0 rgba(255, 240, 200, 0.5);
      --glass-bg: rgba(247, 241, 225, 0.92);
      --glass-inset: rgba(255, 247, 225, 0.95);
      --glass-shadow: 0 4px 12px rgba(26, 20, 8, 0.25);
      --glass-border: var(--border);
      /* Museum spotlight effect */
      --body-gradient:
        radial-gradient(ellipse 100vw 60vh at 50% -10%, rgba(255, 230, 180, 0.40), transparent 60%),
        var(--bg);
      --space-xs: 0.3rem; --space-sm: 0.6rem; --space-md: 1rem;
      --space-lg: 1.5rem; --space-xl: 2.25rem;
      --border-width: 1px;
      --transition-fast: 200ms; --transition-base: 380ms; --transition-slow: 600ms;
      --ease-base: cubic-bezier(0.25, 0.1, 0.25, 1);
      --backdrop-blur: 4px; --backdrop-saturate: 105%;
      --selection-bg: color-mix(in srgb, var(--accent) 30%, transparent);
      --selection-fg: var(--text);
      --scrollbar-thumb: var(--border);
      --scrollbar-thumb-hover: var(--accent);
      --scrollbar-track: transparent;
      --focus-ring: 0 0 0 2px var(--accent);
      --link-decoration-style: solid; --link-decoration-thickness: 1px; --link-underline-offset: 4px;
    }
    [data-theme="museum"] {
      font-feature-settings: "onum" 1, "liga" 1, "calt" 1;
    }
    [data-theme="museum"] .wordmark {
      font-family: var(--display); font-weight: 700;
      color: var(--accent); letter-spacing: 0.15em;
      text-shadow: 0 1px 0 rgba(255, 240, 200, 0.7), 0 -1px 0 rgba(0, 0, 0, 0.2);
      text-transform: uppercase;
    }
    [data-theme="museum"] .wordmark .y { color: var(--accent-deep); font-style: normal; }
    [data-theme="museum"] @keyframes breathe {
      0%,100% { opacity: 0.92; } 50% { opacity: 1; }
    }
    [data-theme="museum"] .cursor { background: var(--accent); }
    [data-theme="museum"] .sidebar {
      background: var(--surface);
      border-right: 1px solid var(--border);
    }
    /* Conv items as brass nameplates with roman numerals */
    [data-theme="museum"] .conv-list { counter-reset: museum-num; }
    [data-theme="museum"] .conv-item-wrap {
      background: linear-gradient(180deg, #c4a468, #8a6a30);
      border: 1px solid #5a4520;
      margin: 0.4rem 0.5rem; padding: 0.6rem 0.8rem 0.6rem 2.2rem;
      box-shadow: 0 2px 4px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255, 230, 180, 0.5);
      position: relative; counter-increment: museum-num;
    }
    [data-theme="museum"] .conv-item-wrap::before {
      content: counter(museum-num, upper-roman) ".";
      position: absolute; left: 0.6rem; top: 50%; transform: translateY(-50%);
      font-family: var(--display); font-weight: 700;
      color: var(--surface);
      text-shadow: 0 1px 1px rgba(0,0,0,0.4);
    }
    [data-theme="museum"] .conv-item {
      color: var(--surface) !important;
      font-family: var(--display); font-style: italic;
      text-shadow: 0 1px 1px rgba(0,0,0,0.3);
    }
    /* Messages as engraved plaques */
    [data-theme="museum"] .msg.user, [data-theme="museum"] .msg.assistant {
      background: linear-gradient(180deg, #d4b478, #b89a5a);
      border: 1px solid #5a4520;
      padding: 1rem 1.2rem 0.9rem; max-width: 80%;
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 240, 200, 0.4);
      position: relative;
    }
    /* Rivets in corners */
    [data-theme="museum"] .msg.user::after, [data-theme="museum"] .msg.assistant::after {
      content: ""; position: absolute;
      top: 4px; left: 4px;
      width: 5px; height: 5px; border-radius: 50%;
      background: radial-gradient(circle at 30% 30%, #f0d088, #5a4520);
      box-shadow:
        calc(100% - 13px) 0 0 0 transparent,
        var(--rivet-tr, 0 0 0 0 transparent);
    }
    [data-theme="museum"] .msg-body {
      color: var(--text); font-family: var(--display);
      line-height: 1.65; font-size: 0.95rem;
    }
    [data-theme="museum"] .msg.user::before, [data-theme="museum"] .msg.assistant::before {
      font-family: var(--display); font-variant: small-caps;
      font-size: 0.78rem; letter-spacing: 0.15em;
      color: var(--accent-deep); display: block; margin-bottom: 0.4rem;
      border-bottom: 1px solid rgba(90, 69, 32, 0.4); padding-bottom: 0.3rem;
    }
    [data-theme="museum"] .msg.user::before { content: "Inquirer"; }
    [data-theme="museum"] .msg.assistant::before { content: "Curator — alyx"; }
    [data-theme="museum"] .composer {
      background: linear-gradient(180deg, #c4a468, #8a6a30);
      border: 1px solid #5a4520;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 240, 200, 0.4);
      padding: 0.8rem 1.2rem;
    }
    [data-theme="museum"] .composer textarea {
      background: rgba(239, 232, 216, 0.95); color: var(--text);
      border: 1px solid #5a4520; border-radius: 2px;
      padding: 0.5rem 0.7rem;
      font-family: var(--body);
    }

    *, *::before, *::after { box-sizing: border-box; }
    html, body {
      height: 100%; margin: 0;
      /* `manipulation` disables double-tap zoom (and the historic 300ms
         tap delay) without breaking scroll. Doesn't block pinch on
         iOS Safari — that needs the JS gesturestart handlers below. */
      touch-action: manipulation;
    }
    /* caret-color is inheritable — declared once at the root so every
       input / textarea / contenteditable across the app gets the accent
       caret without per-element rules. Login.html inherits this too via
       the shared app.css. */
    html { caret-color: var(--accent); }
    body {
      color: var(--text);
      font-family: var(--body);
      font-size: 14px; line-height: 1.55;
      letter-spacing: -0.005em;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      /* App shell: sidebar + main column side-by-side. Internal column
         layout (header/conv/composer) is inside .main-col. */
      display: flex; flex-direction: row;
      min-height: 100vh; height: 100vh;
      /* viewport-relative sizes (vw/vh) so the aurora reads at the same
         proportion regardless of viewport height. Per-theme gradient
         stops live in --body-gradient (set in :root + each theme block). */
      background: var(--body-gradient);
      overflow: hidden;
    }
    /* Grain overlay — dark/black themes only. Pure dark backgrounds
       plus glass blur can feel sterile/digital; a 3% SVG noise grain
       adds analog warmth (closer to film than OLED). Light themes read
       warm already from white paper association — skip there. */
    [data-theme="dark"] body::after,
    [data-theme="black"] body::after {
      content: "";
      position: fixed; inset: 0;
      pointer-events: none;
      z-index: 9999;
      opacity: 0.035;
      mix-blend-mode: overlay;
      background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
    }

    /* ── theme-driven brand details ──
       The four cross-cutting moments where themes can express identity
       even outside their chrome: text selection, scrollbars, focus
       indication, link underlines. Tokens are set per-theme in the
       [data-theme="X"] blocks; these rules are universal consumers. */

    ::selection {
      background: var(--selection-bg);
      color: var(--selection-fg);
    }
    ::-moz-selection {
      background: var(--selection-bg);
      color: var(--selection-fg);
    }

    /* WebKit/Blink scrollbars */
    ::-webkit-scrollbar {
      width: 10px; height: 10px;
    }
    ::-webkit-scrollbar-track {
      background: var(--scrollbar-track);
    }
    ::-webkit-scrollbar-thumb {
      background: var(--scrollbar-thumb);
      border-radius: var(--radius-pill);
      transition: background var(--transition-base) var(--ease-base);
    }
    ::-webkit-scrollbar-thumb:hover {
      background: var(--scrollbar-thumb-hover);
    }
    /* Firefox scrollbar — single rule, less customizable */
    * {
      scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
      scrollbar-width: thin;
    }

    /* Focus ring — keyboard nav indicator. :focus-visible suppresses
       the ring on mouse clicks; tab nav gets the themed box-shadow. */
    :focus { outline: none; }
    :focus-visible {
      outline: none;
      box-shadow: var(--focus-ring);
    }

    /* Link decoration — themes set style/thickness/offset */
    a {
      color: var(--accent-deep);
      text-decoration-style: var(--link-decoration-style);
      text-decoration-thickness: var(--link-decoration-thickness);
      text-underline-offset: var(--link-underline-offset);
    }
    /* Global CRT scanline overlay — gated on --scanline-opacity so themes
       that don't want terminal grit (light, future) hide it entirely
       (opacity 0). Color tinted to the active --accent so it phases with
       whichever palette is in play. */
    body::before {
      content: "";
      position: fixed; inset: 0;
      pointer-events: none;
      z-index: 0;
      opacity: var(--scanline-opacity);
      transition: opacity 200ms ease;
      background: repeating-linear-gradient(
        to bottom,
        transparent 0,
        transparent 3px,
        color-mix(in srgb, var(--accent) 2.5%, transparent) 3px,
        color-mix(in srgb, var(--accent) 2.5%, transparent) 4px
      );
    }
    .main-col {
      flex: 1;
      min-width: 0;            /* so flex children with overflow respect us */
      display: flex; flex-direction: column;
      height: 100vh;
      position: relative;      /* anchor for absolute composer-wrap */
      z-index: 1;              /* above body::before scanlines */
    }

    /* The italic "y" in the wordmark — cyan glow on dark, with a richer
       breathe-pulse. Light theme keeps the original ice-deep glow. */
    [data-theme="terminal"] .wordmark .y { color: var(--accent); }
    [data-theme="terminal"] @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.22em rgba(103, 232, 249, 0.28); }
      50%      { text-shadow: 0 0 0.55em rgba(103, 232, 249, 0.55); }
    }

    /* Cursor — match the active accent in either theme. */
    [data-theme="terminal"] .cursor { background: var(--accent); }


    /* Theme-toggle icon swap — single source of truth for which icon
       shows. Used by the account menu's theme item. */
    .icon-sun { display: none; }
    .icon-moon { display: block; }
    [data-theme="terminal"] .icon-sun { display: block; }
    [data-theme="terminal"] .icon-moon { display: none; }

    /* ── sidebar ─ control terminal ────────────────
       Operator console / dev-tool sidebar. Mono-typeset, sharp edges,
       numbered sessions, status indicators. Visually distinct from the
       editorial conv area so the two regions read as "control surface"
       vs "reading surface". */
    .sidebar {
      position: relative;
      width: 16.5rem;
      flex-shrink: 0;
      display: flex; flex-direction: column;
      gap: 0;
      padding: 0;
      background: color-mix(in srgb, var(--surface) 32%, transparent);
      backdrop-filter: blur(var(--backdrop-blur)) saturate(var(--backdrop-saturate));
      -webkit-backdrop-filter: blur(var(--backdrop-blur)) saturate(var(--backdrop-saturate));
      border-right: var(--border-width) solid var(--border);
      overflow: hidden;
    }
    /* Faint horizontal scanline overlay — barely-visible terminal-CRT
       texture that disappears unless you're looking for it. Light theme
       uses an ink tint; dark theme uses ice for the phosphor feel. */
    .sidebar::before {
      content: "";
      position: absolute; inset: 0;
      opacity: var(--scanline-opacity);
      transition: opacity 200ms ease;
      background: repeating-linear-gradient(
        to bottom,
        transparent 0,
        transparent 3px,
        color-mix(in srgb, var(--accent) 3%, transparent) 3px,
        color-mix(in srgb, var(--accent) 3%, transparent) 4px
      );
      pointer-events: none;
      z-index: 1;
    }
    /* Brand area — wordmark anchored top-left. Hard ice rule along the
       bottom ties it to the terminal frame. The collapse toggle is a
       small bordered square in the top-right. */
    .sidebar-brand {
      position: relative;
      z-index: 2;
      padding: 1.05rem 0.95rem 0.95rem;
      border-bottom: 1px solid var(--border);
    }
    .sidebar-brand .wordmark {
      font-size: 1.95rem;
      line-height: 1;
      margin: 0;
    }
    /* status-pulse keyframe kept — still used by composer's listening
       caption + greeting's pulsing tag was removed but keyframe is
       cheap to keep around for future use. */
    @keyframes status-pulse {
      0%, 100% { opacity: 0.6; transform: scale(0.92); }
      50%      { opacity: 1;   transform: scale(1.12); }
    }
    .sidebar-toggle {
      position: absolute;
      top: 0.9rem; right: 0.55rem;
      width: 1.75rem; height: 1.75rem;
      display: inline-flex; align-items: center; justify-content: center;
      padding: 0;
      background: transparent;
      border: 1px solid color-mix(in srgb, var(--border-strong) 50%, transparent);
      border-radius: var(--radius-chip);
      color: var(--text-faint);
      cursor: pointer;
      transition: color .1s linear, border-color .1s linear,
                  background .1s linear;
    }
    .sidebar-toggle:hover {
      color: var(--accent-fg);
      border-color: var(--border-strong);
      background: var(--accent);
    }
    .sidebar-toggle:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 1px;
    }
    .sidebar-toggle svg { width: 0.85rem; height: 0.85rem; }

    /* Floating reveal button — matches the sidebar's sharp terminal
       aesthetic: square corners, ice border, fills on hover. */
    .sidebar-show {
      display: none;
      position: fixed;
      top: 0.95rem; left: 0.95rem;
      width: 2.15rem; height: 2.15rem;
      align-items: center; justify-content: center;
      padding: 0;
      background: color-mix(in srgb, var(--surface) 75%, transparent);
      backdrop-filter: blur(14px) saturate(140%);
      -webkit-backdrop-filter: blur(14px) saturate(140%);
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      color: var(--text-dim);
      cursor: pointer;
      z-index: 80;
      transition: color .1s linear, background .1s linear,
                  border-color .1s linear;
    }
    .sidebar-show:hover {
      color: var(--accent-fg);
      border-color: var(--border-strong);
      background: var(--accent);
    }
    .sidebar-show:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }
    .sidebar-show svg { width: 0.95rem; height: 0.95rem; }
    body.sidebar-collapsed .sidebar { display: none; }
    body.sidebar-collapsed .sidebar-show { display: inline-flex; }

    /* Backdrop for the mobile drawer overlay. Hidden by default; on
       mobile + body.sidebar-open, fades in. Clicking dismisses. */
    .sidebar-backdrop { display: none; }

    /* New session — sharp-cornered mono-caps button with an ice border.
       Hover fills solid ice with inverted text; active depresses 1px.
       Reads like a "boot a new session" command on a control terminal. */
    .new-chat-btn {
      position: relative;
      z-index: 2;
      display: flex; align-items: center; justify-content: center;
      gap: 0.55rem;
      /* horizontal margin matches .sidebar-account's outer padding so
         the button + account row + conv-list-items column have a
         consistent left/right inset down the whole sidebar. */
      margin: 0.75rem 0.45rem 0.15rem;
      padding: 0.72rem 0.9rem;
      background: transparent;
      color: var(--accent-deep);
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      cursor: pointer;
      font-family: var(--font-chrome);
      font-size: 0.62rem;
      font-weight: 600;
      letter-spacing: 0.24em;
      text-transform: uppercase;
      transition: color .1s linear, background .1s linear,
                  border-color .1s linear, box-shadow .1s linear,
                  transform .08s linear;
    }
    [data-theme="terminal"] .new-chat-btn {
      color: var(--accent);
      border-color: var(--border);
    }
    .new-chat-btn:hover {
      color: var(--accent-fg);
      background: var(--accent);
      border-color: var(--border-strong);
      box-shadow: 0 0 14px -2px color-mix(in srgb, var(--accent) 50%, transparent);
    }
    [data-theme="terminal"] .new-chat-btn:hover {
      box-shadow: 0 0 16px -2px color-mix(in srgb, var(--accent) 60%, transparent);
    }
    .new-chat-btn:active { transform: translateY(1px); }
    .new-chat-btn:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }
    .new-chat-btn svg {
      width: 0.78rem; height: 0.78rem;
      stroke-width: 2.5;
    }

    /* Conv list — sharp rows, no gap, numbered via CSS counter. The
       counter increments per .conv-item-wrap and is rendered into
       each row's ::before. A bit of top padding gives the first row
       air beneath the new-chat button (the section label is gone). */
    .conv-list {
      flex: 1;
      position: relative;
      z-index: 2;
      overflow-y: auto;
      overflow-x: hidden;
      display: flex; flex-direction: column;
      gap: 0;
      padding: 0.75rem 0.45rem 0.5rem;
      counter-reset: conv 0;
      scrollbar-width: thin;
      scrollbar-color: color-mix(in srgb, var(--accent) 35%, transparent) transparent;
    }
    .conv-list::-webkit-scrollbar { width: 4px; }
    .conv-list::-webkit-scrollbar-thumb {
      background: color-mix(in srgb, var(--accent) 35%, transparent);
      border-radius: 0;
    }

    /* Each row is a tabular line: a numeric prefix in mono, the title
       in mono, optional pin/delete icons on the right. Sharp corners,
       hover snaps to an ice tint, active snaps to a solid ice fill. */
    /* Base border is 3px so hover / active states only change COLOR,
       not width — no 1px layout wobble as the cursor crosses items. */
    .conv-item-wrap {
      position: relative;
      counter-increment: conv;
      border-radius: 0;
      border-left: 3px solid transparent;
      transition: background .1s linear, border-color .1s linear;
    }
    .conv-item-wrap:hover {
      background: color-mix(in srgb, var(--accent) 8%, transparent);
      border-left-color: color-mix(in srgb, var(--accent) 50%, transparent);
    }
    .conv-item-wrap.pinned {
      background: color-mix(in srgb, var(--accent) 4%, transparent);
    }
    .conv-item-wrap.pinned:hover {
      background: color-mix(in srgb, var(--accent) 10%, transparent);
    }
    /* Museum-label idiom: a vertical accent bar on the inner edge
       signals "current selection" cleanly, with a subtle accent-tinted
       fill underneath rather than a loud full-accent fill that
       dominates the sidebar. */
    .conv-item-wrap.active {
      background: color-mix(in srgb, var(--accent) 14%, transparent);
      border-left-color: var(--accent);
    }
    .conv-item-wrap.pinned.active {
      background: color-mix(in srgb, var(--accent) 18%, transparent);
      border-left-color: var(--accent);
    }
    /* Right-positioned sidebar: mirror the bar to the outside (visual
       inner edge from the conv-list's perspective). Keep base 3px
       transparent rule for symmetry — hover/active flip the right edge. */
    [data-sidebar-side="right"] .conv-item-wrap {
      border-left: none;
      border-right: 3px solid transparent;
    }
    [data-sidebar-side="right"] .conv-item-wrap:hover {
      border-right-color: color-mix(in srgb, var(--accent) 50%, transparent);
    }
    [data-sidebar-side="right"] .conv-item-wrap.active,
    [data-sidebar-side="right"] .conv-item-wrap.pinned.active {
      border-right-color: var(--accent);
    }

    /* Numeric prefix — leading-zero counter in mono. Swaps to ★ on
       pinned, inverts color on active. */
    .conv-item-wrap::before {
      content: counter(conv, decimal-leading-zero);
      position: absolute;
      left: 0.55rem; top: 0.62rem;
      font-family: var(--font-chrome);
      font-size: 0.58rem;
      font-weight: 500;
      letter-spacing: 0;
      color: var(--text-faint);
      pointer-events: none;
      transition: color .1s linear;
    }
    .conv-item-wrap:hover::before { color: var(--accent-deep); }
    [data-theme="terminal"] .conv-item-wrap:hover::before { color: var(--accent); }
    .conv-item-wrap.pinned::before {
      content: "★";
      font-size: 0.7rem;
      top: 0.54rem;
      color: var(--accent-deep);
    }
    [data-theme="terminal"] .conv-item-wrap.pinned::before { color: var(--accent); }
    /* Active counter marker uses the accent color now that the active
       background is a tint rather than full accent fill — keeps the
       counter readable AND reinforces the accent-bar idiom. */
    .conv-item-wrap.active::before,
    [data-theme="terminal"] .conv-item-wrap.active::before {
      color: var(--accent);
    }

    .conv-item {
      display: block;
      width: 100%;
      padding: 0.5rem 3.4rem 0.5rem 2.1rem;
      background: transparent;
      color: var(--text-dim);
      border: 0;
      border-radius: 0;
      text-align: left;
      cursor: pointer;
      font-family: var(--font-chrome);
      font-size: 0.74rem;
      font-weight: 400;
      letter-spacing: 0;
      line-height: 1.5;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
      transition: color .1s linear;
    }
    .conv-item-wrap:hover .conv-item { color: var(--text); }
    .conv-item-wrap.active .conv-item {
      color: var(--text);
      font-weight: 600;
    }
    .conv-item:focus-visible { outline: none; }
    /* Inset accent ring fires ONLY for keyboard focus (`:has(:focus-visible)`)
       so mouse clicks don't leave a lingering outline — the `.active`
       state is already a clear selection signal for click users. Keyboard
       a11y still gets the ring while tabbing through. */
    .conv-item-wrap:has(:focus-visible) {
      box-shadow: inset 0 0 0 1px var(--accent);
    }

    /* Hover/focus-reveal action row — pin + delete, right side. */
    .conv-item-actions {
      position: absolute;
      top: 50%; right: 0.3rem;
      transform: translateY(-50%);
      display: flex; align-items: center;
      gap: 0;
      opacity: 0;
      transition: opacity .1s linear;
      pointer-events: none;
    }
    .conv-item-wrap:hover .conv-item-actions,
    .conv-item-wrap:focus-within .conv-item-actions {
      opacity: 1;
      pointer-events: auto;
    }
    .conv-item-wrap.pinned .conv-item-action[data-action="pin"] {
      opacity: 1;
      pointer-events: auto;
    }
    @media (hover: none) and (pointer: coarse) {
      .conv-item-actions { opacity: 1; pointer-events: auto; }
      .conv-item { padding-right: 4rem; }
      .conv-item-action { width: 1.7rem; height: 1.7rem; }
      .conv-item-action svg { width: 0.95rem; height: 0.95rem; }
    }

    .conv-item-action {
      display: inline-flex; align-items: center; justify-content: center;
      width: 1.5rem; height: 1.5rem;
      padding: 0;
      background: transparent;
      border: 0;
      border-radius: 0;
      color: var(--text-faint);
      cursor: pointer;
      transition: color .1s linear, background .1s linear;
    }
    .conv-item-action:hover {
      background: color-mix(in srgb, var(--text) 15%, transparent);
      color: var(--text);
    }
    /* Active row's icons follow the same scheme as inactive ones now
       that the active background is a subtle accent tint (no longer
       a high-contrast accent fill). */
    .conv-item-wrap.active .conv-item-action {
      color: var(--text-faint);
    }
    .conv-item-wrap.active .conv-item-action:hover {
      background: color-mix(in srgb, var(--accent) 18%, transparent);
      color: var(--text);
    }
    [data-theme="terminal"] .conv-item-wrap.active .conv-item-action:hover {
      background: color-mix(in srgb, var(--bg) 22%, transparent);
    }
    .conv-item-action.danger:hover {
      background: color-mix(in srgb, var(--danger) 18%, transparent);
      color: var(--danger);
    }
    .conv-item-wrap.pinned .conv-item-action[data-action="pin"] { color: var(--text); }
    [data-theme="terminal"] .conv-item-wrap.pinned .conv-item-action[data-action="pin"] { color: var(--text); }
    .conv-item-wrap.pinned .conv-item-action[data-action="pin"]:hover {
      background: color-mix(in srgb, var(--text) 14%, transparent);
    }
    /* Active+pinned: pin icon flips to match the title — white in
       light, dark in dark — using var(--bg) which inverts across
       themes. Higher specificity than the .pinned rule above so it
       actually wins. */
    .conv-item-wrap.pinned.active .conv-item-action[data-action="pin"] {
      color: var(--accent-fg);
    }
    .conv-item-action:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 0;
    }
    .conv-item-action.danger:focus-visible { outline-color: var(--danger); }
    .conv-item-action svg { width: 0.78rem; height: 0.78rem; }
    .conv-item-action .pin-filled { display: none; }
    .conv-item-wrap.pinned .conv-item-action .pin-outline { display: none; }
    .conv-item-wrap.pinned .conv-item-action .pin-filled { display: inline-block; }

    /* Empty state — terminal "no records found" panel with a blinking
       cursor at the end of the message. Mono throughout, sharp box. */
    .conv-list-empty {
      position: relative;
      z-index: 2;
      margin: 0.6rem 0.45rem;
      padding: 0.85rem 0.85rem 0.9rem;
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      background: color-mix(in srgb, var(--accent) 4%, transparent);
      text-align: left;
      display: flex; flex-direction: column;
      gap: 0.5rem;
    }
    .conv-list-empty::before {
      content: "No conversations";
      font-family: var(--font-chrome); font-size: 0.55rem;
      font-weight: 600;
      letter-spacing: 0.15em;
      text-transform: uppercase;
      color: color-mix(in srgb, var(--accent) 65%, transparent);
    }
    [data-theme="terminal"] .conv-list-empty::before { content: "// no sessions"; }
    .conv-list-empty em {
      font-family: var(--font-chrome); font-style: normal;
      font-weight: 400;
      font-size: 0.7rem;
      color: var(--text-dim);
      letter-spacing: 0;
      line-height: 1.5;
    }
    /* Blinking cursor on the end of the headline — terminal-only;
       other themes get a clean text-only empty state without the
       cursor glyph. */
    .conv-list-empty em::after { display: none; }
    [data-theme="terminal"] .conv-list-empty em::after {
      content: "▌";
      display: inline-block;
      margin-left: 0.15rem;
      color: var(--accent);
      animation: cursor-blink 1.05s steps(2, start) infinite;
    }
    @keyframes cursor-blink {
      0%, 100% { opacity: 1; }
      50%      { opacity: 0; }
    }
    .conv-list-empty span {
      font-family: var(--font-chrome); font-size: 0.55rem;
      font-weight: 500;
      letter-spacing: 0.18em; text-transform: uppercase;
      color: var(--text-faint);
      line-height: 1.55;
    }

    /* (header removed — sidebar now carries all the chrome.)
       Fraunces axes: opsz=144 + SOFT=100 + wonk=1 = the display cut the
       typeface was actually designed for — characterful terminals,
       flaring strokes, swashy italic. Default opsz wastes the personality. */
    .wordmark {
      font-family: var(--display);
      font-variation-settings: "opsz" 144, "SOFT" 100, "wght" 500, "wonk" 1;
      font-size: 2rem; line-height: 1;
      letter-spacing: -0.018em; color: var(--text); margin: 0;
    }
    .wordmark .y {
      font-style: italic;
      font-variation-settings: "opsz" 144, "SOFT" 100, "wght" 450, "wonk" 1;
      color: var(--accent-deep);
      animation: breathe 5s ease-in-out infinite;
    }
    @keyframes breathe {
      0%, 100% { text-shadow: 0 0 0.18em rgba(14, 165, 233, 0.10); }
      50%      { text-shadow: 0 0 0.40em rgba(14, 165, 233, 0.28); }
    }

    .spacer { flex: 1; }
    .icon-btn {
      font-family: var(--font-chrome); font-size: 0.62rem;
      letter-spacing: 0.16em; text-transform: uppercase;
      color: var(--text-dim);
      background: transparent;
      border: 1px solid var(--border);
      border-radius: 8px; padding: 0.42rem 0.78rem;
      cursor: pointer;
      transition: border-color .15s, color .15s, background .15s;
    }
    .icon-btn:hover {
      color: var(--accent-deep);
      border-color: var(--border-strong);
      background: var(--accent-soft);
    }
    .icon-btn:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }

    /* ── account (sidebar footer) ─ operator block ──
       Hard bar at the bottom. Solid ice rule on top, square avatar,
       mono email. Sharp corners throughout — matches the rest of the
       terminal frame. */
    .sidebar-account {
      position: relative;
      z-index: 2;
      padding: 0.55rem 0.45rem 0.65rem;
      border-top: 1px solid var(--border);
    }
    .account { position: relative; }
    .account-trigger {
      display: flex; align-items: center;
      gap: 0.55rem;
      width: 100%;
      padding: 0.42rem 0.5rem;
      background: transparent;
      border: 1px solid transparent;
      border-radius: var(--radius-chip);
      cursor: pointer;
      color: var(--text-dim);
      text-align: left;
      transition: color .1s linear, background .1s linear,
                  border-color .1s linear;
    }
    .account-trigger:hover,
    .account-trigger[aria-expanded="true"] {
      color: var(--text);
      background: color-mix(in srgb, var(--accent) 10%, transparent);
      border-color: var(--border);
    }
    [data-theme="terminal"] .account-trigger:hover,
    [data-theme="terminal"] .account-trigger[aria-expanded="true"] {
      color: var(--text);
      border-color: var(--border);
    }
    .account-trigger:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 1px;
    }
    /* Avatar — square ice-bordered block with the silhouette icon
       inside. Hover flips to solid-ice fill, mirroring the new chat
       button + active conv row pattern. */
    .account-avatar {
      display: inline-flex; align-items: center; justify-content: center;
      width: 1.65rem; height: 1.65rem;
      flex-shrink: 0;
      border-radius: var(--radius-chip);
      border: 1px solid var(--border);
      background: color-mix(in srgb, var(--accent) 8%, transparent);
      color: var(--accent-deep);
      transition: color .1s linear, border-color .1s linear,
                  background .1s linear;
    }
    [data-theme="terminal"] .account-avatar { color: var(--accent); }
    .account-avatar svg { width: 0.88rem; height: 0.88rem; }
    .account-trigger:hover .account-avatar,
    .account-trigger[aria-expanded="true"] .account-avatar {
      background: var(--accent);
      border-color: var(--border-strong);
      color: var(--accent-fg);
    }
    .account-email {
      flex: 1; min-width: 0;
      font-family: var(--font-chrome); font-size: 0.66rem;
      font-weight: 500;
      color: inherit;
      letter-spacing: 0;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .account-chevron {
      width: 0.78rem; height: 0.78rem;
      flex-shrink: 0;
      color: var(--text-faint);
      transition: transform .12s linear, color .1s linear;
    }
    .account-trigger[aria-expanded="true"] .account-chevron {
      transform: rotate(180deg);
      color: var(--accent-deep);
    }
    [data-theme="terminal"] .account-trigger[aria-expanded="true"] .account-chevron {
      color: var(--accent);
    }

    /* Menu pops UP from the trigger — terminal-style panel with sharp
       2px corners, ice border, mono labels. Absolutely-positioned
       elements anchor to their nearest positioned ancestor's PADDING
       edge, not its content edge, so left/right must match the
       sidebar-account's horizontal padding (0.45rem) to align with
       the trigger underneath. */
    .account-menu {
      position: absolute;
      bottom: calc(100% + 0.4rem);
      left: 0.45rem;
      right: 0.45rem;
      padding: 0.25rem;
      background: var(--glass-bg);
      backdrop-filter: blur(var(--backdrop-blur)) saturate(var(--backdrop-saturate));
      -webkit-backdrop-filter: blur(var(--backdrop-blur)) saturate(var(--backdrop-saturate));
      border: var(--border-width) solid var(--border);
      border-radius: var(--radius-chip);
      /* Drop shadow only — the outer accent ring that used to sit here
         was making the menu feel wider than its actual bounds and
         doubled the visual edge with the border underneath. */
      box-shadow: 0 8px 24px -4px rgba(0, 0, 0, 0.18);
      display: flex; flex-direction: column;
      gap: 0;
      z-index: 200;
      transform-origin: bottom left;
      animation: account-pop .12s ease-out;
    }
    @keyframes account-pop {
      from { opacity: 0; transform: translateY(4px); }
      to   { opacity: 1; transform: none; }
    }
    .account-item {
      display: inline-flex; align-items: center; gap: 0.55rem;
      padding: 0.5rem 0.6rem;
      background: transparent;
      border: 0;
      /* Base 3px transparent left border so hover/active states only
         change COLOR — matches the museum-label idiom used by
         .conv-item-wrap and avoids any 3px content shift. */
      border-left: 3px solid transparent;
      border-radius: 0;
      color: var(--text);
      font-family: var(--font-chrome);
      font-weight: 500;
      font-size: 0.7rem;
      letter-spacing: 0.06em;
      cursor: pointer;
      text-align: left;
      transition: background .1s linear, color .1s linear, border-color .1s linear;
    }
    .account-item:hover {
      background: color-mix(in srgb, var(--accent) 14%, transparent);
      border-left-color: var(--accent);
      color: var(--text);
    }
    .account-item:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: -2px;
    }
    .account-item-icon { width: 0.95rem; height: 0.95rem; flex-shrink: 0; }
    .account-item-label { line-height: 1; }
    /* Destructive item — hairline divider above visually separates it
       from the utility actions; danger-color hover instead of accent so
       the consequence is clear before clicking. Inset shadow draws the
       divider across the full menu width regardless of the transparent
       border-left. */
    .account-item-danger {
      margin-top: 0.25rem;
      padding-top: 0.6rem;
      box-shadow: inset 0 1px 0 var(--border);
    }
    .account-item-danger:hover {
      background: color-mix(in srgb, var(--danger) 14%, transparent);
      border-left-color: var(--danger);
      color: var(--danger);
    }
    .account-item-danger:focus-visible { outline-color: var(--danger); }
    /* ── conversation ────────────────────────────── */
    .conv {
      flex: 1; overflow-y: auto;
      padding: 2rem 1.6rem 1.2rem;
      display: flex; flex-direction: column;
      gap: 1.4rem;
      width: 100%; max-width: 860px; margin: 0 auto;
      scrollbar-width: thin;
      scrollbar-color: color-mix(in srgb, var(--accent) 35%, transparent) transparent;
    }
    .conv::-webkit-scrollbar { width: 6px; }
    .conv::-webkit-scrollbar-thumb {
      background: color-mix(in srgb, var(--accent) 35%, transparent);
      border-radius: 0;
    }
    .conv::-webkit-scrollbar { width: 10px; }
    .conv::-webkit-scrollbar-thumb {
      background: var(--border-strong); border-radius: 8px; border: 2px solid transparent;
      background-clip: content-box;
    }

    /* Center the greeting + subtitle as a single stack rather than
       distributing them across the empty space (grid place-items
       centers each row separately, which pushed the subtitle to the
       bottom). Flex column keeps the pair tight together at the
       optical middle of the viewport. */
    /* Terminal-prompt greeting — centered "fresh shell" feel with a
       mono headline and a "❯ {subtitle}▌" prompt line below it.
       Blinking cursor invites typing. */
    .empty {
      flex: 1;
      display: flex; flex-direction: column;
      align-items: center; justify-content: center;
      gap: 0.95rem;
      padding: 3rem 1.2rem;
      color: var(--text-faint); text-align: center;
      position: relative;
    }
    .empty h2 {
      font-family: var(--font-chrome);
      font-weight: 500;
      font-size: clamp(1.3rem, 3vw, 1.7rem);
      line-height: 1.25;
      letter-spacing: -0.01em;
      color: var(--text);
      margin: 0;
      max-width: 36rem;
    }
    /* The italic em from the JS becomes the ice-accent emphasis word —
       still distinguished, but in mono rather than serif italic. */
    .empty h2 em {
      font-style: normal;
      color: var(--accent-deep);
      font-weight: 600;
    }
    [data-theme="terminal"] .empty h2 em { color: var(--accent); }
    /* Subtitle becomes the terminal prompt with a blinking caret. The
       caret sits inline at the end so it reads as "your turn to type". */
    .empty .greeting-sub {
      font-family: var(--font-chrome);
      font-size: clamp(0.78rem, 1.5vw, 0.88rem);
      color: var(--text-dim);
      margin: 0;
      letter-spacing: 0;
      display: inline-flex; align-items: center;
    }
    /* Cursor at the end of the greeting subtitle — terminal-only. */
    [data-theme="terminal"] .empty .greeting-sub::after {
      content: "▌";
      color: var(--accent);
      margin-left: 0.05rem;
      animation: cursor-blink 1.05s steps(2, start) infinite;
    }

    /* Messages — terminal blocks with mono header strips. Sharp 2px
       corners, thin ice/ink left-border accent so user vs assistant
       reads at a glance, no shadows (terminal panels don't float).
       Arrival animation is asymmetric by sender — user messages snap
       in fast (decisive, no second-guessing the send), assistant
       messages rise slowly with a brief delay (considered, "thinking
       → speaking" rhythm). */
    .msg {
      max-width: 100%;
      position: relative;
    }
    .msg.user {
      animation: rise-user .18s cubic-bezier(.4, 0, .2, 1) both;
    }
    .msg.assistant {
      animation: rise .42s cubic-bezier(.2, .7, .2, 1) both;
      animation-delay: 80ms;
    }
    @keyframes rise {
      from { opacity: 0; transform: translateY(6px); }
      to   { opacity: 1; transform: none; }
    }
    @keyframes rise-user {
      from { opacity: 0; transform: translateY(4px) scale(.985); }
      to   { opacity: 1; transform: none; }
    }
    /* Default = BUBBLES. Filled accent for user, soft cool gray for
       assistant. Big asymmetric radius — one corner near the sender's
       side stays small (4px) so the bubble "leans" toward its
       speaker, the rest are pill-rounded (18px). No borders. */
    .msg.user {
      align-self: flex-end;
      background: var(--accent);
      /* Text-on-accent — most accents are saturated colors that want
         white text. Light accents (white / light gray) override
         --accent-fg in their [data-accent] block to use dark text instead. */
      color: var(--accent-fg, #ffffff);
      border: none;
      /* TL TR BR BL — bottom-right corner small (leans toward user side) */
      border-radius: 18px 18px 4px 18px;
      padding: 0.75rem 1.1rem;
      max-width: 80%;
    }
    .msg.user .msg-body { color: inherit; }
    [data-theme="terminal"] .msg.user {
      background: color-mix(in srgb, var(--surface) 50%, transparent);
      border-right-color: var(--border-strong);
    }
    /* Mono "you" label above the body, right-aligned. The leading `<`
       reads "outgoing from us" — message leaving our side of the
       terminal, headed to alyx. */
    .msg.user::before {
      content: "you";
      display: block;
      font-family: var(--font-chrome);
      font-weight: 600;
      font-size: 0.55rem;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      color: var(--accent-deep);
      margin-bottom: 0.35rem;
      text-align: right;
    }
    [data-theme="terminal"] .msg.user::before { color: var(--accent); }

    /* Live-preview bubble in voice mode — shows what's being transcribed
       before the turn is actually sent. Different label + a dashed
       border so it reads as "in progress, not committed yet". */
    .msg.user.preview {
      border-style: dashed;
      border-color: color-mix(in srgb, var(--border-strong) 55%, var(--border));
      border-right: 2px dashed var(--border);
      background: color-mix(in srgb, var(--accent) 6%, var(--surface));
      color: var(--text);
      animation: rise .25s cubic-bezier(.2,.7,.2,1) both;
    }
    .msg.user.preview::before {
      content: "draft";
      color: color-mix(in srgb, var(--accent-deep) 75%, transparent);
    }
    [data-theme="terminal"] .msg.user.preview::before {
      color: color-mix(in srgb, var(--accent) 75%, transparent);
    }
    /* Live caret on the draft so it reads as still being captured. */
    .msg.user.preview .msg-body::after {
      content: "";
      display: inline-block;
      width: 6px; height: 6px; border-radius: 50%;
      margin-left: 0.35em;
      vertical-align: middle;
      background: var(--accent-deep);
      animation: cursor-pulse-soft 1.1s ease-in-out infinite;
    }
    /* Terminal swaps the soft pulsing dot for the blinking █ cursor. */
    [data-theme="terminal"] .msg.user.preview .msg-body::after {
      content: "▌";
      width: auto; height: auto;
      background: transparent;
      border-radius: 0;
      color: var(--accent);
      margin-left: 0.1rem;
      animation: cursor-blink 1.05s steps(2, start) infinite;
    }
    .msg.user.preview .msg-body {
      font-style: normal;
      color: var(--text);
    }
    [data-theme="terminal"] .msg.user.preview {
      background: color-mix(in srgb, var(--accent) 8%, var(--surface));
    }
    /* Assistant turns — sharp block, ice-left-border accent so the eye
       can quickly distinguish from user turns. Same color as active
       conv item in the sidebar (ice) so the system reads coherent. */
    .msg.assistant {
      align-self: flex-start;
      background: var(--surface-2);
      color: var(--text);
      border: none;
      /* Bottom-left corner small (leans toward assistant side). */
      border-radius: 18px 18px 18px 4px;
      padding: 0.8rem 1.15rem;
      max-width: 92%;
    }
    [data-theme="terminal"] .msg.assistant { border-left-color: var(--border-strong); }
    /* "Alyx" attribution label above the message body, suffixed with
       the broker-announced kind (CODE / MED / CHAT) via attr(data-kind)
       — see addAssistantPlaceholder() + the `kind` SSE handler. The
       default kind on a fresh placeholder is "CHAT" so the chip never
       reads "ALYX · " with a trailing dot before the event lands. */
    .msg.assistant::before {
      content: "Alyx • " attr(data-kind);
      display: block;
      font-family: var(--font-chrome);
      font-weight: 600;
      font-size: 0.55rem;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      color: var(--accent-deep);
      margin-bottom: 0.45rem;
    }
    [data-theme="terminal"] .msg.assistant::before {
      color: var(--accent);
      content: "alyx";
    }
    .msg-body {
      white-space: pre-wrap; word-wrap: break-word;
      color: var(--text);
    }
    /* Markdown-rendered assistant content. Once marked + DOMPurify run on
       the final text the .msg-body becomes a small document; these rules
       keep block elements tight inside a chat bubble and respect the
       same palette as the rest of the UI. */
    .msg.assistant .msg-body { white-space: normal; }
    .msg-body > :first-child { margin-top: 0; }
    .msg-body > :last-child  { margin-bottom: 0; }
    .msg-body p { margin: 0 0 0.7em; line-height: 1.55; }
    .msg-body strong { font-weight: 700; color: var(--text); }
    .msg-body em { font-style: italic; }
    .msg-body a {
      color: var(--accent-deep); text-decoration: underline;
      text-underline-offset: 2px;
    }
    .msg-body a:hover { color: var(--accent); }
    .msg-body h1, .msg-body h2, .msg-body h3, .msg-body h4 {
      font-family: var(--display);
      font-variation-settings: "opsz" 36, "SOFT" 60, "wght" 500;
      letter-spacing: -0.012em;
      line-height: 1.2;
      margin: 0.9em 0 0.4em;
    }
    .msg-body h1 { font-size: 1.4rem; }
    .msg-body h2 { font-size: 1.2rem; }
    .msg-body h3 { font-size: 1.05rem; }
    .msg-body h4 { font-size: 0.95rem; }
    .msg-body ul, .msg-body ol {
      margin: 0.3em 0 0.8em;
      padding-left: 1.5em;
    }
    .msg-body li { margin: 0.18em 0; }
    .msg-body li > p { margin: 0; }
    .msg-body code {
      font-family: var(--mono); font-size: 0.86em;
      background: color-mix(in srgb, var(--accent) 8%, transparent);
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      padding: 0.06em 0.36em;
    }
    .msg-body pre {
      font-family: var(--mono); font-size: 0.85em;
      background: color-mix(in srgb, var(--text) 4%, transparent);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      padding: 0.8em 0.95em;
      margin: 0.6em 0 0.9em;
      overflow-x: auto;
      line-height: 1.5;
      position: relative;
      /* Size to the widest content line instead of stretching to full
         bubble width — keeps short snippets / ASCII art compact
         instead of leaving a giant empty rectangle. Capped at 100% so
         genuinely wide content (long lines, code) still scrolls
         horizontally rather than blowing out the layout. */
      width: max-content;
      max-width: 100%;
    }
    /* Top-right copy button — injected by decorateCodeBlocks() after
       every markdown render. Hidden until pre hover so it doesn't
       clutter the read state; pre keeps padding-top room so the
       button doesn't sit on top of the first line of code. */
    .msg-body pre .code-copy {
      position: absolute;
      top: 0.4em; right: 0.5em;
      font-family: var(--font-chrome);
      font-weight: 700;
      font-size: 0.62em;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      color: var(--accent-deep);
      background: color-mix(in srgb, var(--bg) 65%, transparent);
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      padding: 0.28em 0.6em;
      cursor: pointer;
      opacity: 0;
      transition: opacity .12s linear, color .1s linear,
                  background .1s linear, border-color .1s linear;
      z-index: 2;
    }
    [data-theme="terminal"] .msg-body pre .code-copy {
      color: var(--accent);
      background: color-mix(in srgb, var(--surface) 55%, transparent);
    }
    .msg-body pre:hover .code-copy,
    .msg-body pre:focus-within .code-copy { opacity: 1; }
    .msg-body pre .code-copy:hover {
      color: var(--accent-fg);
      background: var(--accent);
      border-color: var(--border-strong);
    }
    .msg-body pre .code-copy.copied {
      color: var(--success);
      border-color: var(--success);
      background: color-mix(in srgb, var(--success) 10%, transparent);
      opacity: 1;
    }
    /* Touch — no hover, always show. */
    @media (hover: none) and (pointer: coarse) {
      .msg-body pre .code-copy { opacity: 0.85; }
    }
    .msg-body pre code {
      background: none; border: none; padding: 0;
      font-size: inherit;
    }
    .msg-body blockquote {
      border-left: 2px solid var(--border-strong);
      padding: 0.05em 0.9em;
      margin: 0.6em 0;
      color: var(--text-dim);
      background: color-mix(in srgb, var(--accent) 6%, transparent);
      border-radius: 0;
    }
    [data-theme="terminal"] .msg-body blockquote { border-left-color: var(--border-strong); }
    .msg-body blockquote > :last-child { margin-bottom: 0; }
    .msg-body hr {
      border: none; height: 1px; background: var(--border);
      margin: 1em 0;
    }
    .msg-body table {
      border-collapse: collapse;
      margin: 0.6em 0 0.8em;
      font-size: 0.92em;
      width: auto; max-width: 100%;
    }
    .msg-body th, .msg-body td {
      border: 1px solid var(--border);
      padding: 0.32em 0.65em;
      text-align: left;
    }
    .msg-body th {
      background: var(--surface-2);
      font-weight: 600;
    }

    /* Inline citation anchors — the [N] that the model writes inside
       sentences becomes a clickable link with a custom hover tooltip
       showing the source title + host. The bracketed brackets stay as
       plain text. */
    .msg-body a.cite {
      position: relative;            /* anchor for .cite-tooltip */
      text-decoration: none;
      color: var(--accent-deep);
      font-weight: 600;
      font-size: 0.86em;
      vertical-align: 0.06em;
      padding: 0 0.06em;
      cursor: pointer;
    }
    .msg-body a.cite:hover,
    .msg-body a.cite:focus-visible {
      color: var(--accent);
      text-decoration: underline;
      text-underline-offset: 2px;
    }
    /* Tooltip — hidden by default, fades in on hover. pointer-events
       are off so the tooltip itself never steals the hover state from
       the citation underneath. */
    .cite-tooltip {
      position: absolute;
      bottom: calc(100% + 0.45em);
      left: 50%;
      transform: translateX(-50%) translateY(4px);
      min-width: 12rem;
      max-width: 22rem;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      padding: 0.55rem 0.7rem;
      box-shadow:
        0 0 0 1px color-mix(in srgb, var(--accent) 8%, transparent),
        0 12px 28px -10px rgba(13, 28, 46, 0.28);
      font-family: var(--body);
      font-style: normal;
      font-weight: 400;
      font-size: 0.78rem;
      letter-spacing: 0;
      line-height: 1.4;
      color: var(--text);
      text-align: left;
      pointer-events: none;
      opacity: 0;
      visibility: hidden;
      transition: opacity .12s ease, transform .12s ease, visibility 0s linear .12s;
      /* High enough to escape every other stacking context (sidebar
         backdrop-filter context, composer-wrap z:5, sidebar-show z:80,
         account-menu z:200, lightbox z:1000, modals z:1100/1200). */
      z-index: 1300;
      white-space: normal;
    }
    .msg-body a.cite:hover .cite-tooltip,
    .msg-body a.cite:focus-visible .cite-tooltip {
      opacity: 1;
      visibility: visible;
      transform: translateX(-50%) translateY(0);
      transition: opacity .12s ease, transform .12s ease;
    }
    /* Arrow below the tooltip pointing to the citation */
    .cite-tooltip::after {
      content: "";
      position: absolute;
      top: 100%; left: 50%;
      transform: translateX(-50%);
      border: 5px solid transparent;
      border-top-color: var(--border);
    }
    .cite-tooltip::before {
      content: "";
      position: absolute;
      top: calc(100% - 1px); left: 50%;
      transform: translateX(-50%);
      border: 4px solid transparent;
      border-top-color: var(--surface);
    }
    .cite-tooltip .tip-title {
      display: block;
      color: var(--text);
      font-weight: 600;
      margin: 0 0 0.18em;
    }
    .cite-tooltip .tip-host {
      display: block;
      font-family: var(--font-chrome);
      font-size: 0.66rem;
      letter-spacing: 0.04em;
      color: var(--text-faint);
    }

    /* Citation footer for med answers — surfaces the trusted-source
       URLs the broker injected as RAG context. */
    .msg-sources {
      margin-top: 0.9rem;
      padding-top: 0.6rem;
      border-top: 1px solid var(--border);
    }
    .msg-sources-header {
      font-family: var(--font-chrome); font-size: 0.6rem;
      font-weight: 600;
      letter-spacing: 0.22em; text-transform: uppercase;
      color: var(--accent-deep);
      margin-bottom: 0.45rem;
    }
    [data-theme="terminal"] .msg-sources-header { color: var(--accent); }
    /* Terminal-only `//` comment prefix on the SOURCES heading. */
    [data-theme="terminal"] .msg-sources-header::before {
      content: "// ";
      opacity: 0.6;
    }
    .msg-sources-list {
      margin: 0;
      padding: 0;
      list-style: none;
      counter-reset: src;
      display: flex; flex-direction: column; gap: 0.18rem;
    }
    .msg-sources-list li {
      counter-increment: src;
      display: flex;
      align-items: baseline;
      gap: 0.45em;
      font-size: 0.84rem;
      line-height: 1.4;
    }
    .msg-sources-list li::before {
      content: "[" counter(src) "]";
      font-family: var(--font-chrome);
      font-size: 0.7rem;
      color: var(--text-faint);
      flex: 0 0 auto;
    }
    .msg-sources-list a {
      color: var(--accent-deep);
      text-decoration: none;
    }
    .msg-sources-list a:hover {
      color: var(--accent);
      text-decoration: underline;
      text-underline-offset: 2px;
    }

    /* highlight.js theme using palette variables — one source of truth
       for both light and dark; no second stylesheet to swap. */
    .msg-body .hljs { color: var(--text); background: transparent; padding: 0; }
    .msg-body .hljs-comment,
    .msg-body .hljs-quote        { color: var(--text-faint); font-style: italic; }
    .msg-body .hljs-keyword,
    .msg-body .hljs-selector-tag,
    .msg-body .hljs-section,
    .msg-body .hljs-link         { color: var(--accent-deep); font-weight: 600; }
    .msg-body .hljs-string,
    .msg-body .hljs-attr,
    .msg-body .hljs-symbol,
    .msg-body .hljs-bullet       { color: var(--success); }
    .msg-body .hljs-number,
    .msg-body .hljs-literal,
    .msg-body .hljs-deletion     { color: var(--warning); }
    .msg-body .hljs-title,
    .msg-body .hljs-name,
    .msg-body .hljs-tag,
    .msg-body .hljs-selector-id,
    .msg-body .hljs-selector-class { color: var(--danger); }
    .msg-body .hljs-built_in,
    .msg-body .hljs-type,
    .msg-body .hljs-class,
    .msg-body .hljs-addition     { color: var(--accent); }
    .msg-body .hljs-variable,
    .msg-body .hljs-template-variable,
    .msg-body .hljs-params       { color: var(--text-dim); }
    .msg-body .hljs-meta,
    .msg-body .hljs-meta-keyword { color: var(--text-faint); }
    .msg-body .hljs-emphasis     { font-style: italic; }
    .msg-body .hljs-strong       { font-weight: 700; }
    /* Legacy msg-meta — hidden; the assistant label now comes from
       .msg.assistant::before. Kept the rule (display: none) instead of
       ripping it out of the JS callers to avoid breaking other paths
       that still build .msg-meta (e.g. potential future type-tag uses).
       If we add type tagging back later, swap this for a real layout. */
    .msg-meta { display: none; }
    .msg-meta .type-tag.med    { color: var(--success); }
    .msg-meta .type-tag.scribe { color: var(--warning); }

    /* Streaming indicator appended to in-flight assistant messages.
       Non-terminal themes get a soft pulsing dot (refined / universal);
       terminal keeps the blinking █ block for the on-brand feel. */
    .cursor {
      display: inline-block;
      width: 7px; height: 7px;
      background: var(--accent-deep);
      border-radius: 50%;
      vertical-align: middle;
      margin: 0 0 0.1em 0.35em;
      animation: cursor-pulse-soft 1.1s ease-in-out infinite;
    }
    [data-theme="terminal"] .cursor {
      width: 0.5em; height: 1em;
      border-radius: 0;
      background: var(--accent);
      vertical-align: text-bottom;
      margin: 0 0 0 1px;
      animation: blink 1s steps(2, start) infinite;
    }
    @keyframes blink { 50% { opacity: 0; } }
    @keyframes cursor-pulse-soft {
      0%, 100% { opacity: 0.35; transform: scale(0.85); }
      50%      { opacity: 1;    transform: scale(1); }
    }

    /* Pre-stream status — what the broker is doing while it's not yet
       emitting tokens (searching, fetching sources, dispatching). Mono
       comment style with animated dots so it reads like a process log. */
    .phase {
      font-family: var(--font-chrome);
      font-style: normal;
      font-size: 0.78rem;
      color: var(--accent-deep);
      opacity: 0.9;
    }
    [data-theme="terminal"] .phase { color: var(--accent); }
    /* Terminal-only `//` comment prefix on phase ("Drafting response…"
       and friends). Other themes show the phase text plain. */
    [data-theme="terminal"] .phase::before {
      content: "// ";
      opacity: 0.6;
    }
    .phase .dots::after {
      content: "";
      display: inline-block;
      animation: phase-dots 1.4s steps(4, end) infinite;
    }
    @keyframes phase-dots {
      0%   { content: ""; }
      25%  { content: "."; }
      50%  { content: ".."; }
      75%  { content: "..."; }
      100% { content: ""; }
    }

    .err {
      align-self: flex-start;
      color: var(--danger);
      font-family: var(--font-chrome); font-size: 0.74rem;
      background: color-mix(in srgb, var(--danger) 8%, transparent);
      border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent);
      border-left: 2px solid var(--danger);
      border-radius: var(--radius-chip);
      padding: 0.55rem 0.85rem;
      max-width: 92%;
    }
    .err::before {
      content: "Error  ";
      font-weight: 700;
      letter-spacing: 0.16em;
      text-transform: uppercase;
      opacity: 0.75;
    }
    [data-theme="terminal"] .err::before { content: "// error  "; }

    /* ── composer ──────────────────────────────── */
    /* Composer-wrap is pulled out of flow and pinned to the bottom of
       the main column, so the conv area extends behind it. A gradient
       fade (transparent → background color) on the wrap lets bubbles
       scroll up "into" the composer's area and dissolve gracefully
       rather than abruptly meeting the composer's edge. The conv
       area's padding-bottom is set in JS to keep the bottom message
       from being hidden under the composer (adapts to multi-line
       textarea growth via ResizeObserver). */
    .composer-wrap {
      position: absolute;
      bottom: 0; left: 0; right: 0;
      padding: 1.6rem 1.6rem 1.4rem;
      background: linear-gradient(to bottom,
        transparent 0%,
        color-mix(in srgb, var(--bg) 50%, transparent) 35%,
        color-mix(in srgb, var(--bg) 88%, transparent) 75%,
        var(--bg) 100%);
      /* Pointer events pass through the transparent gradient zone so
         the user can scroll the conv by touching it; the composer
         itself re-enables pointer events below. */
      pointer-events: none;
      z-index: 5;
    }
    .composer-wrap > * { pointer-events: auto; }
    /* Composer — sharp terminal input panel. 2px corners, ice border,
       no float shadow. */
    .composer {
      width: 100%; max-width: 860px; margin: 0 auto;
      background: var(--glass-bg);
      backdrop-filter: blur(var(--backdrop-blur)) saturate(var(--backdrop-saturate));
      -webkit-backdrop-filter: blur(var(--backdrop-blur)) saturate(var(--backdrop-saturate));
      border: var(--border-width) solid var(--border);
      border-radius: var(--radius-chip);
      padding: 0.7rem 0.7rem 0.5rem 0.85rem;
      position: relative;
      transition: border-color .15s linear, box-shadow .15s linear;
    }

    /* ── Voice mode: composer mic-activity halo ──
       Single soft breathing layer driven entirely by --mic-level
       (0..1, JS-driven from the audio meter). The composer's accent
       glow blooms outward in proportion to voice; at silence it's
       just the bare border ring. Quiet, atmospheric — registered
       as @property below so the JS-set value interpolates smoothly. */
    @property --mic-level {
      syntax: '<number>';
      inherits: true;
      initial-value: 0;
    }
    .composer.voice-on {
      border-color: var(--accent-deep);
      box-shadow:
        0 0 0 1px var(--accent-deep),
        0 0 calc(var(--mic-level, 0) * 32px)
          color-mix(in srgb, var(--accent) calc(var(--mic-level, 0) * 55%), transparent),
        inset 0 0 calc(var(--mic-level, 0) * 18px)
          color-mix(in srgb, var(--accent) calc(var(--mic-level, 0) * 18%), transparent);
    }

    /* Status caption above the composer was removed — the input's own
       placeholder already swaps to "Listening…" / "Not listening…" via
       refreshSendButton(), so the floating tag was redundant. */

    /* Muted — mic is hot but silent. Per-theme treatment so light reads
       calm-and-refined while terminal keeps its harder rose pulse. */

    /* LIGHT muted: very gentle rose-tinted border, opacity breathes
       slowly. No hard color flicker. */
    .composer.voice-on.muted {
      border-color: color-mix(in srgb, var(--danger) 70%, transparent);
      box-shadow:
        0 0 0 1px color-mix(in srgb, var(--danger) 65%, transparent),
        0 0 18px color-mix(in srgb, var(--danger) 14%, transparent);
      animation: composer-muted-breath-soft 4s ease-in-out infinite;
    }
    @keyframes composer-muted-breath-soft {
      0%, 100% { box-shadow:
        0 0 0 1px color-mix(in srgb, var(--danger) 50%, transparent),
        0 0 14px color-mix(in srgb, var(--danger) 10%, transparent);
      }
      50%      { box-shadow:
        0 0 0 1px color-mix(in srgb, var(--danger) 80%, transparent),
        0 0 22px color-mix(in srgb, var(--danger) 22%, transparent);
      }
    }

    /* TERMINAL muted: sharper rose pulse — discrete border flip rather
       than opacity drift. Reads as "warning indicator", on-brand. */
    [data-theme="terminal"] .composer.voice-on.muted {
      border-color: var(--danger);
      box-shadow:
        0 0 0 1px var(--danger),
        0 0 0.5rem color-mix(in srgb, var(--danger) 30%, transparent);
      animation: composer-breath-muted 3.2s ease-in-out infinite;
    }
    @keyframes composer-breath-muted {
      0%, 100% { border-color: color-mix(in srgb, var(--danger) 70%, transparent); }
      50%      { border-color: var(--danger); }
    }

    /* Drag-and-drop overlay — terminal "drop files" instruction. */
    .composer.dragging,
    .composer.voice-on.dragging {
      animation: none;
      border-color: var(--border-strong);
      box-shadow:
        0 0 0 2px var(--accent),
        0 0 1rem color-mix(in srgb, var(--accent) 40%, transparent);
    }
    .composer.dragging::before {
      content: "Drop files to attach";
      position: absolute;
      inset: 0;
      display: grid;
      place-items: center;
      font-family: var(--font-chrome);
      font-weight: 700;
      font-size: 0.7rem;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      color: var(--accent-deep);
      background: color-mix(in srgb, var(--bg) 85%, transparent);
      backdrop-filter: blur(8px);
      border-radius: var(--radius-chip);
      pointer-events: none;
      z-index: 2;
    }
    [data-theme="terminal"] .composer.dragging::before {
      content: "// drop files to attach";
      color: var(--accent);
      background: color-mix(in srgb, var(--bg) 78%, transparent);
    }

    .input-row {
      display: flex; align-items: flex-end; gap: 0.55rem;
    }
    .input {
      flex: 1; font-family: var(--body); font-size: 0.95rem;
      color: var(--text);
      background: transparent;
      border: none; outline: none;
      resize: none;
      /* exact 2.4rem (38.4 px) when empty so chat row matches scribe row.
         content height at 1 line = 0.95rem × 1.55 = 23.56 px; padding 7.4 px
         each side fills out to 38.4 px without overshooting. autosize()
         grows past this when the user types multi-line. */
      min-height: 2.4rem;
      max-height: 24rem;
      line-height: 1.55;
      padding: 0.4625rem 0.2rem;   /* 7.4 px top/bottom */
    }
    /* The composer itself already signals focus via its own border +
       voice-on glow; the global --focus-ring on the textarea piles a
       second box-shadow on top, which reads as a hard outline around
       the input. Suppress it specifically on .input. */
    .input:focus,
    .input:focus-visible {
      box-shadow: none;
      outline: none;
    }
    /* Mono placeholder so the empty input reads like a shell prompt. */
    .input::placeholder {
      color: var(--text-faint);
      font-family: var(--font-chrome);
      font-size: 0.85rem;
      letter-spacing: 0;
    }
    /* Action button — one element, five visual modes (send / speak /
       mute-on / mute-off / stop). Sharp 2px corners, bright cyan fill.
       Foreground uses var(--bg) which inverts across themes — white
       in light, dark in dark — so contrast is theme-native both ways.
       Hover adds an outer ice glow ring. */
    .send {
      font-family: var(--font-chrome); font-weight: 700;
      font-size: 0.62rem;
      letter-spacing: 0.24em;
      text-transform: uppercase;
      color: var(--accent-fg);
      background: var(--accent);
      border: 1px solid var(--border-strong);
      border-radius: var(--radius-chip);
      /* Icon-only button — symmetric padding + square aspect via
         min-width matching the height. */
      padding: 0;
      height: 2.4rem;
      min-width: 2.4rem;
      cursor: pointer;
      transition: background .1s linear, border-color .1s linear,
                  color .1s linear, transform .08s linear,
                  box-shadow .1s linear;
      display: inline-flex; align-items: center; justify-content: center;
      position: relative;
    }
    .send:hover {
      box-shadow: 0 0 14px -2px color-mix(in srgb, var(--accent) 60%, transparent);
    }
    [data-theme="terminal"] .send:hover {
      box-shadow: 0 0 16px -2px color-mix(in srgb, var(--accent) 70%, transparent);
    }
    .send:active { transform: translateY(1px); }
    .send:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }
    .send:disabled { opacity: 0.5; cursor: wait; transform: none; }

    /* Icon variants: show the matching inline svg per mode. Four modes
       — text (paper-plane), speak (waveform), end-voice (X), stop
       (square). Mute lives separately as its own button. */
    .send .send-icon { display: none; width: 1.1rem; height: 1.1rem; }
    .send.mode-text       .icon-text       { display: block; }
    .send.mode-speak      .icon-speak      { display: block; }
    .send.mode-end-voice  .icon-end-voice  { display: block; }
    .send.mode-stop       .icon-stop       { display: block; }

    /* End-voice and Stop — sharp solid rose. Both are "back out of this
       state" actions; distinct icons (X vs square) keep the meaning
       clear. Hover gains an outward rose glow ring. */
    .send.mode-end-voice,
    .send.mode-stop,
    .send.stop {
      background: var(--danger);
      border-color: var(--danger);
      color: var(--surface);
      box-shadow: none;
    }
    [data-theme="terminal"] .send.mode-end-voice,
    [data-theme="terminal"] .send.mode-stop,
    [data-theme="terminal"] .send.stop {
      color: var(--accent-fg);
    }
    .send.mode-end-voice:hover,
    .send.mode-stop:hover,
    .send.stop:hover {
      background: var(--danger);
      border-color: var(--danger);
      box-shadow: 0 0 14px -2px color-mix(in srgb, var(--danger) 60%, transparent);
    }
    .send.mode-end-voice:focus-visible,
    .send.mode-stop:focus-visible,
    .send.stop:focus-visible { outline-color: var(--danger); }

    /* ── left-slot buttons ──────────────────────
       The left slot of the input row is contextual: attach paperclip
       in text mode, mute toggle in voice mode. Both share dimensions
       so the textarea position never jumps when voice mode flips. */
    .attach {
      display: inline-flex; align-items: center; justify-content: center;
      flex-shrink: 0;
      width: 2.4rem; height: 2.4rem;
      padding: 0;
      color: var(--accent-deep);
      background: transparent;
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      cursor: pointer;
      transition: color .1s linear, background .1s linear,
                  border-color .1s linear;
    }
    [data-theme="terminal"] .attach { color: var(--accent); }
    .attach:hover {
      color: var(--accent-fg);
      border-color: var(--border-strong);
      background: var(--accent);
    }
    .attach:active { transform: translateY(1px); }
    .attach:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }
    .attach svg { width: 1rem; height: 1rem; }
    /* Hide attach in voice mode — mute takes its place. */
    .composer.voice-on .attach { display: none; }

    .mute-btn {
      display: none;                 /* CSS shows it when voice mode is on */
      align-items: center; justify-content: center;
      flex-shrink: 0;
      width: 2.4rem; height: 2.4rem;
      padding: 0;
      color: var(--accent-deep);
      background: transparent;
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      cursor: pointer;
      transition: color .1s linear, background .1s linear,
                  border-color .1s linear;
    }
    [data-theme="terminal"] .mute-btn { color: var(--accent); }
    .composer.voice-on .mute-btn { display: inline-flex; }
    .mute-btn:hover {
      color: var(--accent-fg);
      border-color: var(--border-strong);
      background: var(--accent);
    }
    .mute-btn:active { transform: translateY(1px); }
    .mute-btn:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }
    .mute-btn svg { width: 1rem; height: 1rem; }
    .mute-btn .icon-mic-muted { display: none; }
    /* Muted state — switch to rose. */
    .composer.muted .mute-btn {
      color: var(--danger);
      border-color: color-mix(in srgb, var(--danger) 55%, transparent);
    }
    .composer.muted .mute-btn:hover {
      color: var(--accent-fg);
      background: var(--danger);
      border-color: var(--danger);
    }
    .composer.muted .mute-btn .icon-mic { display: none; }
    .composer.muted .mute-btn .icon-mic-muted { display: block; }
    .composer.muted .mute-btn:focus-visible { outline-color: var(--danger); }

    /* Attachment previews — small thumbnails above the input row. */
    .attachments {
      display: flex; flex-wrap: wrap; gap: 0.5rem;
      margin-bottom: 0.55rem;
      padding-bottom: 0.55rem;
      border-bottom: 1px dashed var(--border);
    }
    .attachment {
      position: relative;
      width: 3.2rem; height: 3.2rem;
      border-radius: var(--radius-chip);
      overflow: hidden;
      border: 1px solid var(--border);
      background: color-mix(in srgb, var(--surface-2) 60%, transparent);
    }
    .attachment img {
      width: 100%; height: 100%; object-fit: cover; display: block;
    }
    .attachment .remove {
      position: absolute; top: 2px; right: 2px;
      width: 1.1rem; height: 1.1rem;
      display: flex; align-items: center; justify-content: center;
      background: rgba(13, 28, 46, 0.78);
      color: white;
      border: none; border-radius: var(--radius-chip);
      cursor: pointer;
      font-size: 0.7rem; line-height: 1;
      padding: 0;
    }
    .attachment .remove:hover { background: var(--danger); }

    /* Document + audio chips: rectangular, taller-than-wide doesn't
       work for a file with a long name, so use a horizontal pill that
       grows to fit the filename (but caps). */
    .attachment.file {
      width: auto; height: 3.2rem;
      max-width: 14rem;
      padding: 0.3rem 1.6rem 0.3rem 0.55rem;
      display: flex; align-items: center; gap: 0.5rem;
      background: color-mix(in srgb, var(--surface-2) 60%, transparent);
    }
    .attachment.file.pending { opacity: 0.55; }
    .attachment .file-icon {
      width: 1.6rem; height: 1.6rem;
      display: flex; align-items: center; justify-content: center;
      color: var(--warning);
      flex-shrink: 0;
    }
    .attachment .file-icon svg { width: 1.3rem; height: 1.3rem; }
    .attachment .file-info { min-width: 0; line-height: 1.15; }
    .attachment .file-name {
      font-family: var(--font-chrome);
      font-size: 0.78rem;
      color: var(--text);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .attachment .file-meta {
      font-family: var(--font-chrome);
      font-size: 0.65rem;
      color: var(--text-faint);
      text-transform: uppercase;
      letter-spacing: 0.04em;
    }

    /* Inline chips inside the user message bubble — same shape, smaller. */
    .msg.user .msg-attachments .file-chip {
      display: inline-flex; align-items: center; gap: 0.35rem;
      padding: 0.18rem 0.55rem;
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      background: color-mix(in srgb, var(--accent) 6%, transparent);
      font-family: var(--font-chrome);
      font-size: 0.72rem;
      color: var(--text);
      max-width: 14rem;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .msg.user .msg-attachments .file-chip svg {
      width: 0.9rem; height: 0.9rem;
      color: var(--warning);
      flex-shrink: 0;
    }

    /* User message bubble shows attached image thumbnails inline. */
    .msg.user .msg-attachments {
      display: flex; flex-wrap: wrap; gap: 0.35rem;
      margin-bottom: 0.4rem;
    }
    /* Attachment-only bubble (no typed text): drop the gap to the body. */
    .msg.user .msg-attachments:last-child { margin-bottom: 0; }
    .msg.user .msg-attachments img {
      width: 4rem; height: 4rem;
      object-fit: cover;
      border-radius: var(--radius-chip);
      border: 1px solid var(--border);
    }

    @keyframes pulse {
      0%, 100% { opacity: 0.6; transform: scale(0.85); }
      50%      { opacity: 1;   transform: scale(1.1);  }
    }

    /* Lightbox — backdrop fills the entire viewport. The image is
       centered, sized to its natural aspect ratio capped at the
       viewport bounds. Clicking the area around the image lands on
       the backdrop (.lightbox) and closes the modal. */
    .lightbox {
      position: fixed; inset: 0; z-index: 1000;
      width: 100vw; height: 100vh;
      background: rgba(0, 0, 0, 0.92);
      backdrop-filter: blur(10px);
      -webkit-backdrop-filter: blur(10px);
      display: grid;
      place-items: center;
      cursor: zoom-out;
      opacity: 0;
      transition: opacity .15s ease;
    }
    .lightbox.open { opacity: 1; }
    .lightbox-img {
      max-width: 100vw;
      max-height: 100vh;
      display: block;
      cursor: default;
    }
    .lightbox-close {
      position: absolute; top: 1.1rem; right: 1.4rem;
      width: 2.4rem; height: 2.4rem;
      display: inline-flex; align-items: center; justify-content: center;
      background: transparent;
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      color: white;
      font-family: var(--font-chrome); font-weight: 600; font-size: 0.95rem;
      cursor: pointer;
      transition: background .1s linear, border-color .1s linear,
                  color .1s linear;
      z-index: 1;                     /* sit above the image */
    }
    .lightbox-close:hover {
      background: var(--accent);
      border-color: var(--border-strong);
      color: var(--text);
    }
    /* Mark thumbnails as clickable in both spots. */
    .msg.user .msg-attachments img,
    .attachment img {
      cursor: zoom-in;
    }

    /* ── API keys modal ─────────────────────────────────
       Terminal-styled overlay: full-viewport dim, panel centered with
       sharp ice border, all mono. */
    .keys-modal {
      position: fixed; inset: 0; z-index: 1100;
      display: none;
      align-items: center; justify-content: center;
      padding: 1.5rem;
      background: rgba(0, 0, 0, 0.55);
      backdrop-filter: blur(6px);
      -webkit-backdrop-filter: blur(6px);
      animation: keys-modal-fade .14s ease-out;
    }
    .keys-modal.open { display: flex; }
    @keyframes keys-modal-fade {
      from { opacity: 0; }
      to   { opacity: 1; }
    }
    /* Inner-panel rise: paired with the backdrop fade above, the
       panel surfaces from below rather than just appearing. Same
       duration, different motion — backdrop fades while panel rises.
       Applied to all three modal panel idioms. */
    @keyframes modal-panel-rise {
      from { opacity: 0; transform: translateY(8px); }
      to   { opacity: 1; transform: none; }
    }
    .keys-modal.open .keys-modal-panel,
    .theme-chooser-modal.open .theme-chooser-panel,
    .confirm-modal.open .confirm-modal-panel {
      animation: modal-panel-rise .22s cubic-bezier(.2, .7, .2, 1) both;
    }
    .keys-modal-panel {
      width: min(620px, 100%);
      max-height: 90vh;
      overflow-y: auto;
      background: var(--bg);
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      box-shadow:
        0 0 0 1px color-mix(in srgb, var(--accent) 10%, transparent),
        0 20px 60px -16px rgba(0, 0, 0, 0.45);
      padding: 1.4rem 1.5rem 1.2rem;
      position: relative;
    }
    .keys-modal-head {
      display: flex; align-items: center; justify-content: space-between;
      margin-bottom: 0.85rem;
      padding-bottom: 0.85rem;
      border-bottom: 1px solid var(--border);
    }
    .keys-modal-title {
      font-family: var(--font-chrome);
      font-weight: 700;
      font-size: 0.85rem;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      color: var(--accent-deep);
      margin: 0;
    }
    [data-theme="terminal"] .keys-modal-title { color: var(--accent); }
    .keys-modal-close {
      width: 1.9rem; height: 1.9rem;
      display: inline-flex; align-items: center; justify-content: center;
      background: transparent;
      border: 1px solid color-mix(in srgb, var(--border-strong) 60%, transparent);
      border-radius: var(--radius-chip);
      color: var(--text-faint);
      font-family: var(--font-chrome); font-size: 0.85rem;
      cursor: pointer;
      transition: color .1s linear, border-color .1s linear,
                  background .1s linear;
    }
    .keys-modal-close:hover {
      color: var(--accent-fg);
      background: var(--accent);
      border-color: var(--border-strong);
    }
    .keys-modal-intro {
      font-family: var(--body); font-size: 0.82rem;
      color: var(--text-dim);
      margin: 0 0 1rem;
      line-height: 1.5;
    }
    .keys-modal-intro code {
      font-family: var(--font-chrome); font-size: 0.78rem;
      background: color-mix(in srgb, var(--accent) 8%, transparent);
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      padding: 0.06em 0.36em;
    }
    .keys-create {
      display: flex; gap: 0.5rem;
      margin-bottom: 1rem;
    }
    .keys-create-name {
      flex: 1;
      font-family: var(--font-chrome); font-size: 0.85rem;
      color: var(--text);
      background: color-mix(in srgb, var(--surface) 60%, transparent);
      border: 1px solid color-mix(in srgb, var(--border-strong) 60%, transparent);
      border-radius: var(--radius-chip);
      padding: 0.55rem 0.7rem;
      outline: none;
      transition: border-color .12s linear, box-shadow .12s linear;
    }
    .keys-create-name::placeholder {
      color: var(--text-faint);
      font-family: var(--font-chrome);
    }
    .keys-create-name:focus {
      border-color: var(--border-strong);
      box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 22%, transparent);
    }
    .keys-create-btn {
      font-family: var(--font-chrome); font-weight: 700;
      font-size: 0.62rem;
      letter-spacing: 0.24em;
      text-transform: uppercase;
      color: var(--accent-fg);
      background: var(--accent);
      border: 1px solid var(--border-strong);
      border-radius: var(--radius-chip);
      padding: 0 1rem;
      cursor: pointer;
      transition: box-shadow .1s linear, transform .08s linear;
    }
    .keys-create-btn:hover {
      box-shadow: 0 0 14px -2px color-mix(in srgb, var(--accent) 60%, transparent);
    }
    .keys-create-btn:active { transform: translateY(1px); }
    .keys-create-btn:disabled { opacity: 0.55; cursor: wait; }

    .keys-reveal {
      margin-bottom: 1rem;
      padding: 0.8rem 0.9rem;
      background: color-mix(in srgb, var(--accent) 8%, transparent);
      border: 1px solid var(--border-strong);
      border-left: 3px solid var(--border-strong);
      border-radius: var(--radius-chip);
    }
    .keys-reveal-header {
      font-family: var(--font-chrome); font-weight: 700;
      font-size: 0.6rem;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      color: var(--accent-deep);
      margin-bottom: 0.55rem;
    }
    [data-theme="terminal"] .keys-reveal-header { color: var(--accent); }
    .keys-reveal-row {
      display: flex; gap: 0.5rem; align-items: stretch;
    }
    .keys-reveal-value {
      flex: 1;
      font-family: var(--font-chrome); font-size: 0.78rem;
      color: var(--text);
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      padding: 0.5rem 0.6rem;
      overflow-x: auto;
      white-space: nowrap;
      user-select: all;
    }
    .keys-reveal-copy {
      font-family: var(--font-chrome); font-weight: 600;
      font-size: 0.6rem;
      letter-spacing: 0.18em;
      text-transform: uppercase;
      color: var(--accent-deep);
      background: transparent;
      border: 1px solid var(--border-strong);
      border-radius: var(--radius-chip);
      padding: 0 0.85rem;
      cursor: pointer;
      transition: color .1s linear, background .1s linear;
    }
    [data-theme="terminal"] .keys-reveal-copy { color: var(--accent); }
    .keys-reveal-copy:hover {
      color: var(--accent-fg);
      background: var(--accent);
    }
    .keys-reveal-copy.copied { color: var(--success); border-color: var(--success); }

    .keys-list {
      display: flex; flex-direction: column;
      gap: 0.4rem;
    }
    .keys-list-empty {
      font-family: var(--font-chrome); font-size: 0.72rem;
      color: var(--text-faint);
      padding: 0.85rem 0;
      text-align: center;
    }
    /* Terminal-only `//` prefix on the empty-keys placeholder. */
    [data-theme="terminal"] .keys-list-empty::before { content: "// "; opacity: 0.6; }
    .keys-row {
      display: grid;
      grid-template-columns: 1fr auto;
      gap: 0.6rem 1rem;
      padding: 0.6rem 0.7rem;
      background: color-mix(in srgb, var(--surface) 25%, transparent);
      border: 1px solid color-mix(in srgb, var(--border-strong) 50%, transparent);
      border-radius: var(--radius-chip);
      align-items: center;
    }
    /* Memories grouped under kind labels (Location / Preference / Tech /
       Personal). Subtle uppercase chrome-font label sits above the
       group's rows; rows themselves reuse .keys-row styling. */
    .memories-section { display: flex; flex-direction: column; gap: 0.4rem; }
    .memories-section + .memories-section { margin-top: 0.85rem; }
    .memories-section-label {
      font-family: var(--font-chrome); font-weight: 700;
      font-size: 0.58rem; letter-spacing: 0.2em;
      text-transform: uppercase; color: var(--text-dim);
      padding: 0 0.1rem 0.1rem;
    }
    /* Editable memory content — contenteditable shows a subtle focus
       outline + caret. Click to edit, Enter or blur to save, Esc to
       revert. */
    .memory-content {
      cursor: text;
      white-space: normal;
      outline: none;
      border-radius: var(--radius-chip);
      padding: 0.1rem 0.25rem;
      transition: background .1s ease;
    }
    .memory-content:hover {
      background: color-mix(in srgb, var(--accent) 6%, transparent);
    }
    .memory-content:focus {
      background: color-mix(in srgb, var(--accent) 10%, transparent);
      box-shadow: inset 0 0 0 1px var(--accent);
    }
    .keys-row.revoked { opacity: 0.55; }
    .keys-row-info { min-width: 0; }
    .keys-row-name {
      font-family: var(--font-chrome); font-weight: 600;
      font-size: 0.82rem;
      color: var(--text);
      letter-spacing: 0.02em;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .keys-row-meta {
      font-family: var(--font-chrome); font-size: 0.62rem;
      letter-spacing: 0.05em;
      color: var(--text-faint);
      margin-top: 0.2rem;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .keys-row-meta .prefix { color: var(--accent-deep); }
    [data-theme="terminal"] .keys-row-meta .prefix { color: var(--accent); }
    .keys-row-revoke {
      font-family: var(--font-chrome); font-weight: 600;
      font-size: 0.58rem;
      letter-spacing: 0.18em;
      text-transform: uppercase;
      color: var(--danger);
      background: transparent;
      border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
      border-radius: var(--radius-chip);
      padding: 0.35rem 0.65rem;
      cursor: pointer;
      transition: color .1s linear, background .1s linear,
                  border-color .1s linear;
    }
    .keys-row-revoke:hover {
      color: var(--accent-fg);
      background: var(--danger);
      border-color: var(--danger);
    }
    .keys-row.revoked .keys-row-revoke {
      visibility: hidden;
    }
    .keys-row.revoked .keys-row-name::after {
      content: "  ✕ revoked";
      color: var(--danger);
      font-weight: 500;
      letter-spacing: 0.12em;
      font-size: 0.62rem;
      margin-left: 0.5rem;
    }
    /* Mobile — make the modal occupy the screen cleanly. */
    @media (max-width: 600px) {
      .keys-modal { padding: 0.6rem; }
      .keys-modal-panel { padding: 1rem 1rem 0.9rem; }
      .keys-create { flex-direction: column; }
      .keys-create-btn { padding: 0.65rem 1rem; }
    }

    /* ── theme chooser modal ─────────────────────────
       Two-column layout: scrollable theme list on the left, live mini-
       preview on the right. Clicking a theme name in the list updates
       the preview WITHOUT applying. Apply commits the choice; Cancel
       discards. The preview is a self-contained mini-app that uses the
       hovered theme's own data-theme — so all the design tokens cascade
       and the user sees real type, radii, accent, and atmosphere. */
    .theme-chooser-modal {
      position: fixed; inset: 0; z-index: 1100;
      display: none;
      align-items: center; justify-content: center;
      padding: 1.5rem;
      background: rgba(0, 0, 0, 0.55);
      backdrop-filter: blur(6px);
      -webkit-backdrop-filter: blur(6px);
      animation: keys-modal-fade .14s ease-out;
    }
    .theme-chooser-modal.open { display: flex; }
    .theme-chooser-panel {
      width: min(840px, 100%);
      min-width: 0;
      max-height: 92vh;
      display: flex; flex-direction: column;
      background: var(--bg);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      box-shadow:
        0 0 0 1px color-mix(in srgb, var(--accent) 10%, transparent),
        0 20px 60px -16px rgba(0, 0, 0, 0.45);
      padding: 1.3rem 1.4rem 1.2rem;
      position: relative;
    }
    .theme-chooser-head {
      display: flex; align-items: center; justify-content: space-between;
      margin-bottom: 1rem;
      padding-bottom: 0.85rem;
      border-bottom: 1px solid var(--border);
    }
    .theme-chooser-title {
      font-family: var(--font-chrome);
      font-weight: 700;
      font-size: 0.85rem;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      color: var(--accent-deep);
      margin: 0;
    }
    [data-theme="terminal"] .theme-chooser-title { color: var(--accent); }
    .theme-chooser-close {
      width: 1.9rem; height: 1.9rem;
      display: inline-flex; align-items: center; justify-content: center;
      background: transparent;
      border: 1px solid color-mix(in srgb, var(--border-strong) 60%, transparent);
      border-radius: var(--radius-chip);
      color: var(--text-faint);
      font-family: var(--font-chrome); font-size: 0.85rem;
      cursor: pointer;
      transition: color .1s linear, border-color .1s linear,
                  background .1s linear;
    }
    .theme-chooser-close:hover {
      color: var(--accent-fg);
      background: var(--accent);
      border-color: var(--border-strong);
    }
    /* Two-column body: scrollable list left, live preview right. */
    .theme-chooser-body {
      display: flex;
      gap: 1rem;
      flex: 1;
      min-height: 0;
    }
    .theme-chooser-list {
      flex: 0 0 180px;
      display: flex; flex-direction: column;
      gap: 2px;
      overflow-y: auto;
      padding-right: 0.4rem;
      max-height: 380px;
    }
    .theme-list-item {
      display: flex; align-items: center; gap: 0.6rem;
      width: 100%;
      padding: 0.55rem 0.7rem;
      background: transparent;
      border: 1px solid transparent;
      border-radius: var(--radius-chip);
      cursor: pointer;
      text-align: left;
      font-family: var(--font-chrome);
      font-size: 0.74rem;
      font-weight: 600;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      color: var(--text-dim);
      transition: background .1s linear, color .1s linear,
                  border-color .1s linear;
    }
    .theme-list-item:hover {
      background: color-mix(in srgb, var(--accent) 8%, transparent);
      color: var(--text);
    }
    .theme-list-item.selected {
      background: color-mix(in srgb, var(--accent) 14%, transparent);
      color: var(--accent-deep);
      border-color: var(--border);
    }
    [data-theme="terminal"] .theme-list-item.selected { color: var(--accent); }
    .theme-list-dot {
      flex-shrink: 0;
      width: 10px; height: 10px;
      border-radius: 50%;
      border: 1px solid color-mix(in srgb, var(--text) 15%, transparent);
    }
    .theme-list-label { flex: 1; }
    /* "active" marker = the theme currently applied to the app
       (vs "selected" = the one the user clicked in the chooser). */
    .theme-list-active-marker {
      width: 4px; height: 4px;
      border-radius: 50%;
      background: var(--accent);
      flex-shrink: 0;
    }

    /* Right column — frame around the live mini preview + meta caption. */
    .theme-chooser-preview-wrap {
      flex: 1;
      display: flex; flex-direction: column;
      min-width: 0;
    }
    /* The preview itself — gets its OWN data-theme via JS, so the tokens
       cascade and produce a real-looking mini app in any theme. Position
       relative so the scanline ::before can absolute-position over it. */
    .theme-preview {
      flex: 1;
      position: relative;
      background: var(--bg);
      color: var(--text);
      border-radius: var(--radius-card);
      border: 1px solid var(--border);
      overflow: hidden;
      min-height: 240px;
      transition: background .18s ease;
    }
    /* Body-gradient + scanlines render inside the preview too, scoped
       to its data-theme. Lets you see Glass's aurora or Terminal's
       scanlines without leaving the modal. */
    .theme-preview::before {
      content: "";
      position: absolute; inset: 0;
      background: var(--body-gradient);
      pointer-events: none;
      z-index: 0;
    }
    .theme-preview::after {
      content: "";
      position: absolute; inset: 0;
      opacity: var(--scanline-opacity);
      background: repeating-linear-gradient(
        to bottom,
        transparent 0,
        transparent 3px,
        color-mix(in srgb, var(--accent) 2.5%, transparent) 3px,
        color-mix(in srgb, var(--accent) 2.5%, transparent) 4px
      );
      pointer-events: none;
      z-index: 1;
    }
    .theme-preview-inner {
      position: relative;
      z-index: 2;
      display: flex;
      width: 100%; height: 100%;
      min-height: inherit;
    }
    /* Mini sidebar inside the preview — vertical strip with brand +
       3 conversation rows, the first one "active". Uses the previewed
       theme's surface/line tokens. */
    .theme-preview-sidebar {
      width: 76px;
      flex-shrink: 0;
      background: color-mix(in srgb, var(--surface) 60%, transparent);
      backdrop-filter: blur(8px);
      border-right: 1px solid var(--border);
      padding: 12px 8px;
      display: flex; flex-direction: column;
      gap: 8px;
    }
    .theme-preview-brand {
      font-family: var(--font-chrome);
      font-weight: 800;
      font-size: 0.75rem;
      color: var(--text);
      letter-spacing: 0.02em;
      padding: 2px 4px;
      margin-bottom: 4px;
    }
    .theme-preview-brand .y {
      font-style: italic;
      color: var(--accent-deep);
    }
    .theme-preview-conv {
      height: 9px;
      background: color-mix(in srgb, var(--text) 5%, transparent);
      border-radius: var(--radius-chip);
    }
    .theme-preview-conv.active {
      background: color-mix(in srgb, var(--accent) 22%, transparent);
      border-left: 2px solid var(--border-strong);
    }
    /* Main preview area — two mini message bubbles + composer pill. */
    .theme-preview-main {
      flex: 1;
      display: flex; flex-direction: column;
      padding: 14px 14px 10px;
      gap: 8px;
      min-width: 0;
    }
    .theme-preview-bubble {
      max-width: 80%;
      padding: 7px 11px;
      font-family: var(--body);
      font-size: 0.72rem;
      line-height: 1.4;
      border-radius: var(--radius-bubble);
      border: 1px solid color-mix(in srgb, var(--text) 8%, transparent);
      background: color-mix(in srgb, var(--surface) 60%, transparent);
      color: var(--text);
    }
    .theme-preview-bubble.user {
      align-self: flex-end;
      background: var(--accent);
      color: var(--accent-fg);
      border-color: var(--border-strong);
    }
    .theme-preview-composer {
      margin-top: auto;
      display: flex; align-items: center; gap: 8px;
      padding: 9px 12px;
      background: color-mix(in srgb, var(--surface) 70%, transparent);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      font-family: var(--font-input);
      font-size: 0.68rem;
      color: var(--text-faint);
    }
    .theme-preview-composer-placeholder {
      flex: 1;
      font-family: var(--font-input);
    }
    .theme-preview-composer-mic {
      width: 16px; height: 16px;
      border-radius: 50%;
      background: var(--accent);
      flex-shrink: 0;
    }

    /* Meta line below the preview — theme name + blurb. */
    .theme-preview-meta {
      margin-top: 0.8rem;
      padding: 0.5rem 0.2rem 0;
      font-family: var(--font-chrome);
    }
    .theme-preview-name {
      font-size: 0.95rem;
      font-weight: 700;
      letter-spacing: 0.02em;
      color: var(--text);
      margin: 0 0 0.2rem;
    }
    .theme-preview-blurb {
      font-size: 0.78rem;
      color: var(--text-dim);
      margin: 0;
      line-height: 1.4;
    }
    /* Footer with Cancel + Apply. Apply is disabled when the selected
       theme is already the active theme. */
    .theme-chooser-actions {
      display: flex; justify-content: flex-end; gap: 0.6rem;
      margin-top: 1.1rem;
      padding-top: 1rem;
      border-top: 1px solid var(--border);
    }
    .theme-chooser-btn {
      padding: 0.55rem 1.1rem;
      font-family: var(--font-chrome);
      font-size: 0.74rem;
      font-weight: 700;
      letter-spacing: 0.18em;
      text-transform: uppercase;
      border-radius: var(--radius-chip);
      cursor: pointer;
      border: 1px solid color-mix(in srgb, var(--border-strong) 70%, transparent);
      background: transparent;
      color: var(--text-dim);
      transition: color .12s linear, border-color .12s linear,
                  background .12s linear;
    }
    .theme-chooser-btn:hover {
      color: var(--text);
      border-color: var(--border);
    }
    .theme-chooser-btn.primary {
      background: var(--accent);
      border-color: var(--border-strong);
      color: var(--accent-fg);
    }
    .theme-chooser-btn.primary:hover {
      background: var(--accent-deep);
      border-color: var(--border-strong);
    }
    .theme-chooser-btn.primary:disabled {
      opacity: 0.45;
      cursor: not-allowed;
    }
    @media (max-width: 700px) {
      .theme-chooser-modal { padding: 0.6rem; }
      .theme-chooser-panel { padding: 1rem 1rem 0.9rem; }
      .theme-chooser-body { flex-direction: column; gap: 0.8rem; }
      .theme-chooser-list { flex: 0 0 auto; max-height: 140px; }
      .theme-preview { min-height: 200px; }
    }

    /* ── DISPLAY SETTINGS — sectioned, instant-apply ── */
    .display-body {
      display: flex; flex-direction: column;
      gap: 1.4rem;
      overflow-y: auto;
      min-width: 0;
      max-height: 70vh;
      /* Equal side padding so the active card's accent ring has room to
         breathe on BOTH sides — asymmetric padding was clipping the left
         edge of cards sitting flush against the body's left wall. */
      padding: 0 0.3rem;
    }
    .display-section { display: flex; flex-direction: column; gap: 0.6rem; }
    .display-section-title {
      font-family: var(--font-chrome); font-weight: 700;
      font-size: 0.7rem; letter-spacing: 0.2em; text-transform: uppercase;
      color: var(--text-dim); margin: 0;
    }
    /* Theme card grid */
    .display-themes {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
      gap: 0.6rem;
    }
    .display-theme-card {
      display: flex; flex-direction: column; gap: 0.45rem;
      padding: 0.55rem;
      background: transparent; border: 1px solid var(--border);
      border-radius: var(--radius-card); cursor: pointer;
      text-align: left; font-family: var(--font-chrome);
      transition: border-color .12s ease, transform .12s ease;
    }
    .display-theme-card:hover {
      border-color: var(--border);
      transform: translateY(-1px);
    }
    .display-theme-card.active {
      border-color: var(--border-strong);
      box-shadow: 0 0 0 1px var(--accent);
    }
    .display-theme-swatch {
      position: relative; height: 56px;
      border-radius: var(--radius-chip); overflow: hidden;
    }
    .display-theme-surface {
      position: absolute; left: 6px; right: 6px; bottom: 6px;
      height: 20px; border-radius: 3px;
    }
    .display-theme-accent {
      position: absolute; top: 8px; left: 8px;
      width: 11px; height: 11px; border-radius: 50%;
    }
    .display-theme-label {
      font-weight: 700; font-size: 0.74rem; letter-spacing: 0.1em;
      text-transform: uppercase; color: var(--text);
    }
    .display-theme-blurb {
      font-size: 0.68rem; color: var(--text-dim); line-height: 1.35;
    }
    /* Accent dots — minimal: just colored circles in a row, with a
       ring around the active one. Pure color picker, no labels. */
    .display-accents {
      display: flex; flex-wrap: wrap; gap: 0.5rem;
      align-items: center;
    }
    .display-accent {
      width: 32px; height: 32px;
      padding: 4px;
      background: transparent; border: 2px solid transparent;
      border-radius: 50%;
      cursor: pointer;
      transition: border-color .12s ease, transform .12s ease;
    }
    .display-accent:hover { transform: scale(1.08); }
    .display-accent.active { border-color: var(--text); }
    .display-accent-dot {
      position: relative;
      display: flex;
      align-items: center; justify-content: center;
      width: 100%; height: 100%;
      border-radius: 50%;
      box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08),
                  0 1px 2px rgba(0, 0, 0, 0.10);
    }
    /* Custom-color picker — wraps a hidden native <input type="color">
       that triggers the OS color picker when the visible dot is
       clicked. The `+` overlay signals it's the picker, not a preset. */
    .display-accent-custom { position: relative; }
    .display-accent-custom-input {
      position: absolute;
      inset: 0;
      width: 100%; height: 100%;
      opacity: 0;
      cursor: pointer;
      /* Prevents the native picker thumbnail from showing through. */
      appearance: none;
      -webkit-appearance: none;
      border: none; padding: 0; margin: 0;
    }
    .display-accent-custom-plus {
      color: #ffffff;
      font-weight: 700;
      font-size: 0.9rem;
      line-height: 1;
      text-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
      pointer-events: none;
    }

    /* Segmented control (sidebar / messages) */
    .display-segmented {
      display: inline-flex; flex-wrap: wrap;
      border: 1px solid var(--border); border-radius: var(--radius-chip);
      padding: 2px; gap: 2px;
      background: var(--surface-2);
      align-self: flex-start;
      max-width: 100%;
    }
    .display-segment {
      padding: 0.45rem 1rem;
      background: transparent; border: none;
      border-radius: calc(var(--radius-chip) - 2px);
      cursor: pointer; font-family: var(--font-chrome);
      font-weight: 600; font-size: 0.78rem; letter-spacing: 0.06em;
      color: var(--text-dim);
      transition: background .12s ease, color .12s ease;
    }
    .display-segment:hover { color: var(--text); }
    .display-segment.active {
      background: var(--accent);
      /* Use the same accent-text token as user bubbles so the label
         stays readable regardless of accent OR foreground override. */
      color: var(--accent-fg);
    }
    /* ── ACCENT setting: overrides --accent across all themes ──
       All accents share L=0.58 + C≈0.07 (OKLCH) — only the hue varies.
       This keeps the whole palette tonally cohesive (matches Sage's
       muted feel) so any accent reads as "the same level of color,
       just a different shade." --accent-deep is the darker companion for
       hover/active states. --accent-soft is derived universally from
       --accent via color-mix in the html rule below. */
    [data-accent="red"]    { --accent: rgb(220 85 85);   --accent-deep: color-mix(in srgb, rgb(220 85 85) 72%, black);   }
    [data-accent="pink"]   { --accent: rgb(220 85 165);  --accent-deep: color-mix(in srgb, rgb(220 85 165) 72%, black);  }
    [data-accent="purple"] { --accent: rgb(165 85 220);  --accent-deep: color-mix(in srgb, rgb(165 85 220) 72%, black);  }
    [data-accent="cobalt"] { --accent: rgb(50 130 195);  --accent-deep: color-mix(in srgb, rgb(50 130 195) 72%, black);  }
    [data-accent="sky"]    { --accent: rgb(85 160 220);  --accent-deep: color-mix(in srgb, rgb(85 160 220) 72%, black);  }
    [data-accent="teal"]   { --accent: rgb(85 175 175);  --accent-deep: color-mix(in srgb, rgb(85 175 175) 72%, black);  }
    [data-accent="sage"]   { --accent: rgb(107 138 111); --accent-deep: color-mix(in srgb, rgb(107 138 111) 72%, black); }
    [data-accent="green"]  { --accent: rgb(105 180 110); --accent-deep: color-mix(in srgb, rgb(105 180 110) 72%, black); }
    [data-accent="gold"]   { --accent: rgb(195 155 60);  --accent-deep: color-mix(in srgb, rgb(195 155 60) 72%, black);  }
    /* Neutrals — when used as a user-bubble fill, the text-on-accent
       contrast can flip. --accent-fg overrides the default white text in
       .msg.user for accents that need dark text instead. */
    [data-accent="black"]     { --accent: rgb(0 0 0);       --accent-deep: rgb(40 40 40);    --accent-fg: #fff; }
    [data-accent="darkgray"]  { --accent: rgb(80 80 80);    --accent-deep: rgb(40 40 40);    --accent-fg: #fff; }
    [data-accent="lightgray"] { --accent: rgb(200 200 200); --accent-deep: rgb(160 160 160); --accent-fg: #1a1a1a; }
    [data-accent="white"]     { --accent: rgb(255 255 255); --accent-deep: rgb(225 225 225); --accent-fg: #000; }
    /* Foreground override — explicit user pick of "white" or "black"
       forces text-on-accent regardless of the per-accent default.
       "auto" sets no rule, falling through to the accent's own
       --accent-fg (or .msg.user's #fff fallback). html-prefix gives
       higher specificity (0-1-1) than the bare [data-accent] (0-1-0). */
    html[data-accent-fg="white"] { --accent-fg: #ffffff; }
    html[data-accent-fg="black"] { --accent-fg: #000000; }
    /* Universal derived tokens that any accent block can override:
       - --accent-soft: tinted version of accent for backgrounds
       - --accent-fg:   text color USED ON the accent. Defaults to white;
                     per-accent and html[data-accent-fg] rules can win
                     via specificity to flip to dark text.
       Borders are NOT derived from the accent — see --border / --border-strong
       in each theme for the muted-foreground border palette. */
    html {
      --accent-soft: color-mix(in srgb, var(--accent) 18%, transparent);
      --accent-fg: #ffffff;
    }
    /* Wordmark glow keyframe — token-driven via color-mix so a single
       block handles all theme + accent combinations without per-accent
       overrides of @keyframes. */
    @keyframes breathe-accent {
      0%, 100% { text-shadow: 0 0 0.22em color-mix(in srgb, var(--accent) 28%, transparent); }
      50%      { text-shadow: 0 0 0.55em color-mix(in srgb, var(--accent) 48%, transparent); }
    }

    /* ── SIDEBAR-SIDE setting: right-positioning ── */
    [data-sidebar-side="right"] body { flex-direction: row-reverse; }
    [data-sidebar-side="right"] .sidebar {
      border-right: none;
      border-left: var(--border-width) solid var(--border);
    }
    /* Collapse button moves to the inner edge (near main content)
       and the wordmark mirrors right to keep clear of it. Without
       the brand-area mirror, the wordmark and toggle overlap. */
    [data-sidebar-side="right"] .sidebar-toggle { right: auto; left: 0.55rem; }
    [data-sidebar-side="right"] .sidebar-brand {
      text-align: right;
      padding-left: 2.8rem;
      padding-right: 0.95rem;
    }
    /* Show-sidebar floating button (visible when sidebar is collapsed)
       lives at the right edge so it's where the sidebar would re-enter from. */
    [data-sidebar-side="right"] .sidebar-show { left: auto; right: 0.55rem; }
    /* Chevrons flip horizontally so they point the correct way:
       collapse-arrow points AWAY from the main content (toward the
       sidebar's outer edge), show-arrow points TOWARD where the
       sidebar will reappear. */
    [data-sidebar-side="right"] .sidebar-toggle svg,
    [data-sidebar-side="right"] .sidebar-show svg {
      transform: scaleX(-1);
    }

    /* ── MESSAGE-STYLE setting ──
       Three modes for how messages render:
         - bubbles: default rounded, asymmetric flat-on-accent shape
         - cards:   square rectangular blocks, accent stripe intact
         - compact: no chrome, just attribution + text
       Compact is the most aggressive reset (rewrites layout); cards
       and bubbles differ only in border-radius and slightly heavier
       background tint. */

    /* In BUBBLES mode the attribution chip is hidden — position alone
       tells you who's speaking (user right, assistant left). The chip
       returns in cards (formal feel) and compact (only signal). */
    [data-message-style="bubbles"] .msg.user::before,
    [data-message-style="bubbles"] .msg.assistant::before {
      display: none;
    }

    /* CARDS — square rectangles with hairline border + accent edge
       stripe that FADES vertically. The fade reads as atmospheric
       (accent light casting INTO the card) rather than structural
       (welded-on stripe). User stripe falls on the right, assistant
       on the left. */
    [data-message-style="cards"] .msg.user {
      background:
        linear-gradient(to bottom, var(--accent), transparent 78%) right top / 2px 100% no-repeat,
        color-mix(in srgb, var(--surface) 88%, transparent);
      color: var(--text);
      border: 1px solid color-mix(in srgb, var(--border-strong) 55%, transparent);
      border-radius: 0;
      padding: 0.7rem 0.95rem;
    }
    [data-message-style="cards"] .msg.assistant {
      background:
        linear-gradient(to bottom, var(--accent), transparent 78%) left top / 2px 100% no-repeat,
        color-mix(in srgb, var(--surface-2) 92%, transparent);
      color: var(--text);
      border: 1px solid color-mix(in srgb, var(--border-strong) 55%, transparent);
      border-radius: 0;
      padding: 0.7rem 0.95rem 0.85rem;
    }

    /* ── COMPACT — strip the bubble entirely ── */
    /* Compact = no bubble chrome. Just attribution + body, single hairline
       between turns. Reads more like a transcript than a chat. */
    [data-message-style="compact"] .msg.user,
    [data-message-style="compact"] .msg.assistant {
      align-self: stretch;
      background: transparent;
      border: none;
      border-left: none;
      border-right: none;
      border-radius: 0;
      padding: 0;
      max-width: 100%;
    }
    [data-message-style="compact"] .msg.user { color: var(--text-dim); }
    [data-message-style="compact"] .msg.assistant { color: var(--text); }
    [data-message-style="compact"] .msg + .msg {
      padding-top: 1.2rem;
      border-top: 1px solid color-mix(in srgb, var(--text) 8%, transparent);
    }
    [data-message-style="compact"] .msg.user::before,
    [data-message-style="compact"] .msg.assistant::before {
      font-family: var(--font-chrome); font-weight: 600;
      font-size: 0.6rem; letter-spacing: 0.18em; text-transform: uppercase;
      margin-bottom: 0.3rem; color: var(--text-faint);
      text-align: left;
    }
    [data-message-style="compact"] .msg.user::before { content: "You"; }
    [data-message-style="compact"] .msg.assistant::before {
      content: "Alyx • " attr(data-kind);
      color: var(--accent);
    }

    /* ── confirm modal ─────────────────────────────────
       Compact terminal-styled dialog replacing browser confirm().
       Same overlay backdrop + sharp ice panel idiom as keys-modal,
       just smaller. Driven by confirmModal() in JS. */
    .confirm-modal {
      position: fixed; inset: 0; z-index: 1200;
      display: none;
      align-items: center; justify-content: center;
      padding: 1.5rem;
      background: rgba(0, 0, 0, 0.55);
      backdrop-filter: blur(6px);
      -webkit-backdrop-filter: blur(6px);
      animation: keys-modal-fade .14s ease-out;
    }
    .confirm-modal.open { display: flex; }
    .confirm-modal-panel {
      width: min(420px, 100%);
      background: var(--bg);
      border: 1px solid var(--border);
      border-radius: var(--radius-chip);
      box-shadow:
        0 0 0 1px color-mix(in srgb, var(--accent) 10%, transparent),
        0 20px 60px -16px rgba(0, 0, 0, 0.45);
      padding: 1.25rem 1.35rem 1rem;
    }
    .confirm-modal-title {
      font-family: var(--font-chrome);
      font-weight: 700;
      font-size: 0.72rem;
      letter-spacing: 0.24em;
      text-transform: uppercase;
      color: var(--accent-deep);
      margin: 0 0 0.65rem;
    }
    [data-theme="terminal"] .confirm-modal-title { color: var(--accent); }
    .confirm-modal-message {
      font-family: var(--body);
      font-size: 0.9rem;
      color: var(--text-dim);
      line-height: 1.5;
      margin: 0 0 1.1rem;
    }
    .confirm-modal-actions {
      display: flex; gap: 0.5rem; justify-content: flex-end;
    }
    .confirm-modal-btn {
      font-family: var(--font-chrome); font-weight: 700;
      font-size: 0.62rem;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      padding: 0.55rem 1rem;
      border-radius: var(--radius-chip);
      cursor: pointer;
      transition: color .1s linear, background .1s linear,
                  border-color .1s linear, box-shadow .1s linear,
                  transform .08s linear;
    }
    .confirm-modal-cancel {
      color: var(--text-dim);
      background: transparent;
      border: 1px solid color-mix(in srgb, var(--border-strong) 60%, transparent);
    }
    .confirm-modal-cancel:hover {
      color: var(--text);
      border-color: color-mix(in srgb, var(--text) 40%, transparent);
    }
    .confirm-modal-confirm {
      color: var(--accent-fg);
      background: var(--accent);
      border: 1px solid var(--border-strong);
    }
    .confirm-modal-confirm:hover {
      box-shadow: 0 0 14px -2px color-mix(in srgb, var(--accent) 60%, transparent);
    }
    .confirm-modal-confirm:active { transform: translateY(1px); }
    /* Danger flavor — destructive actions (delete chat, revoke key)
       swap the confirm button to rose so the user has a visual cue
       that this isn't reversible. */
    .confirm-modal.danger .confirm-modal-confirm {
      background: var(--danger);
      border-color: var(--danger);
      color: var(--accent-fg);
    }
    [data-theme="terminal"] .confirm-modal.danger .confirm-modal-confirm {
      color: var(--accent-fg);
    }
    .confirm-modal.danger .confirm-modal-confirm:hover {
      box-shadow: 0 0 14px -2px color-mix(in srgb, var(--danger) 60%, transparent);
    }
    @media (max-width: 600px) {
      .confirm-modal { padding: 0.6rem; }
      .confirm-modal-panel { padding: 1rem 1rem 0.85rem; }
    }

    @media (max-width: 720px) {
      /* Mobile: the sidebar becomes a slide-in drawer instead of a
         fixed rail. Always rendered (display: flex) so the transform
         transition runs; offscreen by default; body.sidebar-open
         slides it in. The floating reveal button is always visible
         so the user can always reach the menu. */
      .sidebar {
        position: fixed;
        top: 0; left: 0; bottom: 0;
        width: 18rem;
        max-width: 82vw;
        z-index: 200;
        transform: translateX(-100%);
        transition: transform .25s cubic-bezier(.4, 0, .2, 1);
        background: color-mix(in srgb, var(--surface) 92%, transparent);
        backdrop-filter: blur(24px) saturate(160%);
        -webkit-backdrop-filter: blur(24px) saturate(160%);
      }
      body.sidebar-open .sidebar {
        transform: translateX(0);
        box-shadow: 0 0 60px -10px rgba(0, 0, 0, 0.45);
      }
      /* Override the desktop collapse rule — mobile doesn't have
         that concept; the only state is "drawer open or closed". */
      body.sidebar-collapsed .sidebar { display: flex; }

      .sidebar-show {
        display: inline-flex;
      }
      body.sidebar-open .sidebar-show {
        /* Hide the reveal button while drawer is open — the user
           can dismiss via the backdrop, the in-drawer chevron, or
           selecting a conv. */
        display: none;
      }

      body.sidebar-open .sidebar-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.45);
        backdrop-filter: blur(4px);
        -webkit-backdrop-filter: blur(4px);
        z-index: 150;
        animation: backdrop-fade .18s ease-out;
      }
      @keyframes backdrop-fade {
        from { opacity: 0; }
        to   { opacity: 1; }
      }
    }
    @media (max-width: 600px) {
      /* (Old `.user { display: none; }` rule removed — it was meant to
         hide the email in the now-deleted header but was also matching
         user-message bubbles (`.msg.user`) and hiding them on mobile.) */
      /* Bump the textarea font-size to 16px so iOS Safari doesn't
         auto-zoom on focus. Any input rendered at < 16px triggers it. */
      .input { font-size: 1rem; }
      .conv { padding: 1.2rem 1rem 0.8rem; }
      .composer-wrap { padding: 1.2rem 1rem 1rem; }
      .empty { padding: 1.6rem 0.5rem; }
      .composer { padding: 0.55rem 0.55rem 0.45rem 0.7rem; }
      .input-row { gap: 0.4rem; }
      .mute-btn { width: 2.2rem; height: 2.2rem; }
      .send { min-width: 2.2rem; padding: 0; }
      .msg.user { max-width: 88%; }
      .msg.assistant { max-width: 96%; }
    }
