  @font-face {
    font-family: 'Brunea';
    src: url('assets/fonts/AT-Brunea-Regular.otf') format('opentype');
    font-weight: 400; font-style: normal;
  }
  /* Open-source UI-font options (John, 2026-08-27): Inter (rsms, OFL) + IBM Plex Sans
     (IBM, OFL). Both selectable in Settings → Visuals → Interface font and take over the
     whole UI so John can test them. Freely redistributable, unlike Anthropic's / Styrene. */
  @font-face { font-family: 'Inter'; src: url('assets/fonts/InterVariable.woff2') format('woff2'); font-weight: 100 900; font-style: normal; }
  @font-face { font-family: 'Inter'; src: url('assets/fonts/InterVariable-Italic.woff2') format('woff2'); font-weight: 100 900; font-style: italic; }
  @font-face { font-family: 'IBM Plex Sans'; src: url('assets/fonts/IBMPlexSans-Regular.woff2') format('woff2'); font-weight: 400; font-style: normal; }
  @font-face { font-family: 'IBM Plex Sans'; src: url('assets/fonts/IBMPlexSans-Medium.woff2') format('woff2'); font-weight: 500; font-style: normal; }
  @font-face { font-family: 'IBM Plex Sans'; src: url('assets/fonts/IBMPlexSans-SemiBold.woff2') format('woff2'); font-weight: 600; font-style: normal; }
  @font-face { font-family: 'IBM Plex Sans'; src: url('assets/fonts/IBMPlexSans-Bold.woff2') format('woff2'); font-weight: 700; font-style: normal; }
  /* Extra open-source UI-font options (John, 2026-09-11): sans (Source Sans 3, Roboto,
     Open Sans), serif (Source Serif 4, Lora, Merriweather) and mono (JetBrains Mono, IBM
     Plex Mono). All OFL / Apache, freely redistributable. Selectable in Settings → Visuals. */
  @font-face { font-family: 'Source Sans 3'; src: url('assets/fonts/SourceSans3-400.woff2') format('woff2'); font-weight: 400; font-style: normal; }
  @font-face { font-family: 'Source Sans 3'; src: url('assets/fonts/SourceSans3-600.woff2') format('woff2'); font-weight: 600; font-style: normal; }
  @font-face { font-family: 'Roboto Flex'; src: url('assets/fonts/Roboto-400.woff2') format('woff2'); font-weight: 400; font-style: normal; }
  @font-face { font-family: 'Roboto Flex'; src: url('assets/fonts/Roboto-500.woff2') format('woff2'); font-weight: 500; font-style: normal; }
  @font-face { font-family: 'Roboto Flex'; src: url('assets/fonts/Roboto-700.woff2') format('woff2'); font-weight: 700; font-style: normal; }
  @font-face { font-family: 'Open Sans'; src: url('assets/fonts/OpenSans-400.woff2') format('woff2'); font-weight: 400; font-style: normal; }
  @font-face { font-family: 'Open Sans'; src: url('assets/fonts/OpenSans-600.woff2') format('woff2'); font-weight: 600; font-style: normal; }
  @font-face { font-family: 'Open Sans'; src: url('assets/fonts/OpenSans-700.woff2') format('woff2'); font-weight: 700; font-style: normal; }
  @font-face { font-family: 'Source Serif 4'; src: url('assets/fonts/SourceSerif4-400.woff2') format('woff2'); font-weight: 400; font-style: normal; }
  @font-face { font-family: 'Source Serif 4'; src: url('assets/fonts/SourceSerif4-600.woff2') format('woff2'); font-weight: 600; font-style: normal; }
  @font-face { font-family: 'Lora'; src: url('assets/fonts/Lora-400.woff2') format('woff2'); font-weight: 400; font-style: normal; }
  @font-face { font-family: 'Lora'; src: url('assets/fonts/Lora-600.woff2') format('woff2'); font-weight: 600; font-style: normal; }
  @font-face { font-family: 'Lora'; src: url('assets/fonts/Lora-700.woff2') format('woff2'); font-weight: 700; font-style: normal; }
  @font-face { font-family: 'Merriweather'; src: url('assets/fonts/Merriweather-400.woff2') format('woff2'); font-weight: 400; font-style: normal; }
  @font-face { font-family: 'Merriweather'; src: url('assets/fonts/Merriweather-700.woff2') format('woff2'); font-weight: 700; font-style: normal; }
  @font-face { font-family: 'JetBrains Mono'; src: url('assets/fonts/JetBrainsMono-400.woff2') format('woff2'); font-weight: 400; font-style: normal; }
  @font-face { font-family: 'JetBrains Mono'; src: url('assets/fonts/JetBrainsMono-500.woff2') format('woff2'); font-weight: 500; font-style: normal; }
  @font-face { font-family: 'JetBrains Mono'; src: url('assets/fonts/JetBrainsMono-700.woff2') format('woff2'); font-weight: 700; font-style: normal; }
  @font-face { font-family: 'IBM Plex Mono'; src: url('assets/fonts/IBMPlexMono-400.woff2') format('woff2'); font-weight: 400; font-style: normal; }
  @font-face { font-family: 'IBM Plex Mono'; src: url('assets/fonts/IBMPlexMono-600.woff2') format('woff2'); font-weight: 600; font-style: normal; }
  @font-face {
    font-family: 'IBM Plex Mono';
    src: url('assets/fonts/IBMPlexMono-Regular.ttf') format('truetype');
    font-weight: 400; font-style: normal;
  }
  @font-face {
    font-family: 'IBM Plex Mono';
    src: url('assets/fonts/IBMPlexMono-Medium.ttf') format('truetype');
    font-weight: 500; font-style: normal;
  }
  /* DARK = the Black theme's ink on dark-GRAY surfaces (John, 2026-08-24). Only the
     near-black fills change to ~80% gray charcoal; text/accent inherit :root, which is
     the BLACK theme. The four themes are named for their buttons: Black, Dark, Light,
     White (John, 2026-09-19), each one value of data-theme — there is no second attribute. */
  body[data-theme="dark"] {
    /* Lifted noticeably (John, 2026-08-25: "WAY TOO BLACK" — this is the Dark theme). */
    --bg: #171717;
    --panel: #272727;
    --panel-2: #303030;
    --sidebar: #1c1c1c;
    --line: #383838;
    --tool: #272727;
    --tool-line: #383838;
  }
  /* BLACK is the base theme: its values ARE :root, so data-theme="black" needs no
     override block. Dark, Light and White each restate only what they change. */
  :root {
    --bg: #000000;
    --panel: #0b0b0b;
    --panel-2: #141414;
    --sidebar: #000000;
    --line: #232323;
    --text: #f2f2f2;
    --muted: #9a9a9a;   /* 4.51:1 on the darkest panel any theme/preset paints */
    --faint: #7c7c7c;   /* 3.04:1 there — the glyph/large-text bar */
    /* Accent color (Settings → Visuals → Accent color). ONE rgb triplet drives the
       solid, the soft tint, and every glow/shadow, so switching the accent recolors
       the whole app. Orange (Sol, 255, 106, 68) is the default. */
    --accent-rgb: 255, 106, 68;
    --accent: rgb(var(--accent-rgb));
    --accent-soft: rgba(var(--accent-rgb), .14);
    /* Branch-out is ALWAYS gold, regardless of the app's chosen accent — it's the
       one signature colour for "this is the parallel-branch super-agent". */
    --bo-rgb: 227, 179, 65;
    --bo: rgb(var(--bo-rgb));
    /* Status DOTS are a fixed traffic-light vocabulary — green=idle/waiting,
       ORANGE=working/thinking, red=error — and must NOT follow the accent picker
       (the green & red are already hardcoded; the orange is too). This is the Sol
       orange the dots have always shown at the default theme. (John, 2026-07-25) */
    --dot-work: #ff6a44;
    --bo-lt: #edc85f;          /* brighter gold for glyphs on dark */
    --bo-txt: #f3e2b4;         /* near-white gold for readable text */
    --bo-deep: #a97b12;        /* deep-gold gradient anchor */
    /* Fathom feedback = the SONNET model blue (#5b8def), NOT gold. Gold is Branch
       Out's signature; Fathom is its own thing and must read distinct from it.
       (John, 2026-07-28: "Gold was not the right color for this. It was the Sonnet
       model color.") Mirrors the --bo-* structure so both themes stay legible. */
    --fx-rgb: 91, 141, 239;
    --fx: rgb(var(--fx-rgb));
    --fx-lt: #7ea6f2;          /* brighter blue for glyphs/badges on dark */
    --fx-txt: #bcd2fb;         /* near-white blue for readable text */
    --user: #232323;
    --tool: #191919;
    --tool-line: #333333;
    --hover: #202020;
    --active: #1a1a1a;   /* active session highlight — darker so it's less harsh on black (John, 2026-08-27) */
    /* Interface typeface (Settings → Visuals). PLEX (IBM Plex Mono) is the default;
       the toggle can flip the whole UI to SF Mono or to CLASSIC (the macOS system
       sans). Only the font changes — every size, weight and layout stays as it was. */
    --ui-font-new: 'SF Mono', ui-monospace, monospace;
    --ui-font-classic: -apple-system, "SF Pro Text", system-ui, sans-serif;
    --ui-font-sfmono: "SF Mono", ui-monospace, monospace;
    --ui-font-inter: 'Inter', -apple-system, system-ui, sans-serif;
    --ui-font-plexsans: 'IBM Plex Sans', -apple-system, system-ui, sans-serif;
    --ui-font-srcsans: 'Source Sans 3', -apple-system, system-ui, sans-serif;
    --ui-font-roboto: 'Roboto Flex', -apple-system, system-ui, sans-serif;
    --ui-font-opensans: 'Open Sans', -apple-system, system-ui, sans-serif;
    --ui-font-srcserif: 'Source Serif 4', Georgia, serif;
    --ui-font-lora: 'Lora', Georgia, serif;
    --ui-font-merri: 'Merriweather', Georgia, serif;
    --ui-font-jetmono: 'JetBrains Mono', ui-monospace, monospace;
    --ui-font-plexmono: 'IBM Plex Mono', ui-monospace, monospace;
    /* The whole app UI + settings are ALWAYS the macOS system font now (John,
       2026-08-25). The Interface-font picker no longer touches the chrome; it only
       swaps --chat-font, applied to the SESSION conversation text (.msg / .q-text). */
    --ui-font: var(--ui-font-classic);
    --chat-font: var(--ui-font-sfmono);
    /* The "colour → 30% darker" left→right fade on session heads / tab chips. Black
       on dark. Light theme flips it to white so the tinted head/chip LIGHTENS toward
       its right edge instead of going dark (John, 2026-08-14). */
    --head-fade: rgba(0,0,0,.30);
  }
  /* Toggled from renderer.js by writing data-font="mono"/"classic"/"sfmono" on <body>.
     Drives ONLY the session conversation text (--chat-font), never the UI chrome. */
  body[data-font="mono"] { --chat-font: var(--ui-font-sfmono); }
  body[data-font="classic"] { --chat-font: var(--ui-font-classic); }
  body[data-font="sfmono"] { --chat-font: var(--ui-font-sfmono); }
  /* Inter / IBM Plex Sans (deliberately) take over the WHOLE app chrome, not just the session
     text — John wants to test them on every UI element. Most of the app HARD-CODES 'SF Mono',
     so swapping the --ui-font var alone barely showed; this forces the chosen family on
     everything (via var(--ui-font)), then restores monospace where alignment matters (code, the
     terminal) and keeps the Brunea logo wordmark. */
  body[data-font="inter"] { --ui-font: var(--ui-font-inter); --chat-font: var(--ui-font-inter); }
  body[data-font="plexsans"] { --ui-font: var(--ui-font-plexsans); --chat-font: var(--ui-font-plexsans); }
  body[data-font="srcsans"] { --ui-font: var(--ui-font-srcsans); --chat-font: var(--ui-font-srcsans); }
  body[data-font="roboto"] { --ui-font: var(--ui-font-roboto); --chat-font: var(--ui-font-roboto); }
  body[data-font="opensans"] { --ui-font: var(--ui-font-opensans); --chat-font: var(--ui-font-opensans); }
  body[data-font="srcserif"] { --ui-font: var(--ui-font-srcserif); --chat-font: var(--ui-font-srcserif); }
  body[data-font="lora"] { --ui-font: var(--ui-font-lora); --chat-font: var(--ui-font-lora); }
  body[data-font="merri"] { --ui-font: var(--ui-font-merri); --chat-font: var(--ui-font-merri); }
  body[data-font="jetmono"] { --ui-font: var(--ui-font-jetmono); --chat-font: var(--ui-font-jetmono); }
  body[data-font="plexmono"] { --ui-font: var(--ui-font-plexmono); --chat-font: var(--ui-font-plexmono); }
  /* Every named UI font takes over the whole chrome (most of the app hard-codes 'SF Mono'). */
  body[data-font="inter"] *, body[data-font="plexsans"] *,
  body[data-font="srcsans"] *, body[data-font="roboto"] *, body[data-font="opensans"] *,
  body[data-font="srcserif"] *, body[data-font="lora"] *, body[data-font="merri"] *,
  body[data-font="jetmono"] *, body[data-font="plexmono"] * { font-family: var(--ui-font) !important; }
  /* Sans/serif UI fonts restore monospace where alignment matters (code, terminal). Mono UI
     fonts (jetmono/plexmono) are left out — they keep the chosen mono in code too. */
  body[data-font="inter"] code, body[data-font="inter"] pre, body[data-font="inter"] kbd, body[data-font="inter"] samp,
  body[data-font="inter"] .xterm, body[data-font="inter"] .xterm *, body[data-font="inter"] .term-cursor, body[data-font="inter"] .job-dcmd,
  body[data-font="plexsans"] code, body[data-font="plexsans"] pre, body[data-font="plexsans"] kbd, body[data-font="plexsans"] samp,
  body[data-font="plexsans"] .xterm, body[data-font="plexsans"] .xterm *, body[data-font="plexsans"] .term-cursor, body[data-font="plexsans"] .job-dcmd,
  body[data-font="srcsans"] code, body[data-font="srcsans"] pre, body[data-font="srcsans"] kbd, body[data-font="srcsans"] samp,
  body[data-font="srcsans"] .xterm, body[data-font="srcsans"] .xterm *, body[data-font="srcsans"] .term-cursor, body[data-font="srcsans"] .job-dcmd,
  body[data-font="roboto"] code, body[data-font="roboto"] pre, body[data-font="roboto"] kbd, body[data-font="roboto"] samp,
  body[data-font="roboto"] .xterm, body[data-font="roboto"] .xterm *, body[data-font="roboto"] .term-cursor, body[data-font="roboto"] .job-dcmd,
  body[data-font="opensans"] code, body[data-font="opensans"] pre, body[data-font="opensans"] kbd, body[data-font="opensans"] samp,
  body[data-font="opensans"] .xterm, body[data-font="opensans"] .xterm *, body[data-font="opensans"] .term-cursor, body[data-font="opensans"] .job-dcmd,
  body[data-font="srcserif"] code, body[data-font="srcserif"] pre, body[data-font="srcserif"] kbd, body[data-font="srcserif"] samp,
  body[data-font="srcserif"] .xterm, body[data-font="srcserif"] .xterm *, body[data-font="srcserif"] .term-cursor, body[data-font="srcserif"] .job-dcmd,
  body[data-font="lora"] code, body[data-font="lora"] pre, body[data-font="lora"] kbd, body[data-font="lora"] samp,
  body[data-font="lora"] .xterm, body[data-font="lora"] .xterm *, body[data-font="lora"] .term-cursor, body[data-font="lora"] .job-dcmd,
  body[data-font="merri"] code, body[data-font="merri"] pre, body[data-font="merri"] kbd, body[data-font="merri"] samp,
  body[data-font="merri"] .xterm, body[data-font="merri"] .xterm *, body[data-font="merri"] .term-cursor, body[data-font="merri"] .job-dcmd {
    font-family: ui-monospace, 'SF Mono', 'IBM Plex Mono', monospace !important;
  }
  body[data-font="inter"] .appname, body[data-font="inter"] .appname *, body[data-font="inter"] .pw-wordmark, body[data-font="inter"] .bn-appname,
  body[data-font="plexsans"] .appname, body[data-font="plexsans"] .appname *, body[data-font="plexsans"] .pw-wordmark, body[data-font="plexsans"] .bn-appname,
  body[data-font="srcsans"] .appname, body[data-font="srcsans"] .appname *, body[data-font="srcsans"] .pw-wordmark, body[data-font="srcsans"] .bn-appname,
  body[data-font="roboto"] .appname, body[data-font="roboto"] .appname *, body[data-font="roboto"] .pw-wordmark, body[data-font="roboto"] .bn-appname,
  body[data-font="opensans"] .appname, body[data-font="opensans"] .appname *, body[data-font="opensans"] .pw-wordmark, body[data-font="opensans"] .bn-appname,
  body[data-font="srcserif"] .appname, body[data-font="srcserif"] .appname *, body[data-font="srcserif"] .pw-wordmark, body[data-font="srcserif"] .bn-appname,
  body[data-font="lora"] .appname, body[data-font="lora"] .appname *, body[data-font="lora"] .pw-wordmark, body[data-font="lora"] .bn-appname,
  body[data-font="merri"] .appname, body[data-font="merri"] .appname *, body[data-font="merri"] .pw-wordmark, body[data-font="merri"] .bn-appname,
  body[data-font="jetmono"] .appname, body[data-font="jetmono"] .appname *, body[data-font="jetmono"] .pw-wordmark, body[data-font="jetmono"] .bn-appname,
  body[data-font="plexmono"] .appname, body[data-font="plexmono"] .appname *, body[data-font="plexmono"] .pw-wordmark, body[data-font="plexmono"] .bn-appname {
    font-family: 'Brunea', 'Bitcount', monospace !important;
  }

  /* ── LIGHT THEME (Settings → Visuals → Theme) ────────────────────────────
     Toggled from renderer.js by writing data-theme="light" on <body>. This
     ONLY re-maps the neutral surface/line/text ramp — the burnt-orange Sol
     accent and every semantic/model color (Haiku green, Sonnet blue, error
     red, etc.) stay exactly as they are, so the app reads the same in both
     themes. Warm off-white surfaces to sit under the warm Sol accent. */
    /* LIGHT-MODE SHADOW DEPTH (John, 2026-08-24: "that drop shadow is too strong").
     Every depth shadow was authored as rgba(0,0,0,.4-.6) for the dark UI; on white
     that reads as a heavy smudge. Each alpha now flows through a --shNN variable so
     light mode can dial the SAME shadows down without touching geometry. Every one
     is pinned to .04 — the Context Card's level, which John picked as the standard
     for all floating surfaces (2026-08-24). --shEdge is separate: the two inset
     1px hairlines are outlines, not depth, so flattening must not erase them. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) {
    --sh8: 0.04;
    --sh12: 0.04;
    --sh18: 0.04;
    --sh22: 0.04;
    --sh28: 0.04;
    --sh30: 0.04;
    --sh32: 0.04;
    --sh35: 0.04;
    --sh40: 0.04;
    --sh50: 0.04;
    --sh55: 0.04;
    --sh60: 0.04;
    --sh62: 0.04;
    --shEdge: 0.16;
  }
  body[data-theme="white"]:not([data-preset]) {
    /* ALL-WHITE surfaces (John, 2026-07-25): "remove all the grays on the backgrounds,
       only use white and lines to separate." Every persistent surface fill is pure white;
       structure is carried by --line borders (sidebar has border-right, panels border-left,
       cards border), never by a gray fill. Interaction feedback (hover/active/selection)
       becomes a faint SOL tint instead of gray — so there is no gray background anywhere,
       yet rows still light up on hover/selection and stay on-brand. */
    /* WHITE, not gray (John, 2026-09-19: "I need the white mode to be WHITE. not gray."
       The 2026-09-02 warm-gray ramp is reverted: every persistent surface is pure
       #ffffff again and structure is carried by --line borders alone. The gray ramp
       still exists as the MEDIUM tone below, which is where a user who wants gray
       picks it. Interaction feedback stays a faint Sol tint, never a gray fill. */
    --bg: #ffffff;
    --panel: #ffffff;
    --panel-2: #ffffff;
    --sidebar: #ffffff;
    --line: #e2e1de;      /* separator — the only structure on white, so it stays visible */
    --text: #1c1c1a;
    --muted: #5c5b58;
    --faint: #8b8a86;
    --head-fade: rgba(255,255,255,.30);   /* fade toward the white canvas */
    /* accent + accent-soft inherit from :root — Sol stays Sol */
    --user: #ffffff;      /* user bubble is plain transparent text anyway */
    --tool: #ffffff;      /* tool block fill — reads via its --tool-line border */
    --tool-line: #e2e1de;
    --hover:  rgba(var(--accent-rgb), .07);   /* feedback = faint Sol tint, never gray */
    --active: rgba(var(--accent-rgb), .12);
    /* Branch-out gold: the dark-tuned --bo-txt/--bo-lt are near-WHITE golds, so on
       light surfaces they vanish (pale gold text on a pale gold fill — the "Branch
       out N of M" button, running chips, sidebar merge state, bo-lesson notes all
       read this way). Re-anchor to DEEP golds under light so every --bo-* surface
       becomes legible across the board in one place. Dark mode keeps the :root golds. */
    --bo-txt: #6f4a00;    /* readable deep-gold text on pale-gold/white */
    --bo-lt:  #946707;    /* glyphs / dots / carets — dark enough to see on light */
    /* FILL gold. The :root --bo-rgb (227,179,65) is a muddy tan that reads dull-brown as
       a solid pill on white (the Master Controller toggle, the "N" job badge) — John,
       2026-08-24: "UI yellows need to be more yellow, they are also muddy." Light mode
       gets a brighter, more saturated yellow-gold; dark keeps the :root value. */
    --bo-rgb: 245, 194, 24;
    /* Fathom blue: the near-white --fx-txt/--fx-lt vanish on white surfaces, so
       re-anchor to deeper Sonnet blues under the light theme (same fix as --bo-*). */
    --fx-txt: #2f5bc0;    /* readable deep-blue text on white */
    --fx-lt:  #2f6ad4;    /* glyphs / badges — dark enough to read on light */
  }
  /* LIGHT = the pale theme on soft warm-GRAY surfaces (John, 2026-08-24: "use these gray
     tones"). Every rule that styles a pale surface matches BOTH light and white (the
     :is() selectors above), so the dark-ink treatment and the light model colours apply
     here too; THIS block only swaps the white fills for the gray ramp. Panels/cards sit a
     shade lighter than the bg so the layers still read; lines darken to stay visible. */
  body[data-theme="light"]:not([data-preset]) {
    --text: #000000;
    --muted: #000000;
    --faint: #000000;
    --bg: #cacad0;
    --panel: #d2d2d8;
    --panel-2: #d8d8dc;
    --sidebar: #ceced1;
    --line: #adadb6;
    --tool: #d2d2d8;
    --tool-line: #adadb6;
    --head-fade: rgba(208,208,214,.30);
    /* BRIGHTER accent families than plain light (John, 2026-08-24: "all colors brighter").
       Light re-anchored these to DEEP tones for legibility on pure white; on the mid-gray
       those read muddy, so medium restores tones closer to the vivid :root/dark values. */
    --bo-rgb: 235, 183, 45;
    /* Measured on the gray ramp (worst surface #d8d8dc): the old values were 1.45:1 for
       the glyph gold and 2.77:1 for the gold text. These clear 3:1 and 4.5:1. */
    --bo-lt:  #8a5f00;   /* 3.46:1 */
    --bo-txt: #6f4a00;   /* 4.85:1 */
    --fx-txt: #24499b;   /* 5.15:1 */
    --fx-lt:  #2a52ad;   /* 4.42:1 */
  }
  /* The light-mode fixes below force pure #ffffff on specific cards; re-point the loudest
     ones to the medium panel gray so they don't read as bright-white islands on the gray. */
  body[data-theme="light"]:not([data-preset]) :is(.cmd-card, .cmd-copy, .ask-card, .note-card, .doc-card) { background: var(--panel); }
  /* Accent-outlined pills read low-contrast on the medium gray, so FILL them with the
     accent and use black text (John, 2026-08-24): the update pill, the Master Controller
     chip, and the layouts/folder button. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .sb-update { background: var(--accent); border-color: var(--accent); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) :is(.sb-update, .sb-update-ic, .sb-update-title, .sb-update-sub) { color: var(--on-accent); }
  body[data-theme="light"]:not([data-preset]) .layouts-btn { background: transparent; border-color: var(--line); }
  body[data-theme="light"]:not([data-preset]) .layouts-btn :is(.ly-lbl, .ly-caret) { color: #1a1a1a; }
  body[data-theme="light"]:not([data-preset]) .mc-chip { background: transparent; border-color: var(--line); }
  body[data-theme="light"]:not([data-preset]) .mc-chip :is(.mc-lbl, .mc-caret) { color: #1a1a1a; }
  /* Light-theme fixes for colors hardcoded OUTSIDE the variable ramp. Every rule
     here is scoped to body:is([data-theme="light"],[data-theme="white"]):not([data-preset]), so dark mode is untouched.
     Kept intentionally dark: the paywall brand overlay (.pw-*) and the terminal
     (#termBody) — both read as deliberate dark moments in a light app. */
  /* 1. Emphasis text that was pure #fff → invisible on light. Make it ink.
     (The #fff-on-orange cases — user bubbles, badges, accent buttons — are NOT
     listed here on purpose; white on Sol stays white.) */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .fname,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .subfolder-head .sf-name,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .folder.active .fname,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .row.session.current .sname,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pane-head .ptitle,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .row-menu-item.selected,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .set-nav-item.active,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .tab-chip.active,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .msg.assistant .md-h,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .msg.assistant strong,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pc-head,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pc-head .pc-x:hover { color: var(--text); }
  /* 2. Self-contained dark components that would otherwise float as dark islands
     in the light transcript. Re-themed to light while KEEPING their identity —
     the command card stays neutral gray, the question card stays blue. */
  /* 2a. Command card (was charcoal → was gray; now white + line, per the all-white rule). */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .cmd-card { background: var(--panel); border-color: var(--line); border-left-color: #c2c2c2; color: #3a3a3a; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .cmd-card:hover { background: var(--panel); border-color: rgba(var(--accent-rgb), .35); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .cmd-copy { background: var(--panel); border-color: var(--line); color: #545454; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .cmd-copy:hover,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .cmd-card:hover .cmd-copy { background: var(--hover); color: #2a2a2a; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .cmd-copy.copied { color: #127a57; border-color: #bfe3d2; background: #e3f4ec; }
  /* 2b. Question card + reply chip (was dark navy). Light-blue, identity intact. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .reply-chip { background: #eef3fd; border-color: #cdddf6; color: #3a496b; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .reply-chip .rc-q { color: #2d3f66; }
  /* 2b-2. Ask/question card + note/doc cards were all hardcoded #0f0f10 with no light
     variant, so they stayed near-black slabs on white (John, 2026-08-23). White surface,
     accent + text colours already come from vars so they carry over untouched. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) :is(.ask-card, .note-card, .doc-card) { background: var(--panel); border-color: var(--line); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .ask-head { border-bottom-color: var(--line); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .ask-q code { background: rgba(0,0,0,.055); color: var(--text); }
  /* Ghost buttons read as invisible outlines on white — give them a real surface. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) :is(.ask-btn, .ask-no) { background: var(--panel); border-color: var(--line); color: #545454; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) :is(.ask-btn:hover, .ask-no:hover) { background: var(--hover); color: #2a2a2a; }
  /* ...but Yes stays the FILLED primary — the rule above must not flatten it. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .ask-btn.ask-yes { background: var(--ac); border-color: var(--ac); color: #fff; font-weight: 700; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .ask-btn.ask-yes:hover { background: var(--ac); filter: brightness(1.08); color: #fff; }
  /* The docs viewer + its iframe were a fixed #0d0d0d panel. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) :is(.docs-view, .docs-frame) { background: var(--panel); }
  /* 2c. Notice pill (was dark → was gray; now white + line, per the all-white rule). */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .notice { background: var(--panel); border-color: var(--line); color: #5f5f5f; }
  /* Table headers set color:#fff, invisible now that --panel-2 is white → ink text. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .msg.assistant .md-table th { color: var(--text); }
  /* 2d. Inline code chip used rgba(255,255,255,.07) — invisible on light. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .msg.assistant code { background: rgba(0,0,0,.05); }
  /* 2e. Scrollbar thumb was a dark gray, then beige (#cfcabf). Neutral gray now. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) ::-webkit-scrollbar-thumb { background: rgba(0,0,0,.14); }
  /* 3. Black hover fills / black inputs → neutral light surfaces. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .row .x:hover,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .row .dots:hover,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .acct-item .rm:hover,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .acct-item .ow-sync:hover,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .tab-chip .tc-x:hover { background: var(--active); }
  /* Usage-meter labels were hardcoded color:#fff — white on the white account panel in
     light mode, i.e. invisible (John, 2026-08-24: "white on white NOBODY CAN READ").
     Dark ink in light mode; dark mode keeps its #fff. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .acct-limits .lim .k,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .acct-limits .lim .v,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .acct-limits .lim .rst { color: var(--text); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .rename-input,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .q-text:focus,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .q-bo-branch { background: var(--panel); }
  /* 4. Dark hover borders (#3a3a3a) → the light line color. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .row-menu-item.rm-rich:hover .rm-value,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pane-head .peffort.set,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pane-head .pcap.set,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .btn-ghost:hover,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pane-head .pfork:hover,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pane-head .pvariants:hover,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .tab-actions .pvariants:hover { border-color: var(--line); }
  /* 5. Phone-chat panel + assistant bubble were hardcoded dark. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pc-panel { background: var(--panel); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pc-msg.assistant { background: var(--panel-2); color: var(--text); }
  /* 6. FLIPPED (John, 2026-09-01): dark theme reads "focused = darker slab", but on
     light that read as dirty gray on the pane you're actually using. Light theme now
     goes the other way — the FOCUSED pane-head is clean white (the brightest surface),
     and unfocused panes carry a faint gray wash so they visibly recede. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pane-head { background: var(--panel); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pane.focused .pane-head { background: var(--panel); }
  /* A TINTED focused head keeps #1b1613 (dark) as its base in the shared rule — override
     it under light so the base stays light too, with the white head-fade on top. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pane.tinted .pane-head {
    background: linear-gradient(90deg, transparent 0%, var(--head-fade) 100%),
                linear-gradient(var(--pane-tint), var(--pane-tint)), color-mix(in srgb, var(--panel) 95%, #000);
  }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pane.tinted.focused .pane-head {
    background: linear-gradient(90deg, transparent 0%, var(--head-fade) 100%),
                linear-gradient(var(--pane-tint), var(--pane-tint)), var(--panel);
  }
  /* 7. Sidebar session names were WHITE (rgba(255,255,255,.x)) — white-on-cream.
     Flip to ink, keeping the current-session (full) vs others (~70%) hierarchy. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .active-row .sname { color: var(--text); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .session .sname { color: rgba(0,0,0,.7); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-name { color: var(--text); }   /* Open-branches name tracks the session-row ink in light theme */
  /* 8. Settings icon tiles used a 4.5% WHITE fill — invisible on a white panel.
     A faint dark tint makes the tile read again. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .set-ic { background: rgba(0,0,0,.04); }
  * { box-sizing: border-box; margin: 0; padding: 0; }
  html, body { height: 100%; }
  body {
    background: var(--bg);
    color: var(--text);
    font-family: var(--ui-font);
    font-size: 14px;
    display: flex; flex-direction: column;
    height: 100vh; overflow: hidden;
    /* macOS renders text heavy by default (subpixel); antialiased = lighter, crisper */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }
  /* UI chrome is never selectable — dragging across buttons/labels/sidebar selects
     nothing. Only real content (the transcript) and inputs opt back in, so replies
     stay copyable. */
  * { -webkit-user-select: none; user-select: none; }
  /* Opt real content back in — AND its descendants. Assistant replies are rich HTML
     (<p>, <code>, <li>, <pre>…); the universal none above hits those nested nodes
     directly, so without the * here only plain text bubbles were selectable. */
  .pane-body, .pane-body *, .msg, .a-text, .a-text *,
  .pc-thread, .pc-thread *, .pc-msg, .pc-msg *,
  textarea, input, [contenteditable], .selectable {
    -webkit-user-select: text; user-select: text;
  }
  /* while dragging a selection inside one pane, the OTHER panes go unselectable, so
     a drag can never cross from one session into another */
  .pane-body.no-select, .pane-body.no-select * { -webkit-user-select: none; user-select: none; }

  header {
    -webkit-app-region: drag;
    height: 46px; flex: 0 0 auto;
    display: flex; align-items: center; gap: 12px;
    /* Left inset MATCHES the gap between the left-group squares (John, 2026-08-18):
       collapse → status is 12px gap minus the -8px pull below = 4px, so the sidebar
       button sits 4px off the edge too. Right side keeps its 14px. */
    padding: 0 14px 0 4px;
    border-bottom: 1px solid var(--line);
    background: var(--panel);
  }
  /* The right-hand tool cluster (// · tasks · tidy · terminal · Layouts) sits half as
     far apart as the rest of the header — 6px, not the header's 12px. Targeted rather
     than dropping the header gap, so the left group (sidebar toggle, status dot, Master
     Controller chip) keeps its breathing room. (John, 2026-08-16.) */
  header .icon-btn + .icon-btn,
  header .icon-btn + .layouts-ctl { margin-left: -6px; }
  .hdr-sep { flex: 0 0 auto; width: 1px; height: 14px; background: var(--line); margin: 0 6px; align-self: center; }   /* top-bar divider (John, 2026-09-24) */
  /* The left group's squares sit MUCH closer too (John, 2026-08-18) — the header's own
     12px gap left them floating apart. Pull the pair together and snug the MC chip up
     to them, so collapse · status · Master Controller read as one tight cluster. */
  header .collapse-btn + .claude-status { margin-left: -8px; }
  header .claude-status + .mc-chip { margin-left: -6px; }
  .icon-btn {
    -webkit-app-region: no-drag;
    background: transparent; color: var(--muted);
    border: 1px solid var(--line); border-radius: 3px;
    /* 28x28 square — same box as the collapse + status buttons on the left, so every
       header button is one identical square (John, 2026-08-18). Was 30x28. */
    width: 28px; height: 28px; box-sizing: border-box; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    font-size: 13px; line-height: 1;
  }
  .icon-btn:hover { color: var(--accent); background: var(--hover); }
  /* Shortcuts button: top-left of the header (opposite the checklist/tidy/terminal
     cluster on the right). Opens a searchable palette of every / and // command. */
  .shortcuts-btn {
    -webkit-app-region: no-drag; font-family: "SF Mono", ui-monospace, monospace;
    font-weight: 700; font-size: 12px; letter-spacing: .3px;
  }
  .shortcuts-btn:hover { color: var(--accent); }
  /* Action-list button: a checklist icon in the top bar with a gold count badge of
     how many things you still have to do. Its own gold accent (matches Action cards). */
  .action-list-btn { position: relative; -webkit-app-region: no-drag; }
  .action-list-btn:hover { color: #e3b341; }
  .action-list-btn.active { color: #e3b341; border-color: rgba(227,179,65,.5); background: rgba(227,179,65,.08); }
  .al-badge {
    display: none; position: absolute; top: -5px; right: -5px; min-width: 15px; height: 15px;
    padding: 0 3px; box-sizing: border-box; border-radius: 3px; background: var(--accent); color: var(--on-accent);
    font-size: 9.5px; font-weight: 800; line-height: 15px; text-align: center;
  }
  .al-badge.show { display: block; }
  /* /Luminair wordmark: each LETTER glitches on its own, with one of several
     effects and its own timing — subtle, never the whole word. (Same as mobile.)
     Two-tone lockup: "Over" neutral, "Watch" in the accent orange. */
  .appname {
    font-family: 'Brunea', 'Bitcount', monospace;   /* LOGO stays Brunea — not a title (John, 2026-08-24) */
    font-size: 18px; letter-spacing: 1px; font-weight: 700;
    text-transform: uppercase; line-height: 1; user-select: none;
    color: var(--text);
    filter: none;
    flex: 0 0 auto; white-space: nowrap; overflow: visible;  /* never shrink / wrap / clip the wordmark */
  }
  .appname .gl, .pw-wordmark .gl { position: relative; display: inline-block; }
  /* ONE brand color — the ENTIRE /LUMINAIR wordmark is brand orange, full stop.
     No two-tone, no gray, no white split. Both spans render `--accent` (John, 2026-07-26). */
  .appname .gl-neutral, .pw-wordmark .gl-neutral,
  .appname .gl-accent,  .pw-wordmark .gl-accent { color: var(--accent); }
  /* effect 1 — chromatic split: faint red/cyan clones flick offset for an instant */
  .gl-rgb::before, .gl-rgb::after {
    content: attr(data-ch); position: absolute; left: 0; top: 0; pointer-events: none; opacity: 0;
  }
  .gl-rgb::before { color: #ff2d2d; }
  .gl-rgb::after { color: #29d3ff; }
  @media (prefers-reduced-motion: no-preference) {
    .gl-rgb::before { animation: glRgbA 6.5s steps(1, end) infinite; animation-delay: inherit; }
    .gl-rgb::after { animation: glRgbB 6.5s steps(1, end) infinite; animation-delay: inherit; }
    .gl-jitter { animation: glJitter 5s steps(1, end) infinite; }
    .gl-skew { animation: glSkew 5.5s steps(1, end) infinite; }
    .gl-flick { animation: glFlick 7s steps(1, end) infinite; }
    .gl-slice { animation: glSlice 6s steps(1, end) infinite; }
  }
  /* Resource discipline: when the window is hidden (minimized / another Space),
     EVERY animation pauses: zero draw work in the background. When it's visible
     but not the focused app, only the decorative logo-glitch stack pauses; live
     status (thinking scanner, pulsing dots) keeps moving so nothing looks hung. */
  body.app-hidden *, body.app-hidden *::before, body.app-hidden *::after { animation-play-state: paused !important; }
  @media (prefers-reduced-motion: no-preference) {
    body.app-blur .gl-rgb::before, body.app-blur .gl-rgb::after,
    body.app-blur .gl-jitter, body.app-blur .gl-skew,
    body.app-blur .gl-flick, body.app-blur .gl-slice { animation-play-state: paused !important; }
  }
  @keyframes glRgbA {
    0%, 95%, 100% { opacity: 0; transform: translate(0, 0); }
    96% { opacity: 0.5; transform: translate(-1px, 0); }
    97.5% { opacity: 0.32; transform: translate(1px, 0); }
    98.5% { opacity: 0; }
  }
  @keyframes glRgbB {
    0%, 95%, 100% { opacity: 0; transform: translate(0, 0); }
    96% { opacity: 0.45; transform: translate(1px, 0); }
    97.5% { opacity: 0.28; transform: translate(-1px, 0); }
    98.5% { opacity: 0; }
  }
  @keyframes glJitter {
    0%, 92%, 100% { transform: translateY(0); }
    93% { transform: translateY(-1px); }
    95% { transform: translateY(1px); }
    97% { transform: translateY(0); }
  }
  @keyframes glSkew {
    0%, 90%, 100% { transform: skewX(0); }
    92% { transform: skewX(-6deg); }
    94% { transform: skewX(4deg); }
    96% { transform: skewX(0); }
  }
  @keyframes glFlick {
    0%, 88%, 100% { opacity: 1; }
    89% { opacity: 0.45; }
    90% { opacity: 0.9; }
    91% { opacity: 0.4; }
    92% { opacity: 1; }
  }
  /* Animation off: the letter itself shows in one solid brand color; the red/cyan
     chromatic-split clones (::before/::after) must stay HIDDEN, not frozen visible —
     opacity:1 on them left the V/T tinted red/cyan (John, 2026-09-09). */
  body.no-logo-anim .gl { animation: none !important; opacity: 1; }
  body.no-logo-anim .gl::before, body.no-logo-anim .gl::after { animation: none !important; opacity: 0 !important; }
  @keyframes glSlice {
    0%, 90%, 100% { clip-path: inset(0 0 0 0); transform: translateX(0); }
    92% { clip-path: inset(35% 0 42% 0); transform: translateX(1px); }
    94% { clip-path: inset(62% 0 8% 0); transform: translateX(-1px); }
    96% { clip-path: inset(0 0 0 0); transform: translateX(0); }
  }
  header .spacer { flex: 1; }
  /* Brand wordmark pinned to the header's top-right corner (John, 2026-07-29). */
  /* Wordmark lives at the top-right INSIDE the side panel (John, 2026-07-30).
     .side-top is space-between: collapse toggle left, wordmark right. */
  /* Top-ALIGNED, not centered (John, 2026-07-30): the wordmark pins to the very top
     of the side panel. .side-top's 30px top padding exists only to clear the macOS
     traffic lights, which sit on the LEFT — so the right-side wordmark shouldn't pay
     for it. Absolute-positioning it out of the flex row lets it sit at the top edge
     while the collapse button keeps its own centered position. */
  .side-top .appname {
    /* RIGHT-aligned again (John, 2026-08-18) — the custom window controls now own the
       top-left corner. 10% smaller: 24.7 → 22.2px. */
    position: absolute; top: 10px; right: 14px; left: auto;
    font-size: 22.2px; line-height: 1; -webkit-app-region: no-drag;
  }
  /* Custom window controls — two small squares pinned to the very top-left, where the
     native traffic lights used to be (John, 2026-08-18). no-drag so they click, not drag. */
  /* Windows draws its own native minimize/close in the frame (titleBarStyle hiddenInset is
     macOS-only), so the custom squares would be a second X and minus a few pixels below
     the real ones. Hide them there, in the main window and the pop-out alike
     (John, 2026-09-09: "Remove X and - on windows"). */
  /* Reverted 2026-09-25: Windows now hides its native caption bar like the Mac build
     ("Can't it be like mac?"), so these squares are the only close/minimize there too. */
  body.ftu-mode .main > .win-ctrls {
    position: absolute; top: 9px; left: 12px; z-index: 6;
    display: inline-flex; gap: 6px; -webkit-app-region: no-drag;
  }
  body.ftu-mode .main > header { padding-left: 64px; }
  .side-top .win-ctrls {
    position: absolute; top: 9px; left: 12px; z-index: 2;
    display: inline-flex; gap: 6px; -webkit-app-region: no-drag;
  }
  .win-ctrl {
    display: inline-flex; align-items: center; justify-content: center;
    box-sizing: border-box; line-height: 0;
    width: 16px; height: 16px; padding: 0; border-radius: 3px;
    border: 1px solid var(--line); background: transparent;
    color: var(--faint); cursor: pointer; -webkit-app-region: no-drag;
    transition: background .12s ease, color .12s ease, border-color .12s ease;
  }
  .win-ctrl svg { display: block; margin: auto; }
  .win-close:hover { background: #e0554a; border-color: #e0554a; color: #fff; }
  .win-min:hover   { background: #e3b341; border-color: #e3b341; color: #1a1a1a; }
  /* The compact /OW mark only exists for the collapsed rail — hidden while expanded. */
  .side-top .appname-short { display: none; }
  /* Collapsed sidebar is a narrow 56px rail: drop the full wordmark, show the /OW mark
     centered in the rail instead (John, 2026-07-31). */
  body.collapsed .side-top #appName { display: none; }
  body.collapsed .side-top .appname-short {
    display: block; right: auto; left: 0; text-align: center; width: 100%;
  }
  header .txt-btn {
    -webkit-app-region: no-drag;
    background: var(--panel-2); color: var(--text);
    border: 1px solid var(--line); border-radius: 3px;
    padding: 5px 11px; font-size: 12.5px; cursor: pointer;
  }
  header .txt-btn:hover { background: var(--hover); }

  /* Text-size setting scales the WHOLE interface via Chromium's NATIVE page zoom
     (webContents.setZoomFactor, driven by applySize() in renderer.js), NOT CSS zoom.
     FREEZE FIX (John, 2026-09-01: "app freezes every minute"): CSS `zoom` on this
     container made the compositor re-rasterize the entire scaled layer on every
     repaint — a streaming reply repaints constantly, pegging the GPU process at 100%
     (measured live) and freezing the app. Native page zoom is compositor-integrated
     and costs what Chrome's own Cmd+/- zoom costs: nothing noticeable. */
  .body-row { flex: 1; display: flex; min-height: 0; }

  /* ---- sidebar (collapsible) ---- */
  aside {
    /* Whole sidebar in the title font (John, 2026-08-24: "all of this should be the new
       font") — sessions, folders, section headers, counts. The .appname wordmark keeps
       its own Brunea via its explicit rule. */
    font-family: var(--ui-font, ui-monospace), monospace;
    width: var(--sidebar-w, 258px); flex: 0 0 auto;
    background: var(--sidebar);
    border-right: 1px solid var(--line);
    display: flex; flex-direction: column; min-height: 0;
    transition: width .16s ease, opacity .16s ease;
    overflow: hidden;
    user-select: none; -webkit-user-select: none; /* dragging never selects text */
  }
  /* Top-level FOLDER names keep the new title font (Monorama, inherited from aside).
     Sessions and SUBFOLDER names use the settings-selected interface font (John,
     2026-08-24: "folders get the new custom font, sub-folders the selected font"). */
  aside :is(.sname, .sf-name) {
    font-family: var(--ui-font, ui-monospace), monospace; text-transform: none;
  }
  /* HARD FLOOR so the /LUMINAIR wordmark can never be clipped, no matter what a
     stale/rogue width value (from the two resize paths) tries to set. Only when
     expanded — the collapsed rail is deliberately 56px. (John, 2026-07-25: logo
     showed "/OVERWATC…" because the sidebar had gone narrower than the wordmark.) */
  body:not(.collapsed) aside { min-width: 208px; }
  /* drag the border to resize the sidebar; double-click to reset */
  /* Straddle the seam with ZERO net layout width: -3px each side pulls the 6px grab strip
     over the sidebar/pane boundary so it takes no flex space of its own. It used to have
     only margin-left:-3px, leaving a 3px body-colour gap (white in light mode) between the
     sidebar and the first pane (John, 2026-08-24: "kill it"). Grab zone is unchanged. */
  .side-resizer { flex: 0 0 auto; width: 6px; margin-left: -3px; margin-right: -3px; cursor: col-resize; z-index: 6; background: transparent; transition: background .12s ease; }
  .side-resizer:hover, body.resizing .side-resizer { background: var(--accent-soft); }
  body.resizing { cursor: col-resize; user-select: none; -webkit-user-select: none; }
  body.resizing aside { transition: none; }   /* follow the cursor with no lag while dragging */
  /* While the OS window is being dragged-resized, freeze the expensive per-frame
     paints (backdrop blur + every transition) so the drag stays smooth. The class
     is added on the first resize tick and removed ~140ms after the last one, so
     the freeze is invisible except during an active drag. */
  body.win-resizing *, body.win-resizing *::before, body.win-resizing *::after {
    transition-duration: 0s !important; transition-delay: 0s !important; }
  body.win-resizing * { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
  body.collapsed .side-resizer { display: none; }
  /* sidebar-owned top bar: LUMINAIR (left) + collapse button (right) */
  /* Sidebar top strip: now holds ONLY the /Luminair wordmark (absolute, top-right).
     The collapse toggle moved to the app header, and the macOS traffic lights were
     removed (John, 2026-07-31) — so the old 30px top clearance is gone. min-height
     matches the header's 46px so the two top bars line up across the split. */
  .side-top {
    -webkit-app-region: drag;   /* the top strip drags the window (traffic lights removed) */
    position: relative;         /* anchor for the top-aligned wordmark */
    flex: 0 0 auto; min-height: 46px;
    padding: 0 10px 0 14px;
    border-bottom: 1px solid var(--line);
  }
  /* (Removed the top-bar "Update now" logo chip — the sidebar update card at the
     bottom (#sbUpdate) is now the single place that signals a staged/ready update.) */

  /* ---- Automations: one-click saved plans at the bottom-left of the sidebar ---- */
  /* Row = fixed status dot + flexible name/summary (ellipsis) + fixed notice/delete.
     Screen-width discipline (Elion Part 2): the text gets flex:1 + min-width:0; the
     fixed siblings get flex-shrink:0. John's dot colors: GRAY idle · ORANGE working ·
     GREEN done · RED errored — note idle is deliberately gray here (the Active-Sessions
     idle dot is green; automations are different). */
  .automations-wrap { flex: 0 0 auto; border-top: 1px solid var(--line); padding-bottom: 4px; }
  .automations-wrap .sec-head { cursor: default; }
  .auto-list { display: flex; flex-direction: column; padding: 0 6px 2px; max-height: 34vh; overflow-y: auto; }
  .auto-row {
    display: flex; align-items: center; gap: 8px; padding: 6px 6px; border-radius: 3px;
    cursor: pointer; min-width: 0;
  }
  .auto-row:hover { background: var(--hover); }
  .auto-dot { flex: 0 0 8px; align-self: center; width: 8px; height: 8px; min-width: 8px; max-width: 8px; min-height: 8px; max-height: 8px; aspect-ratio: 1 / 1; box-sizing: border-box; border-radius: 50%; background: var(--muted); opacity: .8; }
  .auto-dot.idle { background: var(--muted); opacity: .7; }          /* GRAY — inactive */
  .auto-dot.working { background: var(--dot-work); opacity: 1; animation: micpulse 1.1s ease-in-out infinite; }  /* ORANGE (fixed, not accent) */
  .auto-dot.done { background: #45e3b0; opacity: 1; padding: 0; align-self: center; }  /* GREEN — padding:0/align-self reassert beats the generic bare `.done` chat rule that would pill-distort it */
  .auto-dot.error { background: #e0554a; opacity: 1; }               /* RED */
  .auto-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
  .auto-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--text); }
  .auto-sum { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--faint); font-size: 9px; }
  .auto-notice {
    flex: 0 0 auto; width: 16px; height: 16px; border-radius: 50%; border: none; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 10px; font-weight: 800; color: #fff; line-height: 1;
    background: #e0554a; animation: micpulse 1.3s ease-in-out infinite;
  }
  .auto-notice.question { background: var(--accent); }
  .auto-del {
    flex: 0 0 auto; width: 18px; height: 18px; border-radius: 3px; border: none; cursor: pointer;
    background: transparent; color: var(--faint); font-size: 15px; line-height: 1; padding: 0;
    display: none; align-items: center; justify-content: center;
  }
  .auto-row:hover .auto-del { display: inline-flex; }
  .auto-del:hover { color: #e0554a; background: var(--hover); }
  body.collapsed #automationsWrap { display: none; }
  /* Background Jobs panel (background-agents) — reuses the Automations row structure
     (.auto-list/.auto-row/.auto-dot/.auto-meta/.auto-name/.auto-sum) so it reads as
     the same system, plus a small per-job kind chip (Bash / Workflow). */
  body.collapsed #jobsWrap { display: none; }
  .jobs-wrap { border-top: 1px solid var(--line); }
  .jobs-wrap .sec-head { cursor: default; display: flex; align-items: baseline; gap: 6px; min-width: 0; }
  .jobs-wrap .sec-head .job-count { color: var(--faint); font-size: 9px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .job-kind { flex: 0 0 auto; font-size: 8px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; color: var(--faint); background: var(--hover); border-radius: 3px; padding: 1px 4px; align-self: center; }
  .job-row.done .auto-name, .job-row.stale .auto-name, .job-row.cancelled .auto-name { color: var(--muted); }
  .job-act { flex: 0 0 auto; display: none; align-items: center; justify-content: center; width: 20px; height: 20px; padding: 0; border: 0; background: transparent; color: var(--muted); cursor: pointer; border-radius: 3px; font-size: 12px; line-height: 1; }
  .auto-row:hover .job-act { display: inline-flex; }
  .job-act:hover { background: var(--hover); color: var(--text); }
  .job-act.danger:hover { color: #e0554a; }
  /* Drill-in: a job = its row + (when open) a full detail panel below it. */
  .job-item { border-radius: 3px; }
  .job-item.expanded { background: rgba(var(--bo-rgb), .06); box-shadow: inset 0 0 0 1px rgba(var(--bo-rgb), .16); }
  .job-caret { flex: 0 0 auto; align-self: center; color: var(--faint); font-size: 14px; line-height: 1; transition: transform .15s ease, color .15s ease; }
  .job-item.expanded .job-row .job-caret { transform: rotate(90deg); color: var(--bo-lt); }
  .auto-row:hover .job-caret { color: var(--muted); }
  .job-detail { padding: 3px 11px 12px 24px; font-size: 11px; animation: jobDetailIn .14s ease; }
  @keyframes jobDetailIn { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }
  /* Brief attention flash when an action lands on an already-open pane (Open session). */
  .pane-ping { animation: panePing .85s ease-out 1; }
  @keyframes panePing { 0% { box-shadow: none; } 100% { box-shadow: inset 0 0 0 2px transparent; } }
  .job-dtitle { font-weight: 700; color: var(--text); margin-bottom: 9px; line-height: 1.35; overflow-wrap: anywhere; }
  .job-dgrid { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; align-items: baseline; }
  .job-dk { color: var(--faint); white-space: nowrap; font-size: 10.5px; }
  .job-dv { color: var(--muted); min-width: 0; overflow-wrap: anywhere; }
  .job-dcmd { margin-top: 9px; font-family: ui-monospace, 'SF Mono', monospace; font-size: 10.5px; color: var(--bo-txt); background: rgba(var(--bo-rgb), .08); border: 1px solid rgba(var(--bo-rgb), .2); border-radius: 3px; padding: 6px 8px; overflow-wrap: anywhere; white-space: pre-wrap; }
  .job-dresult { margin-top: 10px; }
  .job-dtext { margin-top: 4px; color: var(--muted); overflow-wrap: anywhere; white-space: pre-wrap; max-height: 170px; overflow-y: auto; line-height: 1.45; }
  .job-dacts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
  .job-dbtn { flex: 0 0 auto; font-size: 10.5px; font-weight: 600; color: var(--bo-txt); background: rgba(var(--bo-rgb), .1); border: 1px solid rgba(var(--bo-rgb), .32); border-radius: 3px; padding: 4px 10px; cursor: pointer; -webkit-app-region: no-drag; }
  .job-dbtn:hover { background: rgba(var(--bo-rgb), .2); }
  .job-dbtn.danger { color: var(--muted); background: var(--hover); border-color: var(--line); }
  .job-dbtn.danger:hover { color: #e0554a; border-color: rgba(224,85,74,.5); }
  /* Progress strip under a running job (John, 2026-08-31). Determinate when the job
     reports a real %, indeterminate barber-pole + live elapsed when it can't. */
  .job-item.running { background: rgba(var(--bo-rgb), .05); box-shadow: inset 0 0 0 1px rgba(var(--bo-rgb), .12); }
  .job-prog { display: flex; align-items: center; gap: 8px; padding: 0 11px 8px 24px; }
  .job-prog-track { position: relative; flex: 1 1 auto; height: 4px; border-radius: 3px; background: rgba(var(--bo-rgb), .16); overflow: hidden; }
  .job-prog-fill { height: 100%; border-radius: 3px; background: var(--bo-lt); transition: width .3s ease; }
  .job-prog-pct { flex: 0 0 auto; font-size: 10px; font-variant-numeric: tabular-nums; color: var(--bo-txt); min-width: 30px; text-align: right; }
  .job-prog.indet .job-prog-fill { width: 40%; border-radius: 3px; background: linear-gradient(90deg, transparent, var(--bo-lt), transparent); animation: jobIndet 1.15s ease-in-out infinite; }
  .job-prog.wait .job-prog-track { background: rgba(128,128,128,.14); }
  .job-prog.wait .job-prog-fill { width: 100% !important; animation: none; opacity: .42; background: repeating-linear-gradient(135deg, var(--muted) 0 5px, transparent 5px 10px); }
  .job-prog.wait .job-prog-pct { color: var(--muted); min-width: 42px; }
  @keyframes jobIndet { 0% { transform: translateX(-120%); } 100% { transform: translateX(320%); } }
  /* Session Controller ledger — mirrors the automations panel. Dot colors come from
     the shared contract (owm-controller.js STATUS_COLORS): gray open · orange in-progress
     · blue done · teal tested · green confirmed · red blocked/dropped. */
  .controller-wrap { flex: 0 0 auto; border-top: 1px solid var(--line); padding-bottom: 4px; }
  .controller-wrap .sec-head { cursor: default; display: flex; align-items: baseline; gap: 6px; min-width: 0; }
  .controller-wrap .sec-head .ctl-count { color: var(--faint); font-size: 9px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ctl-list { display: flex; flex-direction: column; padding: 0 6px 2px; max-height: 34vh; overflow-y: auto; }
  .ctl-row {
    display: flex; align-items: center; gap: 8px; padding: 6px 6px; border-radius: 3px;
    cursor: pointer; min-width: 0;
  }
  .ctl-row:hover { background: var(--hover); }
  .ctl-row.confirmed { opacity: .55; }                               /* confirmed collapses/grays */
  .ctl-dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; background: #8a8a8a; opacity: .85; }
  .ctl-dot.open { background: #8a8a8a; opacity: .7; }                /* GRAY — captured, not started */
  .ctl-dot.in-progress { background: #ff6a44; opacity: 1; animation: micpulse 1.1s ease-in-out infinite; }  /* ORANGE working */
  .ctl-dot.done { background: #4a78c0; opacity: 1; }                 /* BLUE — claims complete, untested */
  .ctl-dot.tested { background: #2fa3a3; opacity: 1; }              /* TEAL — evidence attached */
  .ctl-dot.confirmed { background: #3ba55d; opacity: 1; }          /* GREEN — John confirmed */
  .ctl-dot.blocked, .ctl-dot.dropped { background: #d04a3a; opacity: 1; }  /* RED — needs John / fell off */
  .ctl-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--text); }
  .ctl-notice {
    flex: 0 0 auto; width: 16px; height: 16px; border-radius: 50%; border: none; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 10px; font-weight: 800; color: #fff; line-height: 1;
    background: #e0554a; animation: micpulse 1.3s ease-in-out infinite;
  }
  .ctl-notice.question { background: var(--accent); }
  .ctl-confirm {
    flex: 0 0 auto; width: 18px; height: 18px; border-radius: 3px; border: none; cursor: pointer;
    background: transparent; color: var(--faint); font-size: 13px; line-height: 1; padding: 0;
    display: none; align-items: center; justify-content: center;
  }
  .ctl-row:hover .ctl-confirm { display: inline-flex; }
  .ctl-confirm:hover { color: #3ba55d; background: var(--hover); }
  .ctl-del {
    flex: 0 0 auto; width: 18px; height: 18px; border-radius: 3px; border: none; cursor: pointer;
    background: transparent; color: var(--faint); font-size: 15px; line-height: 1; padding: 0;
    display: none; align-items: center; justify-content: center;
  }
  .ctl-row:hover .ctl-del { display: inline-flex; }
  .ctl-del:hover { color: #e0554a; background: var(--hover); }
  /* AUDIT FIX V-M1: the 🔍 manual re-verify the settings card promises. Same reveal
     pattern as ✓/×: hidden until the row is hovered. */
  .ctl-reverify {
    flex: 0 0 auto; width: 18px; height: 18px; border-radius: 3px; border: none; cursor: pointer;
    background: transparent; color: var(--faint); font-size: 11px; line-height: 1; padding: 0;
    display: none; align-items: center; justify-content: center;
  }
  .ctl-row:hover .ctl-reverify { display: inline-flex; }
  .ctl-reverify:hover { color: var(--accent); background: var(--hover); }
  /* MC improvement #2: verify-history chip — the last verdicts as a ✓✗ pattern.
     Always visible (the pattern IS the signal), reasons in the tooltip / on tap. */
  .ctl-vh {
    flex: 0 0 auto; height: 18px; border-radius: 3px; border: none; cursor: pointer;
    background: transparent; color: var(--faint); font-size: 10px; line-height: 1;
    padding: 0 3px; letter-spacing: 1px; display: inline-flex; align-items: center; justify-content: center;
  }
  .ctl-vh:hover { color: var(--accent); background: var(--hover); }
  body.collapsed #controllerWrap { display: none; }
  /* ── MASTER controller: the always-visible on/off switch + "Controlling" state ── */
  .ctl-head { display: flex; align-items: center; gap: 6px; }
  .ctl-head .ctl-title { flex: 0 0 auto; }
  .ctl-head .ctl-count { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Gold "Controlling" word in the sidebar header — no dot now (the ON signal is the
     pulsing yellow MC chip up by "//"). The on/off switch also moved to that chip. */
  .ctl-status { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px; color: var(--bo-txt); font-size: 10px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase; }
  .ctl-empty { padding: 4px 8px 8px; color: var(--faint); font-size: 11px; line-height: 1.35; overflow-wrap: anywhere; }
  /* Master ON: the controller panel takes the gold signature so it reads as live. */
  body.controller-on #controllerWrap { border-top-color: rgba(var(--bo-rgb), .5); box-shadow: inset 0 1px 0 rgba(var(--bo-rgb), .12); }
  body.controller-on #controllerWrap .ctl-title { color: var(--bo-txt); }

  /* MC chip — the ONE global Master Controller switch, in the header next to "//".
     A small yellow "MC" label + a toggle; when ON the toggle glows and PULSES (no
     separate dot). Replaces the per-session controller toggles + the sidebar switch. */
  /* Claude platform status — one dot in the header, immediately left of Master
     Controller, colored off status.claude.com (none=green, minor=amber,
     major=orange, critical=red pulsing, unknown/offline=grey). Click → status page. */
  /* It IS clickable (opens status.claude.com), so it should LOOK clickable — a bordered
     square box like every other header control, not a bare floating dot (John, 2026-08-16).
     Sized to .collapse-btn beside it. */
  .claude-status { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; box-sizing: border-box; padding: 0; margin-right: 0; border: 1px solid var(--line); background: transparent; border-radius: 3px; cursor: pointer; -webkit-app-region: no-drag; }
  .claude-status:hover { background: var(--hover); border-color: var(--accent); }
  .cs-dot { width: 9px; height: 9px; border-radius: 50%; background: #6b7280; transition: background .2s, box-shadow .2s; }
  .claude-status.s-none .cs-dot     { background: #3fb950; box-shadow: none; }
  .claude-status.s-minor .cs-dot    { background: #e3b341; box-shadow: none; }
  .claude-status.s-major .cs-dot    { background: #f0883e; box-shadow: none; }
  .claude-status.s-critical .cs-dot { background: #f85149; box-shadow: none; animation: csPulse 1.3s ease-in-out infinite; }
  .claude-status.s-unknown .cs-dot  { background: #6b7280; box-shadow: none; }
  @keyframes csPulse { 0%,100%{opacity:1} 50%{opacity:.4} }

  /* Master Controller wears the custom ACCENT, not the branch-out gold (John, 2026-08-24:
     "make the master controller also the custom color. All cards etc."). Re-scoping the
     --bo family to the accent on every MC container cascades to the chip, toggle, log pop,
     report card, notice and master card — while leaving jobs/branch-out gold untouched. */
  .mc-chip, #controllerWrap, .mc-pop, .mc-log-pop, .mcr-card {
    --bo-rgb: var(--accent-rgb); --bo: var(--accent); --bo-lt: var(--accent); --bo-txt: var(--accent);
  }
  .mc-chip { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px; padding: 3px 5px 3px 9px; border-radius: 3px; border: 1px solid var(--line); background: transparent; transition: border-color .15s, background .15s; -webkit-app-region: no-drag; }
  .mc-chip:hover { border-color: rgba(var(--bo-rgb), .6); }
  .mc-lbl { font-size: 11px; font-weight: 800; letter-spacing: .04em; color: var(--muted); transition: color .15s; cursor: pointer; white-space: nowrap; }
  .mc-chip:hover .mc-lbl { color: var(--bo-txt); }
  /* the switch is now a separate click target (clicking the label opens the panel instead) */
  .mc-switch { display: inline-flex; cursor: pointer; padding: 1px; border-radius: 999px; }
  .mc-track { width: 30px; height: 17px; border-radius: 999px; background: var(--line); position: relative; transition: background .15s, box-shadow .2s; flex: 0 0 auto; }
  .mc-track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px; border-radius: 50%; background: #cfcfcf; transition: transform .15s, background .15s; }
  .mc-chip.on .mc-lbl { color: var(--bo-txt); }
  .mc-chip.on { border-color: rgba(var(--bo-rgb), .7); background: rgba(var(--bo-rgb), .1); }
  .mc-chip.on .mc-track { background: var(--bo); animation: mcTrackPulse 1.4s ease-in-out infinite; }
  .mc-chip.on .mc-track::after { transform: translateX(13px); background: #fff; }
  @keyframes mcTrackPulse {
    0%, 100% { box-shadow: none; }
    50%      { box-shadow: none; }
  }
  /* Caret that opens the activity dropdown — "what MC has done". */
  .mc-caret { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; padding: 0; border: none; background: transparent; color: var(--muted); cursor: pointer; border-radius: 3px; transition: color .15s, background .15s, transform .18s; -webkit-app-region: no-drag; }
  .mc-caret:hover { color: var(--bo-txt); background: rgba(var(--bo-rgb), .14); }
  .mc-chip.on .mc-caret { color: var(--bo-txt); }
  .mc-caret.open { transform: rotate(180deg); }
  /* Activity dropdown — the list of actions MC took. */
  .mc-log-pop { position: fixed; z-index: 4000; width: 380px; max-height: 70vh; overflow-y: auto; background: var(--panel-2, #161616); border: 1px solid var(--line); border-radius: 3px; box-shadow: 0 14px 44px rgba(0,0,0,var(--sh50, .5)); padding: 8px; font-size: 12px; -webkit-app-region: no-drag; }
  .mc-log-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 4px 6px 8px; border-bottom: 1px solid var(--line); margin-bottom: 4px; }
  .mc-log-title { font-weight: 800; font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--bo-txt); }
  .mc-log-clear { border: none; background: transparent; color: var(--muted); font-size: 11px; cursor: pointer; padding: 2px 4px; border-radius: 3px; }
  .mc-log-clear:hover { color: var(--txt); background: rgba(255,255,255,.06); }
  .mc-log-empty { padding: 16px 8px; text-align: center; color: var(--muted); }
  .mc-log-row { display: flex; align-items: baseline; gap: 8px; padding: 6px 6px; border-radius: 3px; }
  .mc-log-row:hover { background: rgba(255,255,255,.04); }
  .mc-log-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; margin-top: 4px; background: var(--muted); }
  .mc-log-dot.track { background: #7aa2ff; }
  .mc-log-dot.advance { background: #d7a12b; }
  .mc-log-dot.pass { background: #37b24d; }
  .mc-log-dot.fail, .mc-log-dot.error, .mc-log-dot.stale { background: #e5484d; }
  .mc-log-dot.confirm { background: var(--bo, #ff6a44); }
  /* Routine checks / startup checks — muted, so real changes stand out above the diligence hum. */
  .mc-log-dot.patrol, .mc-log-dot.startup { background: #5a5a5a; }
  .mc-log-row:has(.mc-log-dot.patrol) .mc-log-text, .mc-log-row:has(.mc-log-dot.startup) .mc-log-text { color: var(--muted); font-weight: 600; }
  .mc-log-body { flex: 1 1 auto; min-width: 0; }
  .mc-log-text { display: block; color: var(--txt); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mc-log-meta { display: block; color: var(--muted); font-size: 10.5px; margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mc-log-time { flex: 0 0 auto; color: var(--muted); font-size: 10.5px; font-variant-numeric: tabular-nums; }
  .mc-log-daysep { padding: 8px 6px 3px; font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
  /* Expandable log rows — click to reveal full detail + every individual check time */
  .mc-log-item.expandable > .mc-log-row { cursor: pointer; }
  .mc-log-caret { flex: 0 0 auto; align-self: center; color: var(--muted); font-size: 9px; transition: transform .12s ease; }
  .mc-log-item.open .mc-log-caret { transform: rotate(90deg); }
  .mc-log-sub { display: none; padding: 4px 8px 9px 23px; }
  .mc-log-item.open .mc-log-sub { display: block; }
  .mc-log-sub-detail { color: var(--txt); font-size: 11.5px; line-height: 1.5; white-space: normal; overflow-wrap: anywhere; }
  .mc-log-sub-lbl { display: block; margin: 9px 0 5px; font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
  .mc-log-sub-times { display: flex; flex-wrap: wrap; gap: 4px; }
  .mc-log-sub-times span { font-size: 10.5px; color: var(--muted); background: rgba(255,255,255,.05); border: 1px solid var(--line); border-radius: 3px; padding: 2px 6px; font-variant-numeric: tabular-nums; }
  .mc-log-headbtns { display: inline-flex; align-items: center; gap: 4px; }
  .mc-log-report { border: 1px solid rgba(var(--bo-rgb), .5); background: rgba(var(--bo-rgb), .12); color: var(--bo-txt); font-size: 11px; font-weight: 700; cursor: pointer; padding: 2px 8px; border-radius: 3px; }
  .mc-log-report:hover { background: rgba(var(--bo-rgb), .22); }
  /* MC daily report card (Admin). Same language as the branch-out recap card (John,
     2026-09-06, via //maddox): one surface, one accent rail, flat ledger rows instead of a
     wall of boxed tiles, zero counts folded into one quiet line, every colour from the
     accent variables so light mode never shows hard-coded orange/pink. */
  .mcr-overlay { position: fixed; inset: 0; z-index: 4200; background: rgba(0,0,0,.45); display: flex; align-items: center; justify-content: center; padding: 24px; -webkit-app-region: no-drag; }
  .mcr-card { width: 500px; max-width: 100%; max-height: 84vh; overflow-y: auto; background: var(--panel-2, #161616); border: 1px solid var(--line); border-left: 2px solid rgba(var(--bo-rgb), .55); border-radius: 3px; box-shadow: 0 18px 50px rgba(0,0,0,var(--sh60, .5)); padding: 16px 18px 14px; color: var(--text); }
  .mcr-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--line); }
  .mcr-eyebrow { font-size: 10px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--bo-txt); }
  .mcr-date { font-size: 14px; font-weight: 700; color: var(--text); margin-top: 2px; letter-spacing: .2px; }
  .mcr-close { flex: 0 0 auto; border: none; background: transparent; color: var(--muted); font-size: 18px; line-height: 1; cursor: pointer; padding: 2px 6px; border-radius: 3px; margin: -2px -6px 0 0; }
  .mcr-close:hover { color: var(--text); background: color-mix(in srgb, var(--text) 8%, transparent); }
  .mcr-narr { font-size: 12.5px; line-height: 1.55; color: var(--text); margin: 11px 0 0; }
  /* hero pair: the two numbers that are never zero on a normal day, big and accent */
  .mcr-heroes { display: flex; gap: 0; margin: 12px 0 4px; }
  .mcr-hero { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 3px; padding: 8px 12px 8px 0; background: none; border: none; border-radius: 3px; cursor: default; }
  .mcr-hero + .mcr-hero { padding-left: 14px; border-left: 1px solid var(--line); }
  .mcr-hero .mcr-stat-n { font-size: 24px; font-weight: 800; line-height: 1; letter-spacing: -.5px; color: var(--bo-txt); font-variant-numeric: tabular-nums; }
  .mcr-hero .mcr-stat-l { font-size: 9.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--muted); }
  /* ledger: label left, count right, hairline between rows (settings-row idiom) */
  .mcr-ledger { display: flex; flex-direction: column; border-top: 1px solid var(--line); }
  .mcr-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 7px 2px; border-bottom: 1px solid var(--line); border-radius: 0; background: none; cursor: default; }
  .mcr-row .mcr-stat-l { font-size: 12px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--text); }
  .mcr-row .mcr-stat-n { font-size: 12.5px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
  .mcr-row .mcr-stat-n::after { content: "›"; display: inline-block; margin-left: 8px; color: var(--faint); font-weight: 400; transition: transform .12s; }
  .mcr-row.sel .mcr-stat-n::after { transform: rotate(90deg); }
  .mcr-zero { padding: 7px 2px 0; font-size: 11px; line-height: 1.5; color: var(--faint); }
  .mcr-zero b { font-weight: 600; color: var(--muted); }
  /* Clickable stat (non-zero) → drill into the entries behind the number */
  .mcr-stat--click { cursor: pointer; transition: background .12s, color .12s; }
  .mcr-row.mcr-stat--click:hover { background: color-mix(in srgb, var(--text) 5%, transparent); }
  .mcr-row.mcr-stat--click:hover .mcr-stat-n::after, .mcr-row.sel .mcr-stat-n::after { color: var(--bo-txt); }
  .mcr-hero.mcr-stat--click:hover .mcr-stat-l { color: var(--bo-txt); }
  .mcr-stat.sel .mcr-stat-l { color: var(--bo-txt); }
  /* Drill-down: the log entries behind a clicked count, flat rows under an accent rail */
  .mcr-drill { display: none; }
  .mcr-drill.open { display: block; margin: 8px 0 2px; border-left: 2px solid rgba(var(--bo-rgb), .45); padding-left: 10px; }
  .mcr-drill-head { display: flex; align-items: center; justify-content: space-between; padding: 2px 0 6px; }
  .mcr-drill-title { font-size: 10px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--bo-txt); }
  .mcr-drill-close { -webkit-app-region: no-drag; cursor: pointer; border: none; background: transparent; color: var(--muted); font-size: 16px; line-height: 1; padding: 0 2px; }
  .mcr-drill-close:hover { color: var(--text); }
  .mcr-drill-list { max-height: 240px; overflow-y: auto; display: flex; flex-direction: column; }
  .mcr-drill-row { padding: 6px 0; border-top: 1px solid var(--line); background: none; border-radius: 0; }
  .mcr-drill-top { display: flex; align-items: baseline; gap: 8px; margin-bottom: 2px; }
  .mcr-drill-kind { font-size: 9.5px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--bo-txt); }
  .mcr-drill-time { font-size: 10.5px; color: var(--faint); font-variant-numeric: tabular-nums; flex: 0 0 auto; margin-left: auto; }
  .mcr-drill-text { font-size: 12px; line-height: 1.45; color: var(--text); overflow-wrap: anywhere; }
  .mcr-drill-detail { font-size: 11px; line-height: 1.45; color: var(--muted); margin-top: 1px; overflow-wrap: anywhere; }
  .mcr-drill-empty { padding: 10px 0; color: var(--muted); font-size: 12px; }
  .mcr-sec-title { font-size: 10px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--bo-txt); margin: 14px 0 6px; padding-top: 12px; border-top: 1px solid var(--line); }
  .mcr-suggs { display: flex; flex-direction: column; }
  .mcr-sugg { display: flex; align-items: flex-start; gap: 10px; padding: 9px 0; background: none; border: none; border-top: 1px solid var(--line); border-radius: 0; }
  .mcr-sugg:first-child { border-top: none; }
  .mcr-sugg-body { flex: 1 1 auto; min-width: 0; }
  .mcr-sugg-title { font-size: 12.5px; font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
  .mcr-sugg-detail { font-size: 11.5px; line-height: 1.5; color: var(--muted); margin-top: 2px; overflow-wrap: anywhere; }
  .mcr-empty { padding: 0; text-align: left; color: var(--faint); font-size: 11.5px; line-height: 1.5; }
  /* Approve / Reject on each suggestion */
  .mcr-sugg-actions { flex: 0 0 auto; display: flex; gap: 6px; align-items: center; }
  .mcr-approve, .mcr-reject, .mcr-undo { -webkit-app-region: no-drag; cursor: pointer; font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: 3px; border: 1px solid var(--line); background: transparent; color: var(--text); white-space: nowrap; }
  .mcr-approve { background: rgba(var(--bo-rgb), .14); color: var(--bo-txt); border-color: rgba(var(--bo-rgb), .5); }
  .mcr-approve:hover { background: rgba(var(--bo-rgb), .24); border-color: rgba(var(--bo-rgb), .7); }
  .mcr-reject { color: var(--muted); font-weight: 600; }
  .mcr-reject:hover { color: #e5484d; border-color: rgba(229,72,77,.5); background: rgba(229,72,77,.08); }
  .mcr-sugg-state { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; font-size: 11px; font-weight: 700; white-space: nowrap; }
  .mcr-sugg-state.approved { color: #37b24d; }
  .mcr-sugg-state.rejected { color: var(--muted); }
  .mcr-undo { padding: 2px 7px; font-size: 10.5px; font-weight: 600; color: var(--muted); }
  .mcr-undo:hover { color: var(--text); }
  .mcr-sugg.rejected { opacity: .6; }
  /* MC's adopted rules footer */
  .mcr-dirs { display: flex; flex-direction: column; gap: 5px; }
  .mcr-dir { display: flex; align-items: flex-start; gap: 8px; font-size: 12px; line-height: 1.45; }
  .mcr-dir-dot { flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%; margin-top: 6px; background: #37b24d; }
  .mcr-dir-t { flex: 1 1 auto; min-width: 0; color: var(--text); font-weight: 600; overflow-wrap: anywhere; }
  .mcr-dir-d { color: var(--muted); font-weight: 400; }
  /* Report card v3 (John, 2026-09-24, //maddox): verdict first, failures as rows, a quiet
     outcome strip, the model's summary collapsed, totals in a footer. Status is carried by a
     mark AND words, never colour alone. */
  .mcr-verdict { display: flex; align-items: center; gap: 12px; margin: 14px 0 0; padding: 12px 14px; border-radius: 10px; border: 1px solid var(--line); }
  .mcr-vmark { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 800; line-height: 1; }
  .mcr-vtext { min-width: 0; }
  .mcr-vtitle { font-size: 15px; font-weight: 700; line-height: 1.25; color: var(--text); }
  .mcr-vsub { font-size: 12px; line-height: 1.4; color: var(--muted); margin-top: 2px; }
  .mcr-card { --mcr-bad: #ff9a92; --mcr-ok: #7fd89a; }
  body[data-theme="light"]:not([data-preset]) .mcr-card, body[data-theme="white"]:not([data-preset]) .mcr-card { --mcr-bad: #9b1c12; --mcr-ok: #1a6b35; }
  .mcr-verdict.bad { background: color-mix(in srgb, #d92d20 10%, transparent); border-color: color-mix(in srgb, #d92d20 32%, transparent); }
  .mcr-verdict.bad .mcr-vmark { background: #c4291e; color: #fff; }
  .mcr-verdict.bad .mcr-vtitle, .mcr-verdict.bad .mcr-vsub { color: var(--mcr-bad); }
  .mcr-verdict.ok { background: color-mix(in srgb, #1e7a3c 10%, transparent); border-color: color-mix(in srgb, #1e7a3c 30%, transparent); }
  .mcr-verdict.ok .mcr-vmark { background: #1e7a3c; color: #fff; }
  .mcr-verdict.bad.mcr-stat--click:hover { border-color: color-mix(in srgb, #d92d20 55%, transparent); }
  .mcr-needs { display: flex; flex-direction: column; margin: 8px 0 0; }
  .mcr-need { display: grid; grid-template-columns: 64px minmax(0, 1fr) auto; align-items: baseline; gap: 10px; padding: 8px 2px; border-bottom: 1px solid var(--line); }
  .mcr-need-time { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
  .mcr-need-name { font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mcr-need-tag { font-size: 11px; font-weight: 600; color: var(--mcr-bad); white-space: nowrap; font-variant-numeric: tabular-nums; }
  .mcr-need-more { padding: 7px 2px 0; font-size: 11.5px; color: var(--muted); }
  .mcr-cells { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 16px 0 4px; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
  .mcr-cell { display: flex; flex-direction: column; gap: 3px; padding: 10px 12px; }
  .mcr-cell + .mcr-cell { border-left: 1px solid var(--line); }
  .mcr-cell .mcr-stat-n { font-size: 20px; font-weight: 700; line-height: 1.1; color: var(--text); font-variant-numeric: tabular-nums; }
  .mcr-cell .mcr-stat-l { font-size: 11px; color: var(--muted); }
  .mcr-cell--zero .mcr-stat-n { color: var(--faint); }
  .mcr-cell.mcr-stat--click:hover, .mcr-cell.sel { background: color-mix(in srgb, var(--text) 5%, transparent); }
  .mcr-cell.sel .mcr-stat-l { color: var(--text); }
  .mcr-narr--clamp { max-height: 7.8em; overflow: hidden; -webkit-mask-image: linear-gradient(#000 60%, transparent); mask-image: linear-gradient(#000 60%, transparent); }
  .mcr-narr table { border-collapse: collapse; margin: 6px 0; font-size: 12px; }
  .mcr-narr th, .mcr-narr td { text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line); vertical-align: top; }
  .mcr-narr code { font-size: 11.5px; }
  .mcr-more { -webkit-app-region: no-drag; margin: 6px 0 0; padding: 0; border: 0; background: none; color: var(--text); font-size: 12px; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
  .mcr-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 16px 0 0; padding-top: 10px; border-top: 1px solid var(--line); font-size: 11.5px; color: var(--muted); }
  .mcr-foot-sep { color: var(--faint); }
  .mcr-foot-link.mcr-stat--click:hover, .mcr-foot-link.sel { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
  .mc-log-dot.adopt { background: #37b24d; }
  /* Master Controller info + control panel (opened by clicking the chip name) */
  .mc-pop { position: fixed; z-index: 4000; width: 340px; max-height: 78vh; overflow-y: auto; background: var(--panel-2, #161616); border: 1px solid var(--line); border-radius: 3px; box-shadow: 0 14px 44px rgba(0,0,0,var(--sh50, .5)); padding: 12px; font-size: 12px; -webkit-app-region: no-drag; }
  .mc-pop-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 0 2px 9px; border-bottom: 1px solid var(--line); }
  .mc-pop-title { font-size: 13px; font-weight: 800; color: var(--text); }
  .mc-pop-sub { font-size: 11px; color: var(--muted); margin: 8px 2px 4px; line-height: 1.4; }
  .mc-master { display: flex; align-items: center; gap: 12px; padding: 14px 15px; border-radius: 3px; background: rgba(var(--bo-rgb), .08); border: 1px solid rgba(var(--bo-rgb), .28); margin-top: 10px; }
  .mc-master.off { background: rgba(150,150,150,.08); border-color: var(--line); }
  .mc-master-meta { flex: 1; min-width: 0; }
  .mc-master-title { font-size: 14px; font-weight: 800; color: var(--text); }
  .mc-master-state { font-size: 12px; color: var(--muted); margin-top: 2px; }
  .mc-feat-head { font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; color: var(--faint); margin: 18px 2px 7px; }
  .mc-ledger-list { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 3px; overflow: hidden; }
  .mc-ledger-row { display: flex; align-items: center; gap: 9px; min-width: 0; padding: 9px 11px; border-bottom: 1px solid var(--line); cursor: pointer; }
  .mc-ledger-row:last-child { border-bottom: 0; }
  .mc-ledger-row:hover { background: var(--hover); }
  .mc-ledger-row.confirmed { opacity: .58; }
  .mc-ledger-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; color: var(--text); }
  .mc-ledger-status { flex: 0 0 auto; font-size: 9px; font-weight: 700; letter-spacing: .35px; text-transform: uppercase; color: var(--faint); }
  .mc-ledger-empty { padding: 15px; border: 1px dashed var(--line); border-radius: 3px; color: var(--muted); font-size: 12px; }
  .mc-ledger-empty code { color: var(--bo-txt); }
  .mc-ledger-row:hover .ctl-confirm, .mc-ledger-row:hover .ctl-del, .mc-ledger-row:hover .ctl-reverify { display: inline-flex; }
  .mc-feat { display: flex; align-items: flex-start; gap: 11px; padding: 14px 15px; border-radius: 3px; border: 1px solid var(--line); margin-bottom: 7px; }
  .mc-feat.core { background: transparent; border-style: dashed; }
  .mc-feat.disabled { opacity: .5; }
  .mc-feat-meta { flex: 1; min-width: 0; }
  .mc-feat-top { display: flex; align-items: center; gap: 7px; }
  .mc-feat-name { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 700; color: var(--text); }
  .mc-cost { flex: 0 0 auto; font-size: 9px; font-weight: 800; letter-spacing: .3px; text-transform: uppercase; border-radius: 3px; padding: 1px 6px; }
  .mc-cost.free { color: #34c759; background: rgba(52,199,89,.13); border: 1px solid rgba(52,199,89,.3); }
  .mc-cost.tokens { color: #e0a44a; background: rgba(224,164,74,.14); border: 1px solid rgba(224,164,74,.34); }
  .mc-feat-desc { font-size: 12.5px; color: var(--text); line-height: 1.5; margin-top: 5px; }
  .mc-feat-why { font-size: 12px; color: var(--muted); line-height: 1.5; margin-top: 5px; }
  .mc-feat-why b { color: #e0a44a; font-weight: 700; }
  .mc-feat-spend { font-size: 11px; font-weight: 700; color: #e0a44a; margin-top: 4px; }
  /* ---- B5: "Where your tokens went today" report card — a readout, full-width, its
     own column-span so the bars + coaching have room. (John, 2026-08-04) ---- */
  .mc-feat.mc-tr { grid-column: 1 / -1; display: block; }
  .mc-tr-empty { font-size: 12.5px; color: var(--muted); line-height: 1.5; }
  .mc-tr-top { display: flex; align-items: baseline; gap: 8px; }
  .mc-tr-total { font-size: 24px; font-weight: 800; color: var(--text); letter-spacing: -.01em; }
  .mc-tr-sub { font-size: 12px; color: var(--muted); }
  .mc-tr-post { font-size: 11.5px; color: var(--faint); margin-top: 3px; }
  /* The daily "token diet" verdict — one warm line, tinted by how the day went. */
  .mc-tr-diet { font-size: 12.5px; line-height: 1.5; margin-top: 11px; padding: 9px 12px; border-radius: 3px; border: 1px solid var(--line); color: var(--text); }
  .mc-tr-diet.lean { border-color: rgba(52,199,89,.3); background: rgba(52,199,89,.09); }
  .mc-tr-diet.balanced { border-color: rgba(224,164,74,.3); background: rgba(224,164,74,.08); }
  .mc-tr-diet.rich { border-color: rgba(255, 106, 68,.34); background: rgba(255, 106, 68,.09); }
  .mc-tr-week { margin-top: 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 3px; background: var(--panel, rgba(255,255,255,.02)); }
  .mc-tr-week-h { font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; color: var(--faint); margin-bottom: 8px; }
  /* ── Dot-matrix chart engine — the ONE graph style (John, 2026-08-07: "LOVING THIS
     STYLE FOR OUR GRAPHS … use ours for all colors"). An LED panel: a faint even
     dot-grid is always drawn; data lights cells in --accent (currentColor so any
     per-series tint's glow matches its fill). Every graph in the app renders as one
     of these. ── */
  .dotmx { display: inline-grid; grid-template-columns: repeat(var(--dm-cols), var(--dm-dot, 4px)); gap: var(--dm-gap, 3px); align-content: end; justify-content: start; line-height: 0; }
  .dotmx .dm { width: var(--dm-dot, 4px); height: var(--dm-dot, 4px); border-radius: 50%; background: rgba(255,255,255,.09); transition: background .2s ease, box-shadow .2s ease, opacity .2s ease; }
  .dotmx .dm.on { color: var(--dm-on, var(--accent)); background: currentColor; opacity: var(--dm-v, 1); box-shadow: none; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .dotmx .dm { background: rgba(0,0,0,.10); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .dotmx .dm.on { background: currentColor; }
  .mc-tr-spark-row { display: block; }
  .mc-tr-spark-row .dotmx { width: 100%; grid-template-columns: repeat(var(--dm-cols), 1fr); justify-items: center; }   /* weekly bars stretch to the card width, dots stay round + centred */
  .mc-tr-week-line { font-size: 12px; line-height: 1.5; color: var(--text); margin-top: 8px; }
  .mc-tr-bars { margin-top: 12px; display: flex; flex-direction: column; gap: 7px; }
  .mc-tr-row { display: flex; align-items: center; gap: 10px; }
  .mc-tr-name { flex: 0 0 92px; min-width: 0; display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .mc-tr-dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; }
  .mc-tr-track { flex: 1; min-width: 0; display: flex; align-items: center; }   /* holds a dot-matrix meter (its own dim dots are the track) */
  .mc-tr-num { flex: 0 0 auto; font-size: 11.5px; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; }
  .mc-tr-tips-h { font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; color: var(--faint); margin: 16px 0 8px; }
  .mc-tr-tips { display: flex; flex-direction: column; gap: 8px; }
  .mc-tr-tip { border-radius: 3px; border: 1px solid rgba(224,164,74,.34); background: rgba(224,164,74,.08); padding: 10px 12px; }
  .mc-tr-tip.good { border-color: rgba(52,199,89,.3); background: rgba(52,199,89,.09); }
  .mc-tr-tip-h { font-size: 12.5px; font-weight: 800; color: var(--text); }
  .mc-tr-tip-b { font-size: 12px; color: var(--muted); line-height: 1.5; margin-top: 3px; overflow-wrap: anywhere; }
  /* Tokens Control's inline "Apply automatically" sub-toggle inside the card body. */
  .mc-sub-row { display: flex; align-items: center; gap: 10px; margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--line); }
  .mc-sub-label { flex: 1; min-width: 0; font-size: 12px; font-weight: 700; color: var(--text); display: flex; flex-direction: column; gap: 1px; }
  .mc-sub-hint { font-size: 11px; font-weight: 400; color: var(--muted); }
  .mc-core-tag { flex: 0 0 auto; font-size: 9px; font-weight: 700; color: var(--faint); text-transform: uppercase; letter-spacing: .3px; }
  /* the reusable little switch (same look as the chip toggle) */
  .mc-sw { flex: 0 0 auto; width: 32px; height: 18px; border-radius: 999px; background: var(--line); position: relative; cursor: pointer; transition: background .15s; margin-top: 1px; }
  .mc-sw::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #cfcfcf; transition: transform .15s, background .15s; }
  .mc-sw.on { background: var(--bo); }
  .mc-sw.on::after { transform: translateX(14px); background: #fff; }
  /* ---- Master Controller panel: a centered modal sized like Settings, a wide
     horizontal rectangle whose body is a 2-column grid that scrolls vertically.
     (John, 2026-07-26 — was a narrow chip-anchored vertical popup.) ---- */
  /* Big, roomy modal (John, 2026-07-29 — the 680×500 was "a sad pop up"). Wide enough
     that two feature columns breathe, tall enough to show several rows at once.
     NOTE: the selector is `.mc-overlay .mc-modal` (higher specificity) ON PURPOSE — the
     base `.modal { width:470px; padding:22px }` rule lives LATER in this file, so a bare
     `.mc-modal` (equal specificity, earlier) loses to it and the panel silently clamped
     to 470px. This is why it always looked cramped despite the width here. */
  .mc-overlay .mc-modal { width: 960px; max-width: 94vw; height: 680px; max-height: 90vh; padding: 0; overflow: hidden; display: flex; flex-direction: column; animation: setIn .2s ease-out; }
  .mc-modal .set-head { flex: 0 0 auto; padding: 20px 26px 16px; }
  .mc-modal .set-head h3 { font-size: 17px; }
  .mc-close { background: none; border: none; color: var(--muted); font-size: 16px; cursor: pointer; line-height: 1; padding: 5px 7px; border-radius: 3px; }
  .mc-close:hover { color: var(--text); background: rgba(255,255,255,.06); }
  /* overflow-x hidden + shrinkable grid tracks below = no stray horizontal scrollbar. */
  .mc-content { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 6px 28px 28px; }
  .mc-content .mc-pop-sub { margin: 12px 0 4px; font-size: 12.5px; line-height: 1.5; max-width: 760px; }
  /* 2 columns that can shrink below their content (minmax 0) so nothing overflows the
     modal; wraps to as many rows as needed (vertical scroll). */
  .mc-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; margin-top: 8px; }
  @media (max-width: 620px) { .mc-grid { grid-template-columns: minmax(0, 1fr); } }
  .mc-grid .mc-feat { margin-bottom: 0; height: 100%; background: rgba(255,255,255,.02); padding: 14px 15px; }
  /* Example line — "how to run it" as a mono chip. */
  .mc-feat-ex { display: flex; align-items: baseline; gap: 7px; margin-top: 7px; padding-top: 7px; border-top: 1px dashed var(--line); flex-wrap: wrap; }
  .mc-ex-label { flex: 0 0 auto; font-size: 8.5px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase; color: var(--faint); }
  .mc-feat-ex code { flex: 1; min-width: 0; font-family: 'Bitcount', ui-monospace, monospace; font-size: 11.5px; color: var(--bo, var(--accent)); background: rgba(var(--bo-rgb), .08); border: 1px solid rgba(var(--bo-rgb), .2); border-radius: 3px; padding: 4px 7px; line-height: 1.4; overflow-wrap: anywhere; }
  /* ===== MASTER CONTROLLER PANEL — 2026-09-06 redesign (//maddox) ==================
     Three tabs by job (Requests · Controls · Spend). Controls are FLAT divider rows in the
     Settings idiom (.set-card): name + one outcome line + switch, no boxes, no paragraphs
     up front; the why/example opens on demand (+). Numbers use the rail-and-air readout and
     the dot-matrix engine. Contrast floors: labels ≥ 4.5:1 on --panel-2 in both themes;
     state never rides colour alone (dot + word). Motion ≤ 200ms, off under reduced motion. */
  .mcx-head { position: relative; display: flex; align-items: center; gap: 12px; }
  .mcx-head h3 { flex: 0 0 auto; }
  .mcx-head-state { flex: 1; min-width: 0; font-size: 12px; color: var(--muted); letter-spacing: .2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .mcx-tabs { flex: 0 0 auto; display: flex; gap: 2px; padding: 0 26px; border-bottom: 1px solid var(--line); }
  .mcx-tab { appearance: none; background: none; border: none; border-bottom: 2px solid transparent; margin-bottom: -1px; padding: 9px 12px 10px; font: inherit; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; display: inline-flex; align-items: center; gap: 7px; letter-spacing: .1px; }
  .mcx-tab:hover { color: var(--text); }
  .mcx-tab.on { color: var(--text); border-bottom-color: var(--accent); }
  .mcx-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 3px; }
  .mcx-tab-n { font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; padding: 0 5px; border-radius: 999px; background: var(--hover); color: var(--muted); display: inline-flex; align-items: center; justify-content: center; }
  .mcx-tab.on .mcx-tab-n { background: rgba(var(--accent-rgb), .16); color: var(--accent); }
  .mcx-content { padding: 14px 28px 30px; }
  /* Master strip — always visible on Requests + Controls; state carried by dot AND word. */
  .mcx-master { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 3px; border: 1px solid var(--line); background: var(--panel, rgba(255,255,255,.02)); margin: 4px 0 6px; }
  .mcx-master.on { border-color: rgba(var(--accent-rgb), .35); }
  .mcx-master-dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; background: var(--faint); }
  .mcx-master.on .mcx-master-dot { background: var(--accent); box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .18); }
  .mcx-master-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .mcx-master-title { font-size: 14px; font-weight: 700; color: var(--text); }
  .mcx-master-state { font-size: 12px; color: var(--muted); }
  /* Sections + rows */
  .mcx-sec { margin-top: 18px; }
  .mcx-sec-h { display: flex; align-items: baseline; gap: 10px; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin: 0 2px 4px; }
  .mcx-sec-hint { font-size: 11px; font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--faint); }
  .mcx-warn { font-size: 11px; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--accent); }
  .mcx-row { padding: 11px 2px; border-top: 1px solid var(--line); }
  .mcx-row:first-of-type { border-top: none; }
  .mcx-sec-h + .mcx-row { border-top: none; }
  .mcx-row.disabled { opacity: .5; }
  .mcx-row-main { display: flex; align-items: center; gap: 12px; }
  .mcx-row-text { flex: 1; min-width: 0; }
  .mcx-name-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .mcx-name { font-size: 14px; font-weight: 600; font-family: var(--ui-font); color: var(--text); letter-spacing: .2px; }
  .mcx-row.off .mcx-name { color: var(--muted); }
  .mcx-tag { flex: 0 0 auto; font-size: 9.5px; font-weight: 700; letter-spacing: .3px; text-transform: uppercase; border-radius: 3px; padding: 1px 6px; border: 1px solid var(--line); color: var(--muted); }
  .mcx-tag.saves { color: #45e3b0; border-color: rgba(69,227,176,.35); }
  .mcx-tag.tokens { color: #e0a44a; border-color: rgba(224,164,74,.4); }
  .mcx-tag.core { color: var(--faint); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .mcx-tag.saves { color: #0f7a5a; border-color: rgba(15,122,90,.4); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .mcx-tag.tokens { color: #8a5a10; border-color: rgba(138,90,16,.4); }
  .mcx-line { font-size: 12.5px; color: var(--muted); margin-top: 3px; line-height: 1.45; }
  .mcx-line b { color: var(--text); font-weight: 600; }
  .mcx-more { flex: 0 0 auto; width: 22px; height: 22px; border-radius: 3px; border: 1px solid var(--line); background: transparent; color: var(--muted); font: inherit; font-size: 14px; line-height: 1; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
  .mcx-more:hover { color: var(--text); background: var(--hover); }
  .mcx-more:focus-visible, .mc-sw:focus-visible, .mcx-seg-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  .mcx-core { flex: 0 0 auto; font-size: 9px; font-weight: 700; color: var(--faint); text-transform: uppercase; letter-spacing: .3px; width: 32px; text-align: right; }
  .mcx-details { margin: 8px 0 2px; padding: 10px 12px; border-left: 2px solid rgba(var(--accent-rgb), .55); font-size: 12.5px; line-height: 1.5; color: var(--text); }
  .mcx-details p { margin: 0 0 6px; }
  .mcx-details p:last-child { margin-bottom: 0; }
  .mcx-details .mcx-note { color: var(--muted); }
  .mcx-details .mcx-note b { color: var(--text); }
  .mcx-ex { display: flex; align-items: baseline; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
  .mcx-ex-l { flex: 0 0 auto; font-size: 9px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--faint); }
  .mcx-ex code { flex: 1; min-width: 0; font-size: 11.5px; color: var(--accent); background: rgba(var(--accent-rgb), .08); border: 1px solid rgba(var(--accent-rgb), .2); border-radius: 3px; padding: 3px 7px; line-height: 1.4; overflow-wrap: anywhere; }
  /* Level picker (Lean replies) — a segmented control, not a dropdown: 3 options, all visible. */
  .mcx-seg { display: flex; align-items: center; gap: 4px; margin-top: 9px; flex-wrap: wrap; }
  .mcx-seg-btn { appearance: none; font: inherit; font-size: 12px; font-weight: 600; padding: 4px 11px; border-radius: 3px; border: 1px solid var(--line); background: transparent; color: var(--muted); cursor: pointer; }
  .mcx-seg-btn:hover { color: var(--text); background: var(--hover); }
  .mcx-seg-btn.on { color: var(--text); border-color: rgba(var(--accent-rgb), .6); background: rgba(var(--accent-rgb), .12); }
  .mcx-seg-line { flex: 1; min-width: 0; font-size: 11.5px; color: var(--faint); margin-left: 6px; }
  .mcx-sub { display: flex; align-items: center; gap: 12px; margin-top: 9px; padding: 8px 0 0; border-top: 1px dashed var(--line); }
  .mcx-sub-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; font-size: 12px; color: var(--muted); }
  .mcx-sub-text b { color: var(--text); font-weight: 600; }
  /* Switch upgrades: keyboard focus ring above, a disabled look, ≥ 3:1 track contrast. */
  .mc-sw.dis { cursor: default; }
  /* Spend tab — rail-and-air readout (no box, one thin rule), then flat bar rows. */
  .mcx-readout { border-left: 2px solid rgba(var(--accent-rgb), .7); padding: 6px 18px 8px; margin: 6px 0 4px; }
  .mcx-kpis { display: flex; align-items: flex-end; gap: 28px; flex-wrap: wrap; }
  .mcx-kpi-v { font-size: 20px; font-weight: 800; color: var(--text); letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
  .mcx-kpi.big .mcx-kpi-v { font-size: 34px; }
  .mcx-kpi-u { font-size: 12px; font-weight: 600; color: var(--muted); margin-left: 2px; }
  .mcx-kpi-l { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
  .mcx-readout-line { font-size: 12.5px; color: var(--muted); margin-top: 10px; line-height: 1.5; }
  .mcx-readout-line b.good { color: #45e3b0; } .mcx-readout-line b.hot { color: var(--accent); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .mcx-readout-line b.good { color: #0f7a5a; }
  .mcx-empty { font-size: 12.5px; color: var(--muted); line-height: 1.5; padding: 6px 0; }
  .mcx-bar-row { display: flex; align-items: center; gap: 12px; padding: 7px 2px; border-top: 1px solid var(--line); }
  .mcx-sec-h + .mcx-bar-row { border-top: none; }
  .mcx-bar-name { flex: 0 0 172px; min-width: 0; display: flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; }
  .mcx-bar-name > span:nth-child(2), .mcx-bar-name > span:only-child { overflow: hidden; text-overflow: ellipsis; }
  .mcx-bar-sub { flex: 0 0 auto; font-size: 10.5px; font-weight: 400; color: var(--faint); }
  .mcx-bar-track { flex: 1; min-width: 0; display: flex; align-items: center; }
  .mcx-bar-num { flex: 0 0 auto; font-size: 12px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .mcx-dim { color: var(--muted); font-weight: 500; }
  .mcx-est { font-style: normal; font-size: 9px; font-weight: 700; letter-spacing: .3px; text-transform: uppercase; color: #e0a44a; margin-left: 4px; vertical-align: 1px; }
  .mcx-unpriced { font-size: 11px; font-weight: 600; color: var(--muted); }
  .mcx-sess { display: flex; align-items: center; gap: 9px; padding: 8px 2px; border-top: 1px solid var(--line); cursor: pointer; border-radius: 3px; }
  .mcx-sec-h + .mcx-sess { border-top: none; }
  .mcx-sess:hover { background: var(--hover); }
  .mcx-sess-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 600; color: var(--text); }
  .mcx-sess-n { flex: 0 0 auto; font-size: 12px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
  .mcx-foot { font-size: 11.5px; color: var(--faint); line-height: 1.5; margin-top: 16px; }
  .mcx-foot code { color: var(--accent); }
  /* The diet card reuses the old .mc-feat box; inside the new panel flatten it to the same air. */
  .mcx-content .mc-grid { display: block; margin-top: 4px; }
  .mcx-content .mc-grid .mc-feat.mc-tr { background: transparent; border: none; border-left: 2px solid rgba(var(--accent-rgb), .45); border-radius: 3px; padding: 6px 18px 8px; height: auto; }
  .mcx-content .mc-ledger-list { border: none; border-radius: 0; }
  .mcx-content .mc-ledger-row { padding: 9px 2px; border-bottom: none; border-top: 1px solid var(--line); }
  .mcx-content .mc-ledger-row:first-child { border-top: none; }
  .mcx-content .mc-ledger-row:hover { border-radius: 3px; }
  .mcx-content .mc-ledger-empty { border-style: dashed; }
  @media (prefers-reduced-motion: reduce) { .mc-sw, .mc-sw::after, .mcx-tab, .mcx-seg-btn { transition: none; } }
  @media (max-width: 620px) { .mcx-bar-name { flex-basis: 110px; } .mcx-kpis { gap: 16px; } .mcx-kpi.big .mcx-kpi-v { font-size: 26px; } }
  /* Controller enforce-nudge inside the Action card ("2 done but untested, 1 open"). */
  .action-card .ctl-nudge { margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--line); display: flex; flex-direction: column; gap: 1px; }
  .ctl-nudge-label { font-size: 10px; letter-spacing: .04em; text-transform: uppercase; color: var(--faint); margin-bottom: 3px; }
  .ctl-nrow { display: flex; align-items: center; gap: 8px; padding: 3px 4px; border-radius: 3px; cursor: pointer; min-width: 0; }
  .ctl-nrow:hover { background: var(--hover); }
  .ctl-nrow .ctl-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--text); }
  .ctl-nrow .ctl-confirm { flex: 0 0 auto; width: 18px; height: 18px; border-radius: 3px; border: none; background: transparent; cursor: pointer; color: var(--faint); font-size: 13px; line-height: 1; padding: 0; display: inline-flex; align-items: center; justify-content: center; opacity: .6; }
  .ctl-nrow .ctl-confirm:hover { opacity: 1; color: #3ba55d; background: var(--hover); }
  .ctl-nudge-more { font-size: 10px; color: var(--faint); padding: 2px 4px; }
  /* Independent-verify button (appears on `done` items) + its running indicator. */
  .ctl-verify { flex: 0 0 auto; width: 18px; height: 18px; border-radius: 3px; border: none; background: transparent; cursor: pointer; color: var(--faint); font-size: 11px; line-height: 1; padding: 0; display: none; align-items: center; justify-content: center; }
  .ctl-row:hover .ctl-verify, .ctl-nrow:hover .ctl-verify { display: inline-flex; }
  .ctl-verify:hover { color: var(--accent); background: var(--hover); }
  .ctl-verifying { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); animation: micpulse 1s ease-in-out infinite; }
  .collapse-btn {
    /* Square, bordered, and the SAME size as the status box beside it (John,
       2026-08-18: "make sure the button is a square button ... all the same size").
       Was 28x26 with no border, so it read as a slightly-short borderless twin of a
       bordered box. Now 28x28 with the same 1px line — a matched pair of squares. */
    -webkit-app-region: no-drag; background: transparent; cursor: pointer;
    border: 1px solid var(--line);
    color: var(--muted); width: 28px; height: 28px; border-radius: 3px; padding: 0;
    box-sizing: border-box;
    display: flex; align-items: center; justify-content: center; flex: 0 0 auto;
  }
  .collapse-btn svg { width: 16px; height: 16px; }
  .collapse-btn:hover { color: var(--accent); background: var(--hover); }

  /* ---- Session layouts control (desktop, far-right of the top bar) ---- */
  /* Optional top-bar layout tabs (Appearance ▸ Layout tabs). One clickable tab per
     saved layout, beside the layouts dropdown; the strip scrolls if it overflows. */
  /* --lt-w: one tab's fixed width; stride = width + 4px gap. No tab-count cap any more
     (John, 2026-09-22: "the tabs on the right side are cropped too early"): the strip
     takes whatever width the header leaves it and scrolls past that. */
  /* flex-grow 1 (John, 2026-09-22: "Show at least 5 of them if possible. Here we have
     space."): with `flex: 0 1 auto` the header's `.spacer` (flex: 1) swallowed every
     spare pixel and the strip was left at whatever it could keep, scrolling instead of
     using the empty bar. Growing means free space reaches the tabs first, so a wide
     window shows as many names as fit before the strip starts scrolling. */
  .layout-tabs { --lt-w: 150px; --lt-fade: 28px; display: flex; align-items: center; gap: 4px; flex: 1 1 auto; min-width: 0; overflow-x: auto; -webkit-app-region: no-drag; scrollbar-width: none; margin-right: 4px; }
  .layout-tabs::-webkit-scrollbar { display: none; }
  /* Fade whichever edge has hidden tabs behind it, so both sides read as "more tabs".
     fade-l is set only once the strip is scrolled off the first tab; fade-r while there
     is anything left to scroll to. Both classes are kept in sync on scroll. */
  .layout-tabs.fade-r { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--lt-fade)), transparent 100%); mask-image: linear-gradient(to right, #000 calc(100% - var(--lt-fade)), transparent 100%); }
  .layout-tabs.fade-l { -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--lt-fade)); mask-image: linear-gradient(to right, transparent 0, #000 var(--lt-fade)); }
  .layout-tabs.fade-l.fade-r { -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--lt-fade), #000 calc(100% - var(--lt-fade)), transparent 100%); mask-image: linear-gradient(to right, transparent 0, #000 var(--lt-fade), #000 calc(100% - var(--lt-fade)), transparent 100%); }
  /* Width follows the NAME (John, 2026-09-22: "the space between layouts is uneven").
     A fixed 118px box left short names marooned in whitespace and truncated long ones;
     now every tab is its own width, capped, and the gap is the only spacing. */
  .layout-tab {
    -webkit-app-region: no-drag; flex: 0 0 max-content; width: max-content; min-width: min(max-content, var(--lt-w)); max-width: var(--lt-w); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    background: transparent; color: var(--muted); border: 1px solid var(--line); border-radius: 3px;
    height: 28px; padding: 0 10px; cursor: pointer; font-size: 12.5px; line-height: 1; font-family: inherit;
  }
  .layout-tab:hover { color: var(--accent); background: var(--hover); border-color: rgba(var(--accent-rgb), .5); }
  .layout-tab.active { color: var(--text); background: var(--hover); border-color: rgba(var(--accent-rgb), .55); }
  .layout-tab.dirty { color: var(--text); border-color: rgba(var(--accent-rgb), .6); }
  /* Assigned tab colour: coloured left bar + border, like a normal session tab. */
  /* "+" square at the end of the strip, same height as a tab. */
  .layout-tab-add {
    -webkit-app-region: no-drag; flex: 0 0 28px; width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
    background: transparent; color: var(--muted); border: 1px solid var(--line); border-radius: 3px;
    cursor: pointer; font-size: 17px; line-height: 1; font-family: inherit; padding: 0;
  }
  .layout-tab-add:hover { color: var(--accent); background: var(--hover); border-color: rgba(var(--accent-rgb), .5); }
  .layouts-ctl { flex: 0 0 auto; -webkit-app-region: no-drag; }
  .layouts-btn {
    -webkit-app-region: no-drag; display: inline-flex; align-items: center; gap: 6px;
    background: transparent; color: var(--muted);
    border: 1px solid var(--line); border-radius: 3px;
    height: 28px; padding: 0 9px; cursor: pointer;
    font-size: 12.5px; line-height: 1; font-family: inherit;
  }
  .layouts-btn:hover { color: var(--accent); background: var(--hover); border-color: rgba(var(--accent-rgb), .5); }
  .layouts-btn.active { color: var(--text); border-color: rgba(var(--accent-rgb), .55); }
  /* Unsaved-changes state: gold edge + gold "•" marker in the label. */
  .layouts-btn.dirty { color: var(--text); border-color: rgba(var(--accent-rgb),.6); }
  .layouts-btn.dirty .ly-lbl { color: var(--text); }   /* readable ink, not the low-contrast accent (John, 2026-08-24) */
  .layouts-btn .ly-lbl { max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .layouts-btn .ly-caret { flex: 0 0 auto; opacity: .8; }

  .layouts-menu { position: fixed; z-index: 9998; background: var(--panel); border: 1px solid var(--line); border-radius: 3px; padding: 5px; min-width: 220px; max-width: 320px; box-shadow: 0 12px 30px rgba(0,0,0,var(--sh50, .5)); }
  /* `position: relative` anchors the drop indicators below. (John, 2026-08-17: layouts
     are now ⌘1…⌘9 by list position, so the list had to become reorderable.) */
  .lm-row { position: relative; display: flex; align-items: center; gap: 6px; padding: 6px 6px 6px 8px; border-radius: 3px; cursor: pointer; }
  .lm-row:hover { background: var(--hover); }
  .lm-row.dragging { opacity: .45; }
  /* Insertion line — which side of this row the dragged layout will land on. */
  .lm-row.drop-before::before,
  .lm-row.drop-after::after {
    content: ''; position: absolute; left: 4px; right: 4px; height: 2px;
    background: var(--accent); border-radius: 2px;
  }
  .lm-row.drop-before::before { top: -1px; }
  .lm-row.drop-after::after { bottom: -1px; }
  /* The ⌘-number for this row. Monospace digits so the column can't jitter as the list
     is reordered; past 9 there is no key left, so it dims to a dot rather than implying
     a shortcut that would never fire. */
  .lm-num {
    flex: 0 0 auto; width: 15px; text-align: center;
    font-size: 10px; font-weight: 700; font-variant-numeric: tabular-nums;
    color: var(--faint); opacity: .9;
  }
  .lm-row.active .lm-num { color: var(--accent); opacity: 1; }
  .lm-num.none { opacity: .35; font-weight: 500; }
  /* Active layout name: hardcoded #fff read as white-on-white in light mode (John,
     2026-08-24). The accent already marks the active row via .lm-num; use var(--text)
     so the selected name stays legible in both themes. */
  .lm-row.active .lm-name { color: var(--text); font-weight: 700; }
  .lm-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; color: var(--text); }
  .lm-act { flex: 0 0 auto; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; border-radius: 3px; color: var(--muted); opacity: 0; transition: opacity .12s, color .12s, background .12s; }
  .lm-row:hover .lm-act { opacity: 1; }
  .lm-act:hover { color: var(--accent); background: rgba(var(--accent-rgb), .14); }
  .lm-act.del:hover { color: #f2a08f; background: rgba(242,160,143,.14); }
  /* Save icon: hover-only like rename/delete (John, 2026-08-24: "only show the save
     button on hover like the others"). Inherits .lm-act's opacity:0 + :hover reveal;
     just carries the accent tint so it still reads as the primary action on the row. */
  .lm-act.more:hover { color: var(--accent); background: rgba(var(--accent-rgb), .14); }
  /* Kebab overflow-menu items (Colour / Rename / Delete) rendered as buttons. */
  .lm-more-item { width: 100%; background: none; border: 0; font-family: inherit; text-align: left; }
  .lm-more-item.danger:hover { color: #f2a08f; background: rgba(242,160,143,.14); }
  .rm-swatch { flex: 0 0 12px; width: 12px; height: 12px; border-radius: 3px; }
  .lm-act.upd { color: var(--accent); }
  .lm-row:hover .lm-act.upd { background: rgba(var(--accent-rgb), .12); }
  .lm-act.upd:hover { color: var(--accent); background: rgba(var(--accent-rgb), .26); }
  .lm-act svg { width: 14px; height: 14px; }
  .lm-empty { padding: 9px 10px; font-size: 12.5px; color: var(--muted); }
  .lm-sep { height: 1px; background: var(--line); margin: 5px 6px; }
  .lm-save { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 3px; font-size: 13px; cursor: pointer; color: var(--accent); }
  .lm-save:hover { background: rgba(var(--accent-rgb), .14); }
  .lm-save .lm-plus { flex: 0 0 auto; font-size: 15px; line-height: 1; }
  .lm-save .lm-save-ic { display: inline-flex; }
  /* "Save changes to <name>" — only shown when the active layout has drifted. Gold, to
     match the unsaved-changes marker on the button. */
  /* (.lm-update banner removed 2026-08-17 — saving changes is now the .lm-act.upd icon
     on the layout's own row, above.) */
  /* tab-selection outline fully off, everywhere (John's pref). Inputs still show
     a caret + their own border styles, so you can tell where you're typing. */
  *:focus, *:focus-visible { outline: none !important; }

  /* folder shortcut: hidden in the full sidebar, only lives in the collapsed rail */
  .rail-folder-btn { display: none; }
  body.collapsed .rail-folder-btn {
    display: flex; align-items: center; justify-content: center;
    flex: 0 0 auto; width: 38px; height: 38px; margin: 10px auto 4px;
    border-radius: 3px; border: 1px solid transparent;
    background: transparent; color: var(--muted); cursor: pointer;
    transition: color .12s, border-color .12s, background .12s;
  }
  body.collapsed .rail-folder-btn svg { width: 19px; height: 19px; }
  body.collapsed .rail-folder-btn:hover { color: var(--accent); border-color: var(--accent); background: var(--hover); }
  body.collapsed .rail-folder-btn.drop-hover {
    color: var(--accent); border-color: var(--accent); border-style: solid;
    background: var(--hover); transform: scale(1.06);
  }

  /* ---- collapsed = thin rail: OW logo on top, active-chat dots, avatar at bottom ---- */
  body.collapsed aside { width: 56px; }
  /* Collapsed rail: the wordmark is hidden and the collapse toggle now lives in the
     header, so this strip is an empty draggable spacer — keep it aligned to the 46px
     header top (no more 34px traffic-light clearance). */
  body.collapsed .side-top { min-height: 46px; height: auto; padding: 0; }
  body.collapsed #projectsHead, body.collapsed .tree, body.collapsed .side-gutter { display: none; }
  /* The unmerged branch-out panel (name + ahead-count + "diff" pill) has no room in
     the 56px rail — it was the crammed/broken cluster John saw. Hide it when collapsed,
     same as the tree/automations/jobs; it returns in full when the sidebar expands. */
  body.collapsed .side-branches { display: none; }
  /* Status word (IDLE / THINKING / WAITING) sits on the right of every row, exactly like
     the phone's list (John, 2026-09-06: "I want these back on desktop"). This supersedes
     the 2026-07-28 name-only rule that hid it. It shrinks before the name does. */
  .active-row .astatus { display: inline; margin-left: auto; padding-left: 8px; white-space: nowrap; }
  body.collapsed #activeWrap .sec-head { display: none; }
  body.collapsed .active-list { padding: 4px 0; }
  body.collapsed .active-row { justify-content: center; margin: 0 6px; padding: 2px 0; }   /* tightened to match the expanded rows (John, 2026-09-22) */
  body.collapsed .active-row .meta, body.collapsed .active-row .astatus { display: none; }
  body.collapsed .adot { margin-right: 0; width: 8px; height: 8px; }
  /* Collapsed rail: an idle session shows a DIM neutral dot, not its mint idle light.
     (John, 2026-09-10: hiding it entirely left the row blank, so the rail read as a
     column of broken empty gaps.) The muted dot keeps every session a visible, evenly
     spaced tap target without a bright light glowing against the near-black rail. */
  body.collapsed .active-row .adot.idle { display: inline-block; background: var(--faint); opacity: .45; }
  /* The rail is strictly one dot per row: the shared-team icon and the spectate eye
     belong to the expanded row only — in 56px they crowd the dot and knock it off
     centre. (John, 2026-09-10.) */
  body.collapsed .active-row .steam, body.collapsed .active-row .aspec { display: none; }
  /* Collapsed: the avatar keeps its exact left spot (no centering, so it never
     slides as the width animates); only the gear disappears. */
  body.collapsed .side-footer .gear-btn { display: none; }
  /* Collapsed rail footer: stack the avatar, the Journal note button, and the
     account switcher vertically so all three stay reachable in 56px (John, 2026-09-11). */
  body.collapsed .side-footer { flex-direction: column; align-items: center; gap: 8px; padding: 8px 6px; }
  body.collapsed .side-foot-right { flex-direction: column; align-items: center; gap: 8px; }
  body.collapsed .side-footer .sb-brain-btn { display: inline-flex; }
  body.collapsed .acct-btn { width: 32px; height: 30px; justify-content: center; padding: 0; }
  body.collapsed .acct-btn #acctLabel, body.collapsed .acct-btn .caret { display: none; }

  .sec-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 8px;   /* equal on all four sides (John, 2026-08-24) */
    color: var(--text);
    font-size: 10.5px; font-weight: 400; letter-spacing: .8px; text-transform: uppercase;
    white-space: nowrap;
  }
  .sec-head button {
    background: transparent; color: var(--muted); border: none; cursor: pointer;
    font-size: 16px; line-height: 1; padding: 0 4px; border-radius: 3px;
  }
  /* Collapse caret for the whole Active Sessions list (open = points down). */
  .sec-head .sec-caret { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; margin: 0 3px 0 -2px; padding: 0; color: var(--faint); transform: rotate(90deg); transition: transform .12s ease, color .12s; }
  .sec-head .sec-caret:hover { color: var(--accent); background: #0003; }
  .sec-head.collapsed .sec-caret { transform: rotate(0deg); }   /* collapsed = points right */
  .sec-head .sec-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; cursor: pointer; }
  /* Collapsed Active Sessions: compact status-dot strip, right of the title. */
  /* Collapsed Active Sessions: dot strip on its own row under the header title. */
  /* The strip carries the collapsed block's BOTTOM air, so its bottom padding must equal
     the section head's own TOP padding, and its left padding must equal the head's left
     padding — otherwise the block reads low and the dots sit right of the title's first
     letter (John, 2026-09-22). Both numbers follow the head, per skin. */
  #activeWrap .active-dots-mini { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; padding: 0 10px 8px 8px; }
  #activeWrap .active-dots-mini .adot { width: 7px; height: 7px; }
  /* Collapsed Folders: hide the name filter (nothing to filter) and the folder rows. */
  #projectsHead.collapsed .proj-filter, #projectsHead.collapsed .proj-filter-x { display: none; }
  .unsorted-list.collapsed { display: none; }
  /* Collapsed Active Sessions = header only, same 8px rhythm as Folders / Unsorted. */
  .sec-head button:hover { color: var(--accent); background: var(--hover); }

  /* The + shares a column with the per-folder + on the rows below (John, 2026-09-22:
     "the + should align with the last item on the list"). Row +: 8px card margin
     + 7px row padding - 3px (.fnew's negative margin-right) + 4px button padding =
     glyph 16px in from the sidebar edge. Header +: 8px header padding + 4px button
     padding = 12px. This 4px margin closes the 4px gap between them. */
  .sec-head button.add-plus { color: var(--accent); font-size: 18px; font-weight: 700; margin-right: 4px; }
  .sec-head button.add-plus:hover { background: var(--accent-soft); color: var(--accent); }
  /* Tiny inline "Projects" filter — sits between the label and +, pushed to the right. */
  .sec-head .proj-filter {
    margin-left: auto; margin-right: 4px; width: 122px; min-width: 0;
    background: var(--panel, #14161a); color: var(--text);
    border: 1px solid var(--line, #2a2d33); border-radius: 3px;
    padding: 2px 6px; font-size: 10.5px; font-weight: 400; letter-spacing: .3px;
    text-transform: none; outline: none;
  }
  .sec-head .proj-filter::placeholder { color: var(--faint); text-transform: none; letter-spacing: .3px; }
  .sec-head .proj-filter:focus { border-color: var(--accent); }
  /* Clear (✕) sits just LEFT of the filter input; shown only while it has text. */
  .sec-head .proj-filter-x { margin-left: auto; margin-right: 3px; width: 14px; height: 14px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center; background: none; border: 0;
    color: var(--faint); font-size: 10px; line-height: 1; cursor: pointer; border-radius: 3px; }
  .sec-head .proj-filter-x:hover { color: var(--text); background: color-mix(in srgb, var(--text) 12%, transparent); }
  .sec-head .proj-filter-x[hidden] { display: none; }
  /* when the ✕ is present it owns the left auto-margin, so the input hugs it */
  .sec-head .proj-filter-x:not([hidden]) + .proj-filter { margin-left: 8px; }
  /* global "pause all queues" toggle on the Active Sessions bar */
  .sec-head button.q-pause-all { display: inline-flex; align-items: center; gap: 5px; color: var(--muted); font-size: 12px; padding: 2px 6px; }
  .sec-head button.q-pause-all svg { display: block; }
  .sec-head button.q-pause-all:hover { color: var(--accent); background: var(--hover); }
  .sec-head button.q-pause-all.on, .sec-head button.q-pause-all.on:hover { color: var(--accent); background: var(--accent-soft); }
  .sec-head button.q-pause-all .qp-label { font-size: 9px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; }
  .tree { flex: 1; overflow-y: auto; padding-bottom: 10px; }

  /* Every row (folder + session) sits on its own faint card: a persistent subtle fill,
     ~2px gap between rows, small padding (John, 2026-08-24: "add one behind each full
     row ... little padding ... about 2px" gap). Hover/active deepen it. */
  .row {
    display: flex; align-items: center; gap: 7px;
    margin: 0 8px 2px; padding: 7px;   /* EXACTLY 2px between every row — folders + sessions (John, 2026-08-28) */
    border-radius: 0; cursor: pointer; color: var(--text);
    white-space: nowrap;
    background: color-mix(in srgb, var(--text) 5%, transparent);
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--text) 8%, transparent);   /* tiny top highlight (John, 2026-09-15) */
  }
  .row:hover { background: color-mix(in srgb, var(--text) 9%, transparent); }
  /* Casual over-cap folders: visible but locked in place (blocked, never removed). */
  .row.folder.folder-locked { opacity: .45; }
  .row.folder.folder-locked:hover { opacity: .65; }
  .row.active { background: var(--active); }

  .folder .chev {
    width: 16px; flex: 0 0 auto; color: #5a5a5a;
    display: inline-flex; align-items: center; justify-content: center;
    transition: transform .14s ease;   /* same clean rotating chevron as mobile */
  }
  .folder.open .chev { transform: rotate(90deg); }
  /* Folder glyph — flat, minimal, digital. Swaps closed↔open with the folder's state
     (open state is the .open class on the row); accent-tinted when the folder is active. */
  .folder .ficon { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 16px; margin: 0; color: #7a7a7a; cursor: pointer; }   /* now the expand/collapse toggle (chevron removed) */
  .folder .ficon .fi-open { display: none; }
  .folder.open .ficon .fi-closed { display: none; }
  .folder.open .ficon .fi-open { display: inline-flex; }
  .folder.active .ficon,
  .folder:hover .ficon { color: var(--accent); }
  /* Top-level FOLDER names use the branded custom typeface (Brunea) so the
     projects read as headings — independent of the Settings font choice, which
     only governs sub-folders and sessions below. */
  .folder .fname {
    flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 700; color: #fff;
    letter-spacing: .2px;
    font-family: 'Brunea', 'Bitcount', ui-monospace, monospace;
  }
  .folder.active .fname { color: #fff; }
  /* Session-count number on a folder row — big enough to read at a glance so a
     COLLAPSED folder still shows how many sessions are inside. Sits right after the
     name; flex:0 0 auto so it never gets squeezed (screen-width discipline). */
  /* Count is ~50% lighter than the name text (John, 2026-08-24), and stays that way on
     hover/active rather than jumping to the accent. */
  .folder .fcount {
    flex: 0 0 auto; margin: 0; font-size: 13px; font-weight: 800;
    font-variant-numeric: tabular-nums; color: var(--muted); letter-spacing: .2px;
    font-family: 'Brunea', 'Bitcount', ui-monospace, monospace;
  }
  .row .x { opacity: 0; color: var(--faint); font-size: 14px; padding: 0 3px; border-radius: 3px; flex: 0 0 auto; }
  .row:hover .x { opacity: 1; }
  .row .x:hover { color: var(--accent); background: var(--active); }
  .row .dots { opacity: 0; color: var(--faint); font-size: 15px; padding: 0 5px; border-radius: 3px; flex: 0 0 auto; cursor: pointer; line-height: 1; }
  .row:hover .dots { opacity: 1; }
  .row .dots:hover { color: var(--accent); background: var(--active); }
  /* new-session + on a folder row — same orange plus as the PROJECTS "new folder" + */
  /* new-session + on a folder row: dark grey, right edge aligned to the PROJECTS + column */
  .folder .fnew { color: #4d4d4d; font-size: 18px; font-weight: 700; line-height: 1; padding: 0 4px; margin-right: -3px; border-radius: 3px; flex: 0 0 auto; cursor: pointer; }
  .folder .fnew:hover { color: var(--muted); background: var(--hover); }
  /* collapsed folder: one dot per active session inside (orange = working, green = idle) */
  .folder .factive { display: inline-flex; align-items: center; gap: 3px; margin: 0 0 0 1px; flex: 0 0 auto; }
  /* Push the trailing controls (⋯ + new-session +) to the right edge — via .dots
     so it holds whether the folder is OPEN (factive hidden) or collapsed. The
     collapsed activity dots (.factive) then sit next to the name, not the +. */
  .folder .dots { margin-left: auto; }
  .folder.open .factive { display: none; }
  .factive .fdot { width: 6px; height: 6px; border-radius: 2px; background: var(--faint); }
  .factive .fdot.thinking { background: var(--dot-c, var(--accent)); animation: micpulse 1.1s ease-in-out infinite; }   /* model-colour tint, falls back to orange */
  .factive .fdot.waiting { background: #45e3b0; }
  .factive .fmore { font-size: 9.5px; font-weight: 700; color: var(--muted); margin-left: 1px; }
  /* Above .overlay (999) — a row menu opened from INSIDE a settings sheet was
     rendering underneath it, so the list was unusable. Still below tooltips (9999)
     and toasts (10000). (John, 2026-08-16.) */
  .row-menu { position: fixed; z-index: 9998; background: var(--panel); border: 1px solid var(--line); border-radius: 3px; padding: 5px; min-width: 170px; box-shadow: 0 12px 30px rgba(0,0,0,var(--sh50, .5));
    /* A long list (e.g. every project as a "new session in…" target) used to grow taller
       than the window, which threw off the anchor-relative position math below and made
       the menu land pinned to the top-left corner instead of next to the + that opened it
       (John, 2026-08-23). Cap it to the viewport and let it scroll instead. */
    max-height: calc(100vh - 16px); overflow-y: auto; }
  /* Icon-only fold-out (queued-item ⋯) — a compact row of icon buttons, no labels. */
  .row-menu.icon-menu { display: flex; flex-direction: row; gap: 2px; min-width: 0; padding: 4px; overflow: visible; }
  .icon-menu-btn { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 28px; padding: 0; border: 0; background: transparent; border-radius: 3px; color: var(--text); cursor: pointer; }
  .icon-menu-btn svg { width: 17px; height: 17px; }
  .icon-menu-btn:hover { background: var(--hover); color: var(--accent); }
  .icon-menu-btn.danger { color: #f2a08f; }
  .icon-menu-btn.danger:hover { background: rgba(var(--accent-rgb),.16); color: var(--accent); }
  /* Color swatch popover (company color) — saves on click, no native panel. */
  .row-menu.color-menu { padding: 8px; min-width: 0; }
  .color-menu .color-grid { display: grid; grid-template-columns: repeat(7, 18px); gap: 6px; }
  .color-menu .color-sw { width: 18px; height: 18px; padding: 0; border-radius: 4px; border: 1px solid rgba(0,0,0,.25); cursor: pointer; box-shadow: inset 0 0 0 1px rgba(255,255,255,.08); }
  .color-menu .color-sw:hover { transform: scale(1.12); }
  .color-menu .color-sw.on { outline: 2px solid var(--text); outline-offset: 1px; }
  .color-menu .color-reset { display: block; width: 100%; margin-top: 8px; padding: 5px; border: 1px solid var(--line); background: transparent; color: var(--muted); border-radius: 3px; font: inherit; font-size: 11px; cursor: pointer; }
  .color-menu .color-reset:hover { color: var(--accent); border-color: var(--accent); }
  .row-menu-item { display: flex; align-items: center; gap: 7px; padding: 5px 10px; border-radius: 3px; font-size: 13px; cursor: pointer; color: var(--text); white-space: nowrap; }
  .row-menu-item:hover { background: var(--hover); }
  .row-menu-check { flex: 0 0 14px; width: 14px; height: 14px; display: inline-flex; align-items: center; justify-content: center; color: var(--accent); }
  .row-menu-check svg { width: 14px; height: 14px; }
  .row-menu-item.selected { color: #fff; font-weight: 600; }
  /* Model colour swatch in a picker row (John, 2026-07-31) — same hue as the pane-head dot. */
  .rm-swatch { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; margin-right: -1px; }
  /* Selected MODEL row wears the SAME card as the collapsed model chip (John, 2026-07-31):
     the label sits in a bordered pill in the model's own colour. currentColor == the inline
     model hue set on the label, so the box matches the text. Scoped to `.rm-model` so ONLY
     model rows box up — the intensity menu's selected row stays plain. (John, 2026-07-31:
     the check ✓ and colour dot were removed; the pill is now the sole selection cue.) */
  .row-menu-item.rm-model.selected .row-menu-label {
    border: 1px solid currentColor; border-radius: 3px; padding: 1px 8px;
  }
  .row-menu-item.danger { color: #f2a08f; }
  .row-menu-item.danger:hover { background: rgba(var(--accent-rgb),.16); color: var(--accent); }
  /* designed setting rows (compact head menu): label + a value pill on the right */
  .row-menu-sep { height: 1px; background: var(--line); margin: 5px 6px; }
  /* Small group title above each engine's models: which app they come from (John, 2026-08-14). */
  /* The COMPANY heading in a grouped menu (Claude / Codex / Gemini / Perplexity) is set
     in caps so it reads as a divider rather than another pickable row — the model names
     under it keep their own casing. (John, 2026-08-16.) */
  .row-menu-header { padding: 8px 10px 3px; font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--faint); }
  /* Pinned-account hint on a model group header ("on Maria" / "own login") and the dimmed
     rows of every other engine: subtle, never a second colour. */
  .row-menu-hnote { margin-left: 6px; font-weight: 500; letter-spacing: 0; text-transform: none; opacity: .75; }
  .row-menu-item.rm-dim { opacity: .55; }
  .row-menu-item.rm-dim:hover { opacity: .85; }
  .row-menu-item.rm-rich { gap: 10px; padding: 7px 8px 7px 11px; }
  .rm-name { color: var(--muted); }
  .rm-value { flex: 0 0 auto; margin-left: auto; font-size: 12px; font-weight: 600; color: var(--text); border: 1px solid var(--line); border-radius: 3px; padding: 1px 8px; font-variant-numeric: tabular-nums; white-space: nowrap; }
  .rm-chev { flex: 0 0 auto; color: var(--faint); font-size: 13px; line-height: 1; }
  .row-menu-item.rm-rich:hover .rm-value { border-color: #3a3a3a; }
  .rename-input { flex: 1; min-width: 0; background: var(--bg); border: 1px solid var(--accent); color: var(--text); border-radius: 3px; padding: 2px 6px; font: inherit; font-size: 12.5px; outline: none; user-select: text; -webkit-user-select: text; text-align: left; }
  /* drop insertion marks: crisp straight bars, never curved by the row's corners */
  .row.folder.drop-before, .row.folder.drop-after { position: relative; }
  .row.folder.drop-before::before, .row.folder.drop-after::after {
    content: ''; position: absolute; left: 0; right: 0; height: 2px; background: var(--accent); border-radius: 3px;
  }
  .row.folder.drop-before::before { top: -1px; }
  .row.folder.drop-after::after { bottom: -1px; }
  .row.folder.drop-into { box-shadow: none; background: var(--accent-soft); }
  .unsorted-sep { height: 1px; background: var(--line); margin: 12px 12px 0; }
  .unsorted-list { padding-bottom: 10px; }
  /* Empty-Unsorted drop target only appears while a session is being dragged. */
  .drag-only { display: none; }
  body.dragging-session .drag-only { display: block; }
  .unsorted-head { transition: box-shadow .1s, background .1s; }
  .unsorted-head.drop-into { box-shadow: none; background: var(--accent-soft); }
  #projectsHead.drop-into { background: var(--accent-soft); border-radius: 3px; }
  .unsorted-list .session { margin-left: 8px; }
  /* Shared-with-me sessions are NOT inside a folder — cancel the generic 34px
     folder-child indent so they sit flush/edge-to-edge like a top-level row (John, 2026-09-05) */
  .shared-list .session { margin-left: 8px; }
  /* Under the "Shared with me" heading every row is shared, so the team glyph is
     redundant and only pushes the title 22px right (John, 2026-09-07). Shared rows
     filed into one of my folders keep it: there it tells them apart from my own. */
  .shared-list .row.session > .steam { display: none; }
  /* Drag a session onto a subfolder header → real disk move into it. */
  .subfolder-head { transition: box-shadow .1s, background .1s; }
  .subfolder-head.tree-flash, .row.folder.tree-flash { box-shadow: inset 0 0 0 1px var(--accent); background: color-mix(in srgb, var(--accent) 14%, transparent); }
  .subfolder-head.drop-into { box-shadow: none; background: var(--accent-soft); border-radius: 3px; }

  .kids { display: none; position: relative; }
  .folder-item.open > .kids { display: block; padding-bottom: 4px; }   /* 4px tail below an OPEN folder's contents, separating it from the next folder (John, 2026-08-28) */
  .folder-item.open > .kids::before {
    content: ''; position: absolute; left: 26px; top: 0; bottom: 8px; width: 2px; border-radius: 3px; background: #474747;
  }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .folder-item.open > .kids::before { background: #bdbdc2; }
  .folder-item { margin-top: 0; }   /* gaps come only from the uniform 2px row margins (John, 2026-08-24) */

  .session, .session-new { margin-left: 34px; }
  .session-new { color: var(--muted); font-size: 12px; }
  .session-new:hover { color: var(--accent); }
  /* name + time share one line: name grows/truncates, time sits on the right */
  .session .sname { flex: 1; min-width: 0; font-size: 13px; font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: rgba(255,255,255,.7); }
  /* subfolder groups: sessions that live in a nested subfolder are grouped under a collapsible header */
  .subgroup { margin-top: 0; }   /* the 2px comes from the previous row's margin, never doubled */
  /* A subfolder header reads as a real folder — SAME name size/weight/colour as a
     top-level project folder — only pushed further right so the nesting is obvious. */
  /* position:relative + z-index lifts the header above the parent's guide rail
     (.kids::before), and the opaque sidebar background masks the rail where the
     header sits — so the vertical line is CUT at the folder (a clean gap around
     it) instead of running straight through, matching the phone. */
  /* Tight vertical padding (was 7px) so a collapsed folder reads as a FOLDER, not a
     lone dot floating in dead space, and more rows fit on screen. margin-left 11px
     (was 18px) lands the folder glyph's centre on the child rail at x=27px, so the
     folder sits ON the vertical line instead of floating right of it (John, 2026-08-14). */
  .subfolder-head { position: relative; z-index: 1; background: color-mix(in srgb, var(--text) 5%, var(--sidebar)); display: flex; align-items: center; gap: 7px; margin: 0 8px 2px 11px; padding: 7px; border-radius: 0; cursor: pointer; user-select: none; color: var(--muted); overflow: visible; white-space: nowrap; }
  .subfolder-head:hover { background: color-mix(in srgb, var(--text) 9%, var(--sidebar)); }
  /* Subfolder marker = a plain INK arrow (black in light, white in dark), no folder icon
     (John, 2026-08-24). The caret is the whole indicator now; .sf-ficon is hidden below. */
  .subfolder-head .sf-caret { flex: 0 0 auto; width: 12px; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; color: var(--text); transition: transform .12s ease; transform: rotate(90deg); }   /* expanded = pointing down */
  .subgroup.collapsed .sf-caret { transform: rotate(0deg); }
  /* subfolder folder glyph — same open/closed swap as top-level folders, keyed to the
     subgroup's collapsed state (expanded = open folder, collapsed = closed) */
  /* Subfolder marker = a FILLED ink arrow (John, 2026-08-24): points right when collapsed,
     down when expanded. Not a folder icon, not an outline caret. */
  .subfolder-head .sf-ficon { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 12px; margin: 0 2px 0 0; color: var(--text); transition: transform .12s ease; transform: rotate(90deg); }
  .subgroup.collapsed .subfolder-head .sf-ficon { transform: rotate(0deg); }
  .subfolder-head .sf-ficon .fi-closed { display: none; }
  .subgroup.collapsed .subfolder-head .sf-ficon .fi-open { display: none; }
  .subgroup.collapsed .subfolder-head .sf-ficon .fi-closed { display: inline-flex; }
  .subfolder-head:hover .sf-ficon { color: var(--accent); }
  /* One notch quieter than a top-level project name (13px/700/#fff) — same family,
     smaller + softer white so a subfolder clearly reads as a CHILD of the project,
     not a sibling. Depth now shows in weight/colour, not indentation alone. */
  /* SUB-folders follow the font picked in Settings → Visuals (--ui-font), unlike
     top-level folders which are locked to the Brunea brand face. */
  /* flex 0 1 auto (not 1 1) so the name never STRETCHES and shoves the count to the
     far edge — the count sits a couple spaces after the name, same as a top-level
     folder's .fcount. margin-right:auto on the count keeps the ⋯/＋/dots hard right. */
  .subfolder-head .sf-name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 600; color: rgba(255,255,255,.82); letter-spacing: .2px; font-family: var(--ui-font); }
  .subfolder-head .sf-count { flex: 0 0 auto; margin: 0; font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; opacity: .7; }
  /* live dots on a COLLAPSED subfolder header — same language as the collapsed-folder .factive */
  .subfolder-head .sf-active { display: inline-flex; align-items: center; gap: 3px; flex: 0 0 auto; margin-left: auto; }
  .subfolder-head .sf-active:empty { display: none; }
  .sf-active .fdot { width: 6px; height: 6px; border-radius: 2px; background: var(--faint); }
  .sf-active .fdot.thinking { background: var(--dot-c, var(--accent)); animation: micpulse 1.1s ease-in-out infinite; }   /* model-colour tint, falls back to orange */
  .sf-active .fdot.waiting { background: #45e3b0; }
  .sf-active .fmore { font-size: 9.5px; font-weight: 700; color: var(--muted); margin-left: 1px; }
  /* ⋯ on a subfolder header — same affordance as a project folder's, hover-revealed */
  .subfolder-head .sf-dots { flex: 0 0 auto; margin-left: auto; opacity: 0; color: var(--muted); font-size: 13px; line-height: 1; padding: 2px 3px; border-radius: 3px; }
  .subfolder-head:hover .sf-dots { opacity: .7; }
  .subfolder-head .sf-dots:hover { opacity: 1; color: var(--text); background: var(--hover); }
  .subfolder-head .sf-new { flex: 0 0 auto; opacity: 0; color: var(--muted); font-size: 17px; font-weight: 700; line-height: 1; padding: 0 3px; border-radius: 3px; cursor: pointer; }
  .subfolder-head:hover .sf-new { opacity: .7; }
  .subfolder-head .sf-new:hover { opacity: 1; color: var(--text); background: var(--hover); }
  /* a folder you made but haven't filled yet: visible, and obviously a drop target */
  /* Empty groups are just a quieter header (drop target = the header itself) —
     the old dashed "Empty — drag a session here" boxes are gone (John, 2026-08-08). */
  .subgroup.empty .subfolder-head .sf-name { color: var(--muted); font-weight: 400; }
  /* No sessions anywhere under it → outlined (hollow) caret, so an empty subfolder reads
     as empty at a glance (John, 2026-08-28). Filled triangle when it holds sessions. */
  .subgroup.empty .subfolder-head .sf-ficon svg path { fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linejoin: round; }
  /* Undo the generic `.empty` placeholder rule (margin:auto; text-align:center) leaking
     onto an empty subfolder and centring its name (John, 2026-08-27). */
  .subgroup.empty { margin: 0; text-align: left; max-width: none; }
  /* Was 26px — LESS than the header's own name start (~49px), so a subfolder's
     sessions rendered to the LEFT of "Apps"/"Marketing" itself and read as a flat
     continuation of the list above, not as that folder's contents. 42px lands the
     session name flush under the header's name text, matching how a top-level
     session (34px) sits just under its project's fname. */
  .subgroup .row.session { margin-left: 35px; }   /* 42→35: same rail-to-row gap as a top-level session, so the branch tick is identical (John, 2026-08-24) */
  .subgroup.collapsed .row.session { display: none; }
  .subgroup .subgroup { margin-left: 14px; }                 /* nested groups indent inside their parent */
  .subgroup.collapsed .subgroup { display: none; }           /* collapsing a parent hides its child groups too */
  /* A vertical rail from the header down through its sessions — the same
     containment cue a top-level folder gets from `.folder-item.open > .kids::before`.
     Without it, an open subfolder's rows had nothing tying them visually to their
     own header. Skipped while collapsed (nothing below) or empty (nothing to connect). */
  .subgroup:not(.collapsed):not(.empty) { position: relative; }   /* no extra tail padding — uniform 2px rhythm */
  .subgroup:not(.collapsed):not(.empty)::before {
    content: ''; position: absolute; left: 23px; top: 22px; bottom: 3px; width: 2px; border-radius: 3px; background: #474747;
  }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .subgroup:not(.collapsed):not(.empty)::before { background: #bdbdc2; }
  .row.session.current .sname { color: #fff; }   /* the selected session is full white */
  /* time sits flush on the right (aligned with the + column); the ⋯ menu overlays it on hover */
  .row.session { position: relative; }
  /* Tiny highlight on the top edge of the Active Sessions and Folders sections
     and each session row — a hairline of light so each container reads as its
     own surface (John, 2026-09-13). */
  #activeWrap, #projectsHead, .tree .row.session {
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--text) 7%, transparent);
  }
  /* PALE THEMES: lift from WHITE, never from the ink. Same hairline, same geometry; only
     the colour flips, so a row reads raised on Light and White exactly as it does on the
     dark themes (John, 2026-09-19). */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) :is(.row, .active-row, #activeWrap, #projectsHead, .tree .row.session) {
    box-shadow: inset 0 1px 0 rgba(255,255,255,.9);
  }
  /* Branch tick: a short horizontal line joining the vertical rail to each session row,
     like a tree connector (John, 2026-08-24). Same colour as the rail, in every theme.
     -11px = where the rail passes (the .srun dot sits there); the working dot draws over
     it when active. Subgroup rows re-anchor to their deeper rail below. */
  /* Tick STARTS at the vertical rail (its centre) and runs right to the row edge, so it
     visibly joins the line on BOTH top-level and subgroup rows (John, 2026-08-24). The
     rail centre relative to the row = where the .srun dot centres (-7px top / -14px sub). */
  .folder-item.open .row.session::before {
    content: ''; position: absolute; top: 50%; left: -7px; width: 7px; height: 2px;
    margin-top: -1px; border-radius: 2px; background: #474747;
  }
  /* Subgroup rows connect to the subgroup rail at x=24px (aligned with the arrow tip) */
  .subgroup .row.session::before { left: -11px; width: 11px; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .folder-item.open .row.session::before { background: #bdbdc2; }
  /* live "working" dot for an active session, centered ON the connector line */
  /* The dot is TWO layers (John, 2026-08-26): `.srun` itself is an always-opaque mask
     (sidebar-coloured disc + a 3px sidebar ring) that hides the connector line under it,
     and `.srun::after` is the coloured core that pulses. Pulsing the ELEMENT's opacity
     faded the mask too, so at the trough the line showed through — now only the core
     fades, the mask stays 100%. */
  .row.session .srun { display: none; position: absolute; left: -11px; top: 50%; transform: translateY(-50%); width: 8px; height: 8px; border-radius: 2px; background: var(--sidebar); box-shadow: 0 0 0 3px var(--sidebar); z-index: 1; }
  .row.session .srun::after { content: ''; position: absolute; inset: 0; border-radius: 2px; background: var(--dot-c, #45e3b0); }
  /* Subgroup rail center is at 24px (arrow point); row is at 35px: dot center = -11px, left = -15px */
  .subgroup .row.session .srun { left: -15px; }   /* dot centered on the subgroup rail at x=24px */
  .row.session.active-waiting .srun, .row.session.active-thinking .srun, .row.session.active-running .srun { display: block; }   /* green = open/idle; running = a live shared session */
  .row.session.active-thinking .srun::after, .row.session.active-running .srun::after { background: var(--dot-c, var(--accent)); animation: micpulse 1.1s ease-in-out infinite; }   /* answering — model colour (tintSessionDot sets --dot-c), falls back to accent; only the core pulses, the mask stays solid */
  /* A shared-with-me row sits at the sidebar's left edge with no folder rail, so the
     absolute -11px rail dot hung OUTSIDE the row. Bring the status dot inside the row
     and onto the right, the way a folder shows its active dots (John, 2026-09-11). */
  .shared-list > .row.session .srun { position: static; left: auto; top: auto; transform: none; order: 2; margin-left: 6px; background: transparent; box-shadow: none; }
  .shared-list > .row.session .time { order: 3; }
  /* queued-item count badge — same language as the phone's per-session badge */
  .session .row-q, .active-row .row-q { flex: 0 0 auto; min-width: 15px; height: 15px; padding: 0 5px; margin-left: 6px; border-radius: 3px; background: var(--accent-soft); color: var(--accent); font-size: 10px; font-weight: 700; line-height: 15px; text-align: center; }
  /* ⇄ Handoff arrival flag: a peer handed work to this session; clears when you focus it. */
  .row-handoff { flex: 0 0 auto; margin-left: 6px; font-size: 11px; font-weight: 700; line-height: 1; color: var(--accent); opacity: .9; animation: handoffPulse 1.8s ease-in-out infinite; }
  @keyframes handoffPulse { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }
  .session .time { flex: 0 0 auto; margin-left: auto; margin-right: -3px; font-size: 10.5px; color: var(--faint); transition: opacity .12s ease; }
  /* the ⋯ menu takes the right-edge slot only on hover; the time owns it at rest */
  .session .dots { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); }
  .row.session:hover .time { opacity: 0; }
  .session .dots { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); }
  .session:hover .time { visibility: hidden; }

  .kids .loading, .kids .none { color: var(--faint); font-size: 11px; padding: 5px 9px 5px 43px; }

  /* ---- main / panes ---- */
  .main { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
  .main-body { flex: 1; display: flex; flex-direction: row; min-width: 0; min-height: 0; }
  #panes-root { flex: 1; display: flex; min-width: 0; min-height: 0; }

  /* POP-OUT (solo) window: a single session detached into its own window. Strip the app
     down to just that session — no sidebar, no resizer, no top header/Master-Controller. */
  body.solo-window aside,
  body.solo-window .side-resizer,
  body.solo-window .main > header { display: none !important; }
  /* A REAL, MOVABLE WINDOW (John, 2026-08-17: "make it its own window... right now it's a
     weird window inside the luminair window"). Pop-outs use `titleBarStyle: 'hiddenInset'`
     — there is no OS title bar, so SOMETHING in the page has to be `-webkit-app-region:
     drag` or the window can't be dragged by its background at all. Every drag region the
     normal window has lives in chrome this mode hides on purpose: the app `<header>` is
     gone, and so is the sidebar's `.side-top` strip (`aside` is hidden entirely). With
     both gone, a pop-out had ZERO drag surface — it sat there looking like a borderless
     panel glued in place, exactly the "embedded, not a real window" feeling reported.
     One dedicated strip, tall enough to clear the traffic-light buttons (Electron's
     native traffic lights render on TOP of page content and stay clickable regardless of
     the drag region underneath, so this can't block them). */
  body.solo-window .main { padding-top: 28px; position: relative; }
  body.solo-window .main::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 28px;
    -webkit-app-region: drag; z-index: 5;
  }
  /* Pop-out window controls (John, 2026-09-03): the same close/minimize squares as the
     main window, re-homed into the solo strip (renderer lifts them out of the hidden
     aside). Above the drag region so they stay clickable. */
  body.solo-window .main > .win-ctrls {
    position: absolute; top: 6px; left: 12px; z-index: 6;
    display: inline-flex; gap: 6px; -webkit-app-region: no-drag;
  }

  /* "Connect your Claude account" prompt — sessions-view banner shown when signed
     into Luminair but no Claude login/connector yet (replaces auto-opening OAuth). */
  /* Front-and-center connect prompt (John, 2026-07-25): centered card over a dimmed
     app, not a thin bar. */
  /* Brand colors, not the themeable accent: true app black/gray for the surface and
     the Luminair burnt-orange (#ff6a44) for the CTA — the same brand orange used on
     the update chip / branch badges, NOT the bright themeable #ff6a44 accent. */
  .cc-prompt { position: fixed; inset: 0; z-index: 5000; display: flex; align-items: center;
    justify-content: center; padding: 24px; background: rgba(0,0,0,.62); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
  .cc-prompt-card { display: flex; flex-direction: column; align-items: center; text-align: center;
    gap: 16px; width: 100%; max-width: 420px; padding: 34px 30px; background: var(--panel);
    border: 1px solid var(--line); border-radius: 3px; box-shadow: 0 26px 72px rgba(0,0,0,var(--sh60, .6)); }
  .cc-prompt-txt { display: flex; flex-direction: column; gap: 8px; }
  .cc-prompt-txt b { font-size: 22px; font-weight: 700; color: var(--text); letter-spacing: -0.01em; }
  .cc-prompt-txt span { font-size: 14px; line-height: 1.45; color: var(--muted); }
  .cc-prompt-btn { width: 100%; max-width: 320px; background: var(--accent); color: #fff; border: none;
    border-radius: 3px; padding: 14px 22px; font-size: 15px; font-weight: 700; cursor: pointer;
    box-shadow: none; transition: filter .12s; }
  .cc-prompt-btn:hover { filter: brightness(1.06); }
  .cc-prompt-btn:disabled { opacity: .6; cursor: default; }
  .cc-prompt-diag { max-width: 340px; width: 100%; font-size: 12px; line-height: 1.4; color: var(--muted);
    overflow-wrap: anywhere; margin-top: -4px; }
  .cc-prompt-recheck { background: none; border: none; color: var(--muted); font-size: 12.5px;
    font-weight: 600; cursor: pointer; padding: 2px 4px; text-decoration: underline; text-underline-offset: 2px; }
  .cc-prompt-recheck:hover { color: var(--text); }

  .split { display: flex; flex: 1 1 0; min-width: 0; min-height: 0; }
  .split-row { flex-direction: row; }
  .split-col { flex-direction: column; }
  .split > * { flex: 1 1 0; min-width: 0; min-height: 0; }

  .pane {
    flex: 1 1 0;
    display: flex; flex-direction: column; min-width: 0; min-height: 0;
    position: relative; overflow: hidden;
    /* Each pane paints into its OWN compositing layer, so a partial repaint in one can
       never leave residue over another. Chasing the "printing issue" (John, 2026-08-16):
       removing `content-visibility` from .msg fixed the fictional-height layout part, but
       leftovers kept appearing — including one pane's folder chip drawn over another
       pane's transcript, which is not something CSS layout can produce. That signature is
       a stale-pixel/compositing artifact, and layer isolation is the standard cure.
       `isolation` costs nothing; `translateZ(0)` on the scroller pins it to its own layer. */
    isolation: isolate;
  }
  /* Focused head tinted to the ACCENT, not a fixed orange-brown (John, 2026-08-24). */
  /* Active title bar is a DARKER shade of the theme surface, NOT the accent (John, 2026-08-25). */
  .pane.focused .pane-head { background: color-mix(in srgb, var(--panel) 78%, #000); }
  .pane.focused { box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb),.35); }
  /* Highlighted (focused) session window reads ~99% black on the dark themes so the
     active pane pops against the lifted/gray unfocused ones (John, 2026-09-09). Scoped
     off light; a tinted focused pane keeps its brand wash (its .pane.tinted rule wins). */
  body:not([data-theme="light"]):not([data-theme="white"]) .pane.focused:not(.tinted) { background: #030303; }
  /* Per-session subtle background tint (⋯ → Colour). applyPaneTint() paints
     --pane-tint (header layer) + --pane-tint-bg (whole-pane wash) on the root; no
     class = no tint. The .focused rule below is 4 classes so it beats the plain
     focused-head colour above and keeps #1b1613 UNDER the tint. */
  /* The colour → 30%-darker fade lives HERE, on the header BACKGROUND (John,
     2026-08-13), not on the title text. Top layer is a transparent→30%-black wash
     running left→right: the left end is exactly the tint as-is, the right end is
     that same tint 30% darker. Theme-independent (black darkens on light too). */
  /* Layer the brand wash OVER --bg — NOT instead of it. As `var(--pane-tint-bg)` alone,
     the pane dropped its themed --bg and fell through to the near-black app background, so
     tinted panes read black on the Dark/gray theme (John, 2026-08-25: "TOOOO DARK"). */
  .pane.tinted { background: linear-gradient(var(--pane-tint-bg), var(--pane-tint-bg)), var(--bg); }
  .pane.tinted .pane-head {
    background: linear-gradient(90deg, transparent 0%, var(--head-fade) 100%),
                linear-gradient(var(--pane-tint), var(--pane-tint)), var(--panel);
  }
  /* The ACTIVE (focused) session's title bar wears the SAME colour as its active tab
     (John, 2026-09-01): --pane-tint is now .22 (same alpha as the chip's --chip-tint)
     over the tab's own --panel-2 base, so head and active tab read as one surface. */
  .pane.tinted.focused .pane-head {
    background: linear-gradient(90deg, transparent 0%, var(--head-fade) 100%),
                linear-gradient(var(--pane-tint), var(--pane-tint)), var(--panel-2);
  }
  /* the SELECTED (focused) pane reads full-strength; the others dim to ~70% so it's
     clear which one is selected (same treatment as the active-sessions list). The
     WHOLE unfocused pane body dims uniformly — including the bottom "thinking"
     scanner. The scanner is NOT held at full strength: it must not be the only thing
     that reads on a dimmed pane, so it fades with the rest of that pane's content. */
  .pane:not(.focused) .pane-body { opacity: var(--dim); }
  /* The ACTIVE (focused) window is painted LIGHTER than the app bg in every mode; the
     unfocused panes sink a touch below it (John, 2026-08-25). A filter did nothing here
     because .pane is transparent — the surface is painted behind it — so we paint the
     pane background itself. */
  .pane { background: var(--bg); }
  .pane.focused { background: color-mix(in srgb, #fff 5%, var(--bg)); }
  .pane:not(.focused) { background: color-mix(in srgb, #000 3%, var(--bg)); }
  /* New/empty pane KEEPS its title bar (John: "on new sessions I still need to see
     the title bar"). We only hide the controls that have no session to act on yet —
     forks / variants / queue-flow / more — while the title and the close ✕ stay.
     The model·intensity chip goes too (John, 2026-08-16: "THIS SHOULD NOT show you the
     model at all we don't care here"): before a session exists there is nothing running,
     so naming a model is noise, not information. It reappears the moment the pane has a
     real session to act on. */
  .pane.empty-pane .pane-head .pvariants,
  .pane.empty-pane .pane-head .pfork,
  .pane.empty-pane .ph-flow,
  .pane.empty-pane .pane-head .pcap,
  .pane.empty-pane .pane-head .pmore { display: none; }
  /* Keep the model + thinking pill on a NEW session so its session-level model and
     intensity can be set BEFORE the first message (John, 2026-08-31). */
  .pane.empty-pane .pane-head .pmodesel { display: inline-flex; }
  /* Empty pane has no header bar, so its close ✕ floats top-right. Only shown when
     there's more than one pane (closing the sole pane would be a no-op). */
  .pane-empty-x {
    display: none; position: absolute; top: 10px; right: 10px; z-index: 6;
    width: 26px; height: 26px; align-items: center; justify-content: center;
    background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px;
    color: var(--muted); font-size: 12px; cursor: pointer; -webkit-app-region: no-drag;
    transition: color .12s, background .12s, border-color .12s;
  }
  .pane-empty-x:hover { color: var(--accent); background: var(--hover); border-color: rgba(var(--accent-rgb),.5); }
  /* The header's own close ✕ now handles closing an empty pane, so the floating
     fallback ✕ is no longer needed. */
  body.multi-pane .pane.empty-pane .pane-empty-x { display: none; }
  .pane-head {
    height: 34px; flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
    padding: 0 6px 0 11px; border-bottom: 1px solid var(--line);
    background: var(--panel); font-size: 11.5px; color: var(--muted);
  }
  .pane-head .phdot { flex: 0 0 auto; width: 7px; height: 7px; margin: 0 -2px 0 0; }   /* status dot left of the title */
  /* REVERTED (John, 2026-08-12): idle/waiting tab dots were tinted to the model colour
     (2026-07-31 decision below), but that made a done/idle tab read orange while the
     same session's Active Sessions row read green — John flagged the mismatch with a
     screenshot and wants idle/waiting to match the sidebar's green status vocabulary.
     Thinking still pulses in the model colour (`.adot.thinking` below); only idle/waiting
     on the tab dot are back to plain green, same as the Active Sessions list. */
  .pane-head .ptitle {
    position: relative;
    flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    color: #fff; font-size: 13.5px; font-weight: 400;
    /* Plain solid title. The colour→darker fade belongs to the header BACKGROUND
       (see .pane.tinted .pane-head); painting it on the glyphs was the bug — it just
       made long titles fade out and left the bar flat. */
    cursor: text; padding: 1px 4px; margin: 0 -4px; border-radius: 3px;   /* click to rename */
    -webkit-app-region: no-drag;
  }
  .pane-head .ptitle:hover { background: var(--hover); }
  .pane-head .ptitle .rename-input, .pane-head input.rename-input { font-size: 13.5px; }
  .pane-head .phspacer { flex: 1 1 auto; }
  .pane-head .pfolder { color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 130px; border: 1px solid var(--line); }
  .pane-head .pfolder.icon-only { max-width: none; }
  .pane-head .pfolder.icon-only svg { margin-right: 0; }
  .pane-head .pbtn { cursor: pointer; color: var(--faint); padding: 2px 5px; border-radius: 3px; font-size: 12px; }
  .pane-head .pbtn:hover { color: var(--accent); background: var(--hover); }
  /* The ⋯ menu is PERMANENT (John, 2026-08-11): always the home for Max size +
     Colour. On a narrow pane the model/thinking controls also fold into it. */
  .pane-head .pmore { display: inline-block; font-size: 15px; line-height: 1; }
  .pane-head.compact .pfork, .pane-head.compact .peffort, .pane-head.compact .pfolder { display: none; }
  /* <500px: hide the model chip; <400px: hide Journal + Pins (moved into ⋯). (John, 2026-09-02) */
  .pane-head.hide-model .pmodesel, .pane-head.hide-model .pminimodel { display: none !important; }
  .pane-head.tuck-tools .pscrap, .pane-head.tuck-tools .ppins { display: none !important; }
  .pane-head.tuck-pins .ppins { display: none !important; }   /* <460px: Pins folds before Journal */
  /* The compact head keeps the SAME model chip (.pmodel folds to its 19px .mini
     square) instead of swapping in a second marker — one model button, never two.
     .pminimodel is retired (kept in the DOM but always hidden) to avoid the
     duplicate that a specificity tie let both render at once. */
  .pane-head .pminimodel { display: none; }
  /* Model + thinking are ONE button now: a single bordered pill wrapping the model
     segment, a hairline divider, and the intensity segment (John, 2026-07-28). The
     inner chips keep their own padding but drop their individual borders (kept 1px
     transparent so nothing shifts) — the model still signals its colour via its text. */
  .pane-head .pmodesel.pbtn { display: inline-flex; align-items: center; padding: 0; border: 1px solid var(--line); border-radius: 3px; flex: 0 0 auto; }
  .pane-head .pmodesel:hover { background: var(--hover); }
  /* Model-change confirmation (John, 2026-08-08): a glow pulse ON this session's own
     model chip, tinted to the model just switched to (--flash-c, set in JS), instead
     of a floating app-wide toast that read as belonging to no particular session. */
  .pane-head .pmodesel.flash { animation: pmodeselFlash .6s ease-out; }
  @keyframes pmodeselFlash {
    0%   { box-shadow: 0 0 0 0 var(--flash-c, var(--accent)); border-color: var(--flash-c, var(--accent)); }
    60%  { box-shadow: 0 0 0 5px transparent; }
    100% { box-shadow: 0 0 0 0 transparent; border-color: var(--line); }
  }
  .pane-head .pmodesel .pmodel,
  .pane-head .pmodesel .peffort { border-color: transparent !important; border-radius: 3px; }
  .pane-head .pmodesel .pmodel.set:hover,
  .pane-head .pmodesel .peffort:hover { background: transparent; }
  .pane-head .pms-div { align-self: stretch; width: 1px; margin: 3px 0; background: var(--line); flex: 0 0 auto; }
  .pane-head.compact .pms-div { display: none; }
  /* model chip: normal is quiet; an expensive model is loud so you always know */
  /* model chip: each model its own colour (set inline in JS), quiet grey for Auto */
  .pane-head .pmodel { border: 1px solid var(--line); font-weight: 700; white-space: nowrap; flex: 0 0 auto; padding: 2px 5px; }
  .pane-head .pmodel.set:hover { background: var(--hover); }
  /* tight head: the chip folds to just the model's initial — a true SQUARE (equal
     width/height, border included), never a compressed/squished rectangle. */
  .pane-head .pmodel.mini {
    display: inline-flex; align-items: center; justify-content: center;
    box-sizing: border-box; width: 19px; height: 19px; padding: 0;
    font-size: 11.5px; font-weight: 800; line-height: 1;
  }
  /* thinking-intensity chip: pulse icon + level */
  .pane-head .peffort { display: inline-flex; align-items: center; gap: 4px; border: 1px solid var(--line); font-weight: 600; padding: 2px 5px; }
  .pane-head .peffort svg { opacity: .8; }
  .pane-head .peffort.set { color: var(--text); border-color: #3a3a3a; }
  /* Max size moved into the permanent ⋯ menu (John, 2026-08-11) — the inline chip is
     retired so the header stays uncluttered. Kept in the DOM (click handler intact),
     just hidden. */
  .pane-head .pcap { display: none; border: 1px solid var(--line); font-weight: 600; font-variant-numeric: tabular-nums; }
  .pane-head .pcap.set { color: var(--text); border-color: #3a3a3a; }
  /* Per-session queue-flow switch on the title bar — the same orange pill as the
     queue panel's auto-send toggle, sized a touch smaller to sit in the 34px head.
     ON (orange) = queued messages send automatically; OFF = this session holds its queue. */
  .ph-flow { flex: 0 0 auto; margin: 0 1px; }
  .ph-flow .q-auto-track { width: 28px; height: 16px; }
  .ph-flow .q-auto-track::after { width: 12px; height: 12px; }
  .ph-flow input:checked + .q-auto-track::after { transform: translateX(12px); }
  /* Session-title auto-send toggle: FLAT fill in the chosen theme accent, both modes
     (John, 2026-08-24: "remove the gradient, make it flat... the custom color from
     settings"). No linear-gradient, no darkened second stop — just var(--accent). */
  .ph-flow input:checked + .q-auto-track {
    background: var(--accent);
  }
  /* pinned "what this session is working on" bar (last message you sent), shown
     above the scrolling body while the reply is running so you can always see it */
  .pane-pin { display: none; flex: 0 0 auto; padding: 7px 16px; border-bottom: 1px solid var(--line); background: var(--panel); color: var(--muted); font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .pane-pin::before { content: "› "; color: var(--accent); font-weight: 700; }
  /* superseded by the sticky query bubbles — the message itself pins now */
  .pane.running .pane-pin.show { display: none; }
  /* Chat padding tiers (Settings → Visuals). Medium is the default; the body
     carries data-pad="s"/"l" for the other two. Chat text and composer share it. */
  :root { --chat-pad: 22px; --comp-pad: 20px; --msg-gap: 20px; --chat-scale: 1.05; --dim: 0.7; }
  body[data-pad="s"] { --chat-pad: 12px; --comp-pad: 10px; }
  body[data-pad="l"] { --chat-pad: 34px; --comp-pad: 32px; }
  /* Message spacing — vertical gap BETWEEN messages (Settings → Visuals). Medium is
     the default (roomier than before); small tightens, large is generous. */
  body[data-gap="s"] { --msg-gap: 12px; }
  body[data-gap="l"] { --msg-gap: 40px; }
  /* Text size — the whole interface scales via NATIVE page zoom (applySize() →
     webContents.setZoomFactor; see the .body-row freeze-fix note). The old per-size
     --chat-scale overrides are gone on purpose: page zoom multiplies everything, so
     a size-varying --chat-scale would double-scale its calc() consumers. */
  /* Inactive-session dimming — how much the non-focused panes fade. */
  body[data-dim="none"] { --dim: 1; }
  body[data-dim="low"]  { --dim: 0.85; }
  body[data-dim="high"] { --dim: 0.5; }
  /* Accent color — one rgb triplet recolors the whole app. Orange (default) needs
     no attribute. The four model colors + cyan + red.
     IMPORTANT: --accent / --accent-soft are DERIVED here on <body>, not on :root.
     data-accent is set on <body>, so --accent-rgb is overridden on <body>; if the
     derived colors lived on :root (<html>) they'd be computed from html's triplet
     and never pick up the override — the picker would only change the few spots
     that use var(--accent-rgb) directly. Deriving on body fixes the whole app. */
  body { --accent: rgb(var(--accent-rgb)); --accent-soft: rgba(var(--accent-rgb), .14); }
  /* Readable INK for text/icons that sit ON an --accent fill. Default dark, because
     every accent except one clears WCAG better against black (readableInk() in
     renderer.js agrees — only purple wins on white). Purple is a dark, saturated
     hue: dark ink on it is 3.5:1 (fails AA), white ink is 6:1. So the composer
     mic/send button, primary buttons, active segments, badges etc. must use
     var(--on-accent), NOT a hardcoded #1a1a1a, or they go unreadable on purple.
     (John, 2026-09-01: "white text in light mode + purple, fix all contrast".) */
  body { --on-accent: #1a1a1a; }
  body[data-accent="green"]  { --accent-rgb: 69, 227, 176; }
  body[data-accent="blue"]   { --accent-rgb: 91, 141, 239; }
  body[data-accent="purple"] { --accent-rgb: 119, 37, 255; --on-accent: #f5f5f5; }
  body[data-accent="cyan"]   { --accent-rgb: 34, 211, 238; }
  body[data-accent="red"]    { --accent-rgb: 229, 72, 77; }
  body[data-accent="pink"]   { --accent-rgb: 255, 20, 147; --on-accent: #ffffff; }   /* white ink on pink, not the dark default (John, 2026-09-06) */
  body[data-accent="neon"]   { --accent-rgb: 198, 255, 0; }   /* neon lime (John, 2026-08-24) */
  body[data-accent="neonorange"] { --accent-rgb: 255, 84, 5; }   /* neon orange (John, 2026-08-25) */
  body[data-accent="neongreen"]  { --accent-rgb: 57, 255, 20; }   /* neon green (John, 2026-08-25) */
  /* GRAY accent (John, 2026-07-29): a neutral scheme — everything that's normally the
     Sol orange goes gray. Same one-triplet mechanism as the other accents, so all 379
     var(--accent*) surfaces (solids, soft tints, glows, terminal, backdrop) recolor at
     once. Two things intentionally stay their fixed color even under gray, because
     they're semantic/branded vocabularies, NOT the accent: the ORANGE "working" status
     dot (traffic-light: green idle / orange working / red error, --dot-work) and the
     GOLD Branch-Out signature (--bo-*). A mid neutral (Apple system gray) reads cleanly
     on dark and still glows.
     TONE (John, 2026-07-30): the first pass (152,152,158 / #98989e) read too bright, so
     it came down a notch to #86868b. There IS a floor here, because --accent is a TEXT
     color in 136 rules: on --bg #0d0d0d this holds 5.36:1 (WCAG AA body text needs 4.5),
     and #7c7c81 at 4.68:1 is the darkest that still passes. Anything below that (#78787d
     = 4.43:1, #6e6e73 = 3.83:1) makes accent-colored TEXT fail AA — so don't darken past
     #7c7c81 without switching those 136 rules off the accent. Bonus: darker also fixes
     light mode, where #98989e on white was a poor 2.87:1 and #86868b is 3.62:1. */
  body[data-accent="gray"]   { --accent-rgb: 134, 134, 139; }

  /* ── FUN THEME PRESETS (John, 2026-09-01) — full-mood looks (bg family + accent) ── */
  body[data-preset="cove"] {
    --bg: #0d1a1c; --panel: #12262a; --panel-2: #183036; --sidebar: #0f2124;
    --line: #244349; --tool: #12262a; --tool-line: #244349;
    --accent-rgb: 220, 249, 138; --on-accent: #12211f;
  }
  body[data-preset="ember"] {
    --bg: #14161c; --panel: #1b1e26; --panel-2: #232732; --sidebar: #171921;
    --line: #313743; --tool: #1b1e26; --tool-line: #313743;
    --accent-rgb: 255, 107, 94; --on-accent: #26120f;
  }
  body[data-preset="neon"] {
    --bg: #161125; --panel: #1e1830; --panel-2: #261f3c; --sidebar: #191327;
    --line: #322a49; --tool: #1e1830; --tool-line: #322a49;
    --accent-rgb: 255, 45, 142; --on-accent: #ffffff;   /* 3.49:1; #f6eaf1 was 2.98:1 */
  }
  body[data-preset="aurora"] {
    --bg: #0e1d28; --panel: #142936; --panel-2: #1a3644; --sidebar: #102330;
    --line: #244656; --tool: #142936; --tool-line: #244656;
    --accent-rgb: 255, 122, 92; --on-accent: #26120c;
  }
  body[data-preset="halo"] {
    --bg: #1a1715; --panel: #221e1b; --panel-2: #2b2622; --sidebar: #1d1a17;
    --line: #38312b; --tool: #221e1b; --tool-line: #38312b;
    --accent-rgb: 255, 90, 60; --on-accent: #260e08;
  }
  body[data-preset="sentinel"] {
    --bg: #12171b; --panel: #191f24; --panel-2: #21282e; --sidebar: #141a1f;
    --line: #2c353d; --tool: #191f24; --tool-line: #2c353d;
    --accent-rgb: 255, 42, 36; --on-accent: #f6e9e8;
  }
  body[data-preset="nova"] {
    --bg: #15162b; --panel: #1c1d36; --panel-2: #242544; --sidebar: #171830;
    --line: #302f52; --tool: #1c1d36; --tool-line: #302f52;
    --accent-rgb: 232, 92, 255; --on-accent: #200a26;
  }
  body[data-preset="onyx"] {
    --bg: #060607; --panel: #0d0d0e; --panel-2: #131315; --sidebar: #0a0a0b;
    --line: #202022; --tool: #0d0d0e; --tool-line: #202022;
    --accent-rgb: 235, 235, 238; --on-accent: #101012;
  }
  body[data-preset="graphite"] {
    --bg: #17171a; --panel: #202024; --panel-2: #2a2a2f; --sidebar: #1b1b1f;
    --line: #3a3a40; --tool: #202024; --tool-line: #3a3a40;
    --accent-rgb: 200, 200, 206; --on-accent: #17171a;
  }
  body[data-preset="scanner"] {                  /* deep navy HUD + desaturated amber */
    --bg: #12151c; --panel: #191d26; --panel-2: #212632; --sidebar: #141822;
    --line: #2c323f; --tool: #191d26; --tool-line: #2c323f;
    --accent-rgb: 214, 138, 82; --on-accent: #201206;
  }

  /* ── UI DEPTH & GLOW (John, 2026-09-01) — opt-in (Settings → Appearance) ─────────
     Cheap holographic depth: STATIC multi-layer box-shadows only — a top sheen, a
     faint accent rim, a soft drop, and one offset spread-negative shadow that reads
     as a faint "duplicate layer / reflection". No blur, no backdrop-filter, no
     animation loop, so it is essentially free to paint. Toggled by data-depth="on". */
  body[data-depth="on"] :is(.set-card, .note-card, .ask-card, .doc-card, .cmd-card, .acct-item) {
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,.05),
      0 0 0 1px rgba(var(--accent-rgb), .06),
      0 12px 30px -18px rgba(0,0,0,.72),
      7px 9px 0 -7px rgba(var(--accent-rgb), .07);
  }
  /* Focused pane gets a soft inner accent bloom + reflected top edge. */
  body[data-depth="on"] .pane.current .pane-body {
    box-shadow: inset 0 1px 0 rgba(255,255,255,.04), inset 0 0 70px -34px rgba(var(--accent-rgb), .20);
  }
  /* Modals/menus lift off the page with a deeper drop + accent rim. */
  body[data-depth="on"] :is(.modal-card, .row-menu, .set-modal, .docs-view) {
    box-shadow:
      0 0 0 1px rgba(var(--accent-rgb), .08),
      0 24px 60px -28px rgba(0,0,0,.8),
      8px 12px 0 -9px rgba(var(--accent-rgb), .06);
  }
  @media (prefers-reduced-motion: reduce) { /* effect is already static; nothing to disable */ }
  /* Scroll-anchoring (browser anti-jump) is ON at the container level so image/markdown
     reflow above the viewport no longer shoves your read position — the long-standing
     "scrollbar jump" (2026-07-28). Anchoring was originally killed WHOLESALE here to stop
     one thing: a collapsed query bubble expanding above the viewport bumping scrollTop and
     blocking scroll-to-top. The correct scope is per-element — so anchoring stays on for
     everything, and ONLY the collapse/expand query bubbles are excluded as anchor
     candidates (`.msg.user { overflow-anchor: none }` below). Best of both: no reflow jump,
     and you can still scroll freely to the very first message. */
  .pane-body {
    flex: 1; overflow-y: auto; overflow-x: hidden; overflow-anchor: auto;
    /* translateZ(0) REMOVED (John, 2026-08-17). It was added to chase the "printing
       issue" on the theory that a dedicated layer isolates repaints. It does the
       opposite here: promoting a long scrolling region to its own composited layer is a
       classic source of STALE TILES — the layer keeps previously rasterized content and
       an incorrect invalidation leaves the old pixels visible under the new ones, which
       is exactly the overlap in the screenshots. Painting in the normal document layer
       lets the scroller invalidate the way Chromium expects. */
    padding: 0 var(--chat-pad) 64px; display: flex; flex-direction: column; gap: var(--msg-gap);   /* gap == .turn's gap (uniform), both driven by the Message-spacing setting */
    font-size: 14px;   /* scales with the interface via .body-row zoom */
    /* NO bottom fade mask (John, 2026-07-25 — "bottom of session still cropped, fixed
       this 10 times"). Every prior round TUNED this gradient (12px band) + its padding
       and it still read as cropped: a mask fades the bottom edge to transparent, so the
       newest line — the one you most need to read while it streams — was the exact thing
       being erased. Removed entirely: a clean hard edge can never eat text. The 96px
       bottom padding (was 72) keeps the newest line comfortably clear of the composer at
       rest. Pair with scrollPane's post-layout re-pin so the tail is always scrolled in. */
  }
  /* While a query is running, lift the thinking scanner / streaming reply well
     clear of the composer with extra bottom padding — the scanner's time/token
     readout kept sitting inside the 12px bottom fade (mask-image above) and
     reading as dim/half-erased, so the lift needs real margin past that fade
     band, not just past the composer. It's ONLY padding, so you can still scroll
     back to the full height of the transcript exactly as before.
     NO transition on this property (John, 2026-07-25 — round 2): setPaneRunning
     toggles `.running` and then immediately scrolls-to-bottom in the same tick.
     With a transition, reading scrollHeight that same tick still sees the OLD
     (pre-transition, 40px) padding — CSS transitions interpolate from the value
     at the moment of change, so a synchronous read at t=0 is the start value,
     not the target. That pinned scrollTop at the SMALL scrollHeight, so the
     scanner landed flush against the viewport's bottom edge — exactly inside
     the 12px fade — and never moved, because nothing re-scrolls once the
     padding finishes animating in the background. Snapping it instead means
     scrollHeight already includes the full 200px the instant we measure it. */
  .pane.running .pane-body { padding-bottom: 120px; }
  /* soft fade at the top edge: a sticky gradient overlay (bg to transparent). Looks
     identical to a mask over the solid background, but costs nothing: a mask forces
     the whole scroller into offscreen compositing that repaints on every scroll. */
  /* (removed) top fade gradient — John didn't want the dark "drop shadow" at the
     top edge of each session's message area. Content now meets the header cleanly. */
  .pane-body::before { display: none; }
  /* nothing inside a session may ever force sideways scroll: every child adapts
     to the pane width (flex min-width:auto is the classic culprit — kill it) */
  /* flex-shrink:0 (John, 2026-09-03): the browser default flex-shrink:1 let Chromium
     squeeze a very tall reply's `.turn` so later turns painted on top of it. Rows must
     keep their measured height; overflow goes to `.pane-body`, never to overlapping
     children. max/min-width keep the matching horizontal fix. */
  .pane-body > *, .turn > * { flex-shrink: 0; max-width: 100%; min-width: 0; }
  .msg.user .msg-img { max-width: min(260px, 100%); }
  /* Side padding is fixed to match the bottom (10px) — the Visuals padding tier
     (--comp-pad) must NOT push the composer's sides in/out (John, 2026-08-29). */
  .pane-composer { flex: 0 0 auto; padding: 10px; border-top: none; background: transparent; container: comp / inline-size; }

  .drop-ind {
    position: absolute; inset: 0; pointer-events: none; z-index: 32; display: none;
    background: var(--accent-soft); border: 2px solid var(--accent); border-radius: 3px;
    /* NO position/size transition (2026-08-07): animating left/right/top/bottom made the
       highlight visibly CHASE the pointer for 160ms on every zone flip — and those are
       layout-triggering properties, so the browser re-laid-out continuously while it
       eased. The indicator now snaps to the zone instantly; the magnet keeps its own
       snap animation below, which is transform-only and cheap. */
  }
  /* Compact custom drag ghost: without one, dragging a pane header ghosts the whole
     pane-width bar over the very zones being aimed at. Parked offscreen; Chromium
     snapshots it for setDragImage. */
  .drag-ghost {
    position: fixed; top: -1000px; left: -1000px; z-index: 9999; pointer-events: none;
    max-width: 240px; padding: 6px 12px; border-radius: 3px;
    background: var(--panel, #1c1c1e); border: 1px solid var(--accent);
    color: var(--accent); font-size: 12px; font-weight: 600;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* Magnetized onto a header — about to fold into ONE tab strip on drop. A
     stronger glow + a quick overshoot/settle so catching it reads as a snap, not
     a flat highlight (paired with .magnet-bridge, which shows where it's headed). */
  .drop-ind.magnet {
    box-shadow: none;
    animation: magnetSnap .18s cubic-bezier(.3,1.7,.4,1);
  }
  @keyframes magnetSnap {
    0% { transform: scaleY(.7); opacity: .5; }
    55% { transform: scaleY(1.1); opacity: 1; }
    100% { transform: scaleY(1); opacity: 1; }
  }
  /* the bridge: a thin glowing line connecting the dragged pane/tab to the header
     it's magnetized onto, so it's visible the WHOLE line is about to merge into
     that group before you let go — not just after you drop. */
  .magnet-bridge {
    position: fixed; z-index: 24; display: none; pointer-events: none;
    background: var(--accent); border-radius: 3px;
    box-shadow: none;
    animation: magnetPulse 1s ease-in-out infinite;
  }
  @keyframes magnetPulse { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
  /* dragging OS files (images, fonts, …) in from Finder */
  .pane.filedrop::after {
    content: "Drop files to attach";
    position: absolute; inset: 6px; z-index: 40; pointer-events: none;
    display: flex; align-items: center; justify-content: center;
    border: 2px dashed var(--accent); border-radius: 3px;
    background: var(--accent-soft); color: var(--accent);
    font-size: 13px; font-weight: 700; letter-spacing: .3px;
  }

  #transcript { flex: 1; overflow-y: auto; padding: 20px 20px 8px; display: flex; flex-direction: column; gap: 13px; }
  /* THE "PRINTING ISSUE" — messages drawn on top of each other (John, 2026-08-16:
     "this printing issue keeps happening"). This used to carry
     `content-visibility: auto; contain-intrinsic-size: auto 40px`, which tells the browser
     to skip laying out off-screen turns and stand in a 40px guess for each one. Every time
     that guess was wrong — which is every message longer than two lines — the transcript
     was laid out against fictional heights, so a query bubble or a Master Control card
     landed on top of the reply above it until something forced a real re-layout.
     It was a scroll-performance optimisation paid for in correctness. Removed: a
     transcript that renders wrong is not faster, it is broken. (2026-07-27 → 2026-08-16.) */
  .msg { max-width: min(1200px, 100%); line-height: 1.55; overflow-wrap: anywhere; font-family: var(--chat-font); }
  /* All messages LEFT-aligned in one consistent column (John, 2026-08-27: "they should all
     be aligned" — the centred column put queries in the middle). Cap the width for reading,
     but pin to the left edge so every query + reply lines up. */
  .msg.assistant, .msg.user { align-self: flex-start !important; text-align: left; margin-left: 0 !important; margin-right: auto !important; max-width: min(760px, 100%) !important; }
  /* The Interface-font picker lands ONLY here — the session conversation text. */
  .q-text { font-family: var(--chat-font); }
  /* one query + its whole reply = one .turn block; the query bubble pins inside
     its block, so the NEXT query physically pushes it out on contact (same as mobile) */
  .turn { display: flex; flex-direction: column; gap: var(--msg-gap); align-items: flex-start; }
  /* your messages: gray text with a hanging orange ›, left-aligned, so a query
     reads differently from a reply. It stays IN THE FLOW and scrolls away with the
     transcript — it does NOT pin. The floating "what this session is on" summary is
     the Context Card banner (.ctx-pop) alone, so the query never double-floats
     behind it. `relative` only so the ::before › anchors to the bubble. */
  .msg.user {
    align-self: flex-start; max-width: min(760px, 100%);
    position: relative;
    background: transparent; border: none; border-radius: 3px; box-shadow: none;
    font-family: 'SF Mono', ui-monospace, monospace; font-size: 13px; letter-spacing: .4px;
    color: var(--muted); padding: 3px 0 3px 20px; white-space: pre-wrap; word-wrap: break-word;
    cursor: pointer;
    /* Excluded from scroll-anchoring: these query bubbles collapse/expand as you scroll,
       and if the browser picked one as the anchor its resize would block scroll-to-top.
       Anchoring stays ON everywhere else (see .pane-body) so reflow doesn't jump. */
    overflow-anchor: none;
  }
  /* Queries stay PLAIN even when pinned — just gray text + the orange › (the original
     look, arrow + text). The Context Card is now a SEPARATE banner at the top of the
     pane (.ctx-pop), never the query bubble itself. They do not interact. */
  .msg.user.pinned { background: transparent; border: none; box-shadow: none; color: var(--muted); }
  .msg.user .u-context, .msg.user .pin-jump { display: none; }

  /* Context Card banner: pinned at the top of the pane, showing what this session is
     working on — the LAST query's AI summary (else its text), clamped to 2 lines. The
     transcript scrolls under it; query bubbles below stay plain + intact. */
  .ctx-pop {
    display: none; align-items: flex-start; gap: 8px; flex: 0 0 auto;
    position: relative; z-index: 2;   /* so the drop shadow lands ON the transcript below it */
    /* Full-width Context Card: 10px gutter top/left/right (John). NO gap BELOW it
       (John, 2026-07-25): a bottom margin left a white band between the card and the top
       of the scrolling transcript, and the transcript clipped THERE (a few px below the
       card) instead of at the card — so text appeared to "disappear" into a white border.
       margin-bottom:0 makes the content clip EXACTLY at the card's bottom edge, no band.
       NO downward drop-shadow — content meets the card cleanly, no dark bleed. */
    /* Mobile parity (John: "exactly this look, how it works"): tight 5px gutter + 12px
       side padding, matching mobile/src/styles.css .ctx-pop. */
    margin: 10px 10px 0; padding: 8px 12px; box-sizing: border-box;  /* top+sides spacing is MARGIN not padding (John, 2026-07-25) — space around the card, not inside it; bottom margin stays 0, no band */
    /* OPAQUE BLACK (John, 2026-08-18): the .015 accent wash was effectively transparent,
       so the transcript scrolled visibly behind this floating card. It must be a solid
       surface, not a tint. */
    background: var(--panel-2); border: 1px solid rgba(var(--accent-rgb), .30); border-radius: 3px;
    /* BLACK DROP SHADOW (John, 2026-08-17): the card floats above the scrolling
       transcript, so it needs to read as a layer — a soft black shadow under it, not the
       flat seam it had. Kept dark and tight so no light band ever appears below the card. */
    box-shadow: 0 4px 10px rgba(0,0,0,var(--sh55, .28)), 0 1px 3px rgba(0,0,0,var(--sh40, .2));
    color: #fff; cursor: pointer;              /* tappable like mobile → scrolls to the query */
    transition: transform .08s ease, border-color .15s ease;     /* mobile press feedback */
  }
  .ctx-pop.show { display: flex; }
  .ctx-pop:hover  { border-color: rgba(var(--accent-rgb), .5); }
  .ctx-pop:active { transform: scale(.99); border-color: rgba(var(--accent-rgb), .55); }
  /* Light theme (John, 2026-07-25): the card is dark-tuned (#1e1512 / #fff white text),
     so under light it stayed a black bar with white text. Re-anchor to a pale Sol-tinted
     surface with ink text — same warm-orange card identity, now legible on a light app.
     .ctx-body inherits this color; .ctx-mark keeps var(--accent), .ctx-loading var(--muted). */
  /* Light theme keeps an OPAQUE surface too — same reason as the dark rule above: this
     card floats over scrolling content and must never let it show through. */
  /* Shadow re-tuned too (John, 2026-08-23: "shadow is WAY too strong in light mode") — the
     .55/.4 opacities above were tuned for the dark card floating on a dark transcript;
     unchanged, they read as a heavy black smudge under a pale card on a pale background. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .ctx-pop { background: var(--panel); border-color: rgba(var(--accent-rgb), .28); color: var(--text); box-shadow: 0 6px 14px rgba(0,0,0,var(--sh12, .12)), 0 2px 4px rgba(0,0,0,var(--sh8, .08)); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .jump-latest { background: var(--panel); color: var(--text); }

  /* Unmerged branch-out branches, top of the sidebar. Flex-row discipline: the name is the
     only flexible child (flex:1 + min-width:0 so it truncates); count/meta never shrink. */
  /* No bottom margin: collapsed, that 6px sat inside the group between the header and the
     next section hairline, so the title read 6px above centre and shifted when the group
     opened (John, 2026-09-22). Section hairlines already separate the groups. */
  .side-branches { margin: 0; }
  .side-branches[hidden] { display: none; }
  .side-branches .sb-list[hidden] { display: none; }   /* the flex rule below would otherwise beat the hidden attribute (John, 2026-09-20: "open branches isn't closing anything") */
  /* Header + rows are styled to match the "Active Sessions" section (.sec-head / .active-row)
     EXACTLY — same padding, font, colours, and leading status dot — so the two sections read
     as one system. No disclosure caret (Active Sessions has none); the header still toggles
     collapse on click. */
  .side-branches .sb-head {
    display: flex; align-items: center; gap: 6px; padding: 8px; cursor: pointer;   /* match .sec-head (John, 2026-08-24) */
    color: var(--text); font-size: 10.5px; font-weight: 400;
    text-transform: uppercase; letter-spacing: .8px; white-space: nowrap; user-select: none;
  }
  .side-branches .sb-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .side-branches .sb-count {
    flex-shrink: 0; min-width: 16px; text-align: center; padding: 0 5px; height: 15px; line-height: 15px;
    background: var(--hover); color: var(--muted); border-radius: 3px; font-size: 10px;
  }
  /* CAP AT 5 ROWS, THEN SCROLL (John, 2026-08-18): with 20 open branches the list grew
     without limit and pushed Projects off the sidebar. --sb-row-h is the real height of
     one row (6px+6px padding + 2px margin + the two text lines), so five of them is an
     exact stop rather than a guessed pixel value; the 6th is half-visible, which is what
     tells you there IS more to scroll. */
  .side-branches .sb-list {
    display: flex; flex-direction: column; padding: 0 0 6px;
    --sb-row-h: 40px;
    max-height: calc(var(--sb-row-h) * 5);
    overflow-y: auto; overflow-x: hidden;
    scrollbar-width: auto;
  }
  .side-branches .sb-list::-webkit-scrollbar { width: 8px; }
  .side-branches .sb-list::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
  .side-branches .sb-list::-webkit-scrollbar-thumb:hover { background: var(--muted); }
  .side-branches .sb-list::-webkit-scrollbar-track { background: transparent; }
  /* Same card fill + 2px separation as the active-session rows (John, 2026-08-24). */
  .side-branches .sb-row {
    display: flex; align-items: center; gap: 7px; margin: 2px 8px; padding: 7px;
    border-radius: 0; font-size: 12px;
    background: color-mix(in srgb, var(--text) 5%, transparent);
  }
  .side-branches .sb-row:hover { background: color-mix(in srgb, var(--text) 9%, transparent); }
  .side-branches .sb-dot { flex-shrink: 0; width: 6px; height: 6px; border-radius: 2px; background: var(--muted); opacity: .85; }
  /* flex-row discipline: the text column is the only flexible child (flex:1 + min-width:0);
     dot, meta, and the merge button never shrink so long names truncate instead of pushing. */
  .side-branches .sb-rowmain { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
  .side-branches .sb-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 400; color: rgba(255,255,255,.8); }   /* match the Active Sessions row font */
  .side-branches .sb-sess { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--faint); font-size: 8.5px; }
  .side-branches .sb-sess.err { color: #e0704a; }
  /* Owning session, ABOVE the branch name — small + dim so it reads as a label for the row
     rather than competing with the name. Same truncation discipline as every other flex text
     child (min-width:0 + ellipsis) so a long session title can never push the buttons. */
  .side-branches .sb-from {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    color: var(--faint); font-size: 9px; letter-spacing: .03em; line-height: 1.25; opacity: .9;
  }
  /* A persisted merge error must be READABLE, not ellipsized to one clipped line — let it
     wrap and let the row grow past the 60px cap (screen-width discipline: minWidth 0 +
     overflow-wrap so the message can never run past the sidebar edge). */
  .side-branches .sb-row.has-err { max-height: none; align-items: flex-start; }
  .side-branches .sb-row.has-err .sb-sess.err { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; line-height: 1.3; margin-top: 2px; }
  .side-branches .sb-meta { flex-shrink: 0; color: #7d7470; font-size: 10px; font-variant-numeric: tabular-nums; }
  .side-branches .sb-merge {
    flex-shrink: 0; border: 1px solid rgba(var(--accent-rgb), .40); background: rgba(var(--accent-rgb), .12);
    color: var(--accent); font-size: 10px; font-weight: 600; padding: 2px 7px; border-radius: 3px;
    cursor: pointer; opacity: .55; transition: opacity .12s ease, background .12s ease;
  }
  .side-branches .sb-row:hover .sb-merge { opacity: 1; }
  .side-branches .sb-merge:hover { background: rgba(var(--accent-rgb), .25); }
  .side-branches .sb-merge:disabled { opacity: .5; cursor: default; }
  /* Branch conflicts with the base: the merge will stop for resolution, so the button
     reads as a caution ("merge anyway"), not the normal accent action (John, 2026-09-09). */
  .side-branches .sb-merge.has-conf { border-color: rgba(242,160,143,.5); background: rgba(242,160,143,.14); color: #f2a08f; }
  .side-branches .sb-row:hover .sb-merge.has-conf, .side-branches .sb-merge.has-conf:hover { background: rgba(242,160,143,.24); }
  /* pillar 4: per-branch action cluster (diff · merge · discard) + conflict-preview flag.
     flex-shrink:0 so the cluster holds while long names truncate (screen-width discipline). */
  .side-branches .sb-bo-acts { flex-shrink: 0; display: flex; align-items: center; gap: 4px; }
  .side-branches .sb-bo-diff, .side-branches .sb-bo-discard {
    flex-shrink: 0; border: 1px solid var(--line); background: transparent; color: var(--muted);
    font-size: 10px; font-weight: 600; padding: 2px 6px; border-radius: 3px; cursor: pointer;
    opacity: .5; transition: opacity .12s ease, background .12s ease, color .12s ease;
  }
  .side-branches .sb-row:hover .sb-bo-diff, .side-branches .sb-row:hover .sb-bo-discard { opacity: 1; }
  .side-branches .sb-bo-diff:hover { background: var(--hover); color: var(--text); }
  .side-branches .sb-bo-discard { color: #c56; border-color: rgba(200,90,100,.3); padding: 2px 6px; }
  .side-branches .sb-bo-discard:hover { background: rgba(255,92,77,.14); color: #ff5c4d; }
  .side-branches .sb-bo-diff:disabled, .side-branches .sb-bo-discard:disabled { opacity: .4; cursor: default; }
  /* Commit: shown only on a worktree row with uncommitted edits, where merge is absent
     because there is nothing committed to merge. It is the one action that moves that
     row forward, so it reads as the primary one. (John, 2026-09-23) */
  .side-branches .sb-bo-commit {
    flex-shrink: 0; border: 1px solid var(--line); background: transparent;
    color: var(--accent); font-size: 10px; font-weight: 600; padding: 2px 6px; border-radius: 3px;
    cursor: pointer; transition: background .12s ease, color .12s ease;
  }
  .side-branches .sb-bo-commit:hover { background: rgba(var(--accent-rgb), .14); }
  .side-branches .sb-bo-commit:disabled { opacity: .4; cursor: default; }
  .side-branches .sb-bo-conf { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #e0a44a; font-size: 8.5px; font-weight: 600; }
  /* reserved line: the flag toggling between empty and filled must never change the row height */
  .side-branches .sb-bo-conf { min-height: 11px; line-height: 11px; }
  .side-branches .sb-bo-conf.is-empty { visibility: hidden; }
  /* Conflict resolution: two side-choice buttons under the error line so a conflicted merge
     is a one-click decision, never a terminal errand. The row grows to fit them (max-height). */
  .side-branches .sb-row:has(.sb-bo-resolve) { max-height: 120px; }
  .side-branches .sb-bo-resolve { display: flex; gap: 6px; margin-top: 5px; }
  .side-branches .sb-bo-take {
    flex: 0 0 auto; border: 1px solid rgba(var(--accent-rgb), .40); background: rgba(var(--accent-rgb), .12);
    color: var(--accent); font-size: 10px; font-weight: 600; padding: 3px 8px; border-radius: 3px;
    cursor: pointer; transition: background .12s ease;
  }
  .side-branches .sb-bo-take:hover { background: rgba(var(--accent-rgb), .25); }
  .side-branches .sb-bo-take:disabled { opacity: .5; cursor: default; }
  /* Replaying on base is the only choice that keeps BOTH sides, so it reads as the primary
     action next to the two lossy ones (John, 2026-09-19). Accent fill, readable ink. */
  .side-branches .sb-bo-take.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 700; }
  .side-branches .sb-bo-take.primary:hover { background: var(--accent); filter: brightness(1.07); }
  /* diff modal: clean / conflict banner above the stat line */
  .bd-banner { display: block; font-size: 11px; font-weight: 700; padding: 4px 8px; border-radius: 3px; margin-bottom: 6px; overflow-wrap: anywhere; }
  .bd-banner.clean { color: #34c759; background: rgba(52,199,89,.12); }
  .bd-banner.conflict { color: #ff5c4d; background: rgba(255,92,77,.12); }
  .bd-stat { white-space: pre-wrap; }
  /* Optimistic merge: the row collapses out the INSTANT you click, so it never lingers
     while the git merge + re-list run in the background (that was the "slow to disappear").
     Restored if the merge actually fails. */
  .side-branches .sb-row { transition: max-height .2s ease, opacity .16s ease, padding .2s ease, margin .2s ease; max-height: 88px; overflow: hidden; }
  /* A branch-out still BUILDING shows here immediately as a live, non-mergeable row, so the
     branch is visible the moment you kick it off — not only after the merge finishes. The
     real, mergeable row replaces it when the run completes. */
  .side-branches .sb-row.building { opacity: .82; cursor: default; }
  .side-branches .sb-row.building:hover { background: transparent; }
  .side-branches .sb-row.building .sb-name { color: var(--accent); display: flex; align-items: center; gap: 6px; }
  .side-branches .sb-bo-spin { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%;
    border: 1.5px solid rgba(var(--accent-rgb), .30); border-top-color: var(--accent);
    animation: sb-bo-rot .7s linear infinite; }
  @keyframes sb-bo-rot { to { transform: rotate(360deg); } }
  .side-branches .sb-row.merging-out { max-height: 0; opacity: 0; padding-top: 0; padding-bottom: 0; margin-top: 0; margin-bottom: 0; pointer-events: none; }
  /* Merging in progress: the clicked button reads "Merging" and the WHOLE section
     adopts the branch-out signature gold (--bo-*) so the active state is unmistakable.
     Toggled by the .merging class on #sideBranches; cleared on re-render or failure. */
  .side-branches.merging { background: linear-gradient(180deg, rgba(var(--bo-rgb), .06), rgba(var(--bo-rgb), 0) 72%); border-radius: 3px; }
  .side-branches.merging .sb-head, .side-branches.merging .sb-title { color: var(--bo-txt); }
  .side-branches.merging .sb-caret { color: var(--bo-lt); }
  .side-branches.merging .sb-count { background: rgba(var(--bo-rgb), .20); color: var(--bo-lt); }
  .side-branches.merging .sb-dot { background: var(--bo-lt); box-shadow: none; opacity: 1; }
  .side-branches.merging .sb-merge {
    opacity: 1; border-color: rgba(var(--bo-rgb), .5); background: rgba(var(--bo-rgb), .16); color: var(--bo-lt);
  }
  .side-branches.merging .sb-merge:hover { background: rgba(var(--bo-rgb), .26); }
  /* the row actually merging (its button is disabled): stays full-gold and softly pulses */
  .side-branches.merging .sb-merge:disabled { opacity: 1; animation: bo-merge-pulse 1.1s ease-in-out infinite; }
  @keyframes bo-merge-pulse { 0%, 100% { opacity: .6; } 50% { opacity: 1; } }
  /* Stranded-work warning row: amber, distinct from the orange branch rows, so a
     shelved (stashed) chunk of work reads as "attention needed", never as normal. */
  .side-branches .sb-stashwrap { margin: 4px 0 2px; }
  .side-branches .sb-stash-head {
    display: flex; align-items: center; gap: 6px; padding: 2px 2px 4px;
    font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #e3b341;
  }
  .side-branches .sb-stash {
    display: flex; flex-direction: column; gap: 6px; margin: 3px 0 1px; padding: 7px 8px;
    border: 1px solid rgba(227, 179, 65, .40); background: rgba(227, 179, 65, .10);
    border-radius: 3px; cursor: default;
  }
  .side-branches .sb-stash-top { display: flex; align-items: center; gap: 7px; }
  .side-branches .sb-stash-ic { flex-shrink: 0; font-size: 12px; line-height: 1; color: #e3b341; }
  .side-branches .sb-stash .sb-rowmain { flex: 1; min-width: 0; }   /* screen-width discipline: text child must be allowed to shrink */
  .side-branches .sb-stash .sb-name { color: #e9cd80; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .side-branches .sb-stash .sb-sess { color: #a8935a; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Three actions share the row evenly so none overflows the sidebar. */
  .side-branches .sb-st-actions { display: flex; gap: 6px; }
  .side-branches .sb-st-btn {
    flex: 1; min-width: 0; border: 1px solid rgba(227, 179, 65, .40); background: rgba(227, 179, 65, .10);
    color: #e3b341; font-size: 10px; font-weight: 600; padding: 4px 6px; border-radius: 3px;
    cursor: pointer; transition: background .12s ease, opacity .12s ease;
  }
  .side-branches .sb-st-btn:hover { background: rgba(227, 179, 65, .22); }
  .side-branches .sb-st-btn:disabled { opacity: .55; cursor: default; }
  .side-branches .sb-st-btn.danger { border-color: rgba(var(--accent-rgb), .45); background: rgba(var(--accent-rgb), .10); color: #e07a5f; }
  .side-branches .sb-st-btn.danger:hover { background: rgba(var(--accent-rgb), .22); }
  .side-branches .sb-st-msg { font-size: 10.5px; line-height: 1.4; overflow-wrap: anywhere; }
  .side-branches .sb-st-msg.ok { color: #7fc98a; }
  .side-branches .sb-st-msg.err { color: #e07a5f; }
  /* Stash diff viewer — wider than the default modal; scrollable monospace patch. */
  .stash-modal { width: 760px; max-width: 92vw; }
  .stash-modal h3 { word-break: break-word; }
  .stash-modal .stash-stat { color: var(--muted); font-family: "SF Mono", ui-monospace, monospace; font-size: 11px; white-space: pre-wrap; margin: 4px 0 10px; }
  .stash-modal .stash-diff {
    max-height: 56vh; overflow: auto; background: var(--panel-2); border: 1px solid var(--line);
    border-radius: 3px; padding: 10px 12px; font-family: "SF Mono", ui-monospace, monospace;
    font-size: 11.5px; line-height: 1.5; white-space: pre; margin: 0;
  }
  .stash-modal .stash-diff .dl { display: block; }
  .stash-modal .stash-diff .add { color: #7fc98a; }
  .stash-modal .stash-diff .del { color: #e07a5f; }
  .stash-modal .stash-diff .hunk { color: #6cb6d9; }
  .stash-modal .stash-diff .meta { color: var(--muted); }
  .ctx-pop .ctx-mark { flex: 0 0 auto; color: var(--accent); font-weight: 700; font-family: 'SF Mono', ui-monospace, monospace; line-height: 1.5; }
  .ctx-pop .ctx-body {
    flex: 1; min-width: 0; font-size: 13px; line-height: 1.5; letter-spacing: .3px;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; word-break: break-word;
  }
  /* Waiting on the work-based label: dim + italic + soft pulse, never the raw query. */
  .ctx-pop .ctx-body.ctx-loading { font-style: italic; color: var(--muted); opacity: .8; animation: ctxpulse 1.3s ease-in-out infinite; }
  @keyframes ctxpulse { 0%, 100% { opacity: .45; } 50% { opacity: .85; } }
  /* Queries are ALWAYS shown in full — never collapsed to one line. When pinned at the
     top they get the floating card look (above) but keep their whole text wrapping,
     so nothing you sent is ever hidden behind an ellipsis. */
  /* Query chevron drawn as an SVG (not the "›" glyph) so its THICKNESS and LENGTH are
     controllable: doubled stroke, ~2× taller (John, 2026-08-25). Accent-tinted via mask. */
  .msg.user::before {
    content: ""; position: absolute; left: 1px; top: 1px; width: 7px; height: 22px;
    background: var(--accent);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 5 9 12 3 19'/%3E%3C/svg%3E") no-repeat center / contain;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 5 9 12 3 19'/%3E%3C/svg%3E") no-repeat center / contain;
  }
  /* interrupt notice ("[Request interrupted by user]") — red, faintly glowing, no marker */
  .msg.user.interrupted { background: transparent; border-color: transparent; box-shadow: none; color: #e5484d; text-shadow: none; margin-left: 0; padding-left: 0; text-align: left; }
  .msg.user.interrupted::before { content: none; }
  /* Profanity glitch — a bad word sits as NORMAL text (same color as the line, not
     accent), then every few seconds the WHOLE word bugs out: a quick jitter + an
     RGB-split flash. The glitch IS the tell, not the color. Minimal but noticeable. */
  .badword {
    position: relative; display: inline-block; color: inherit; font-weight: inherit;
  }
  .badword::before, .badword::after {
    content: attr(data-text); position: absolute; left: 0; top: 0; width: 100%;
    pointer-events: none; opacity: 0;   /* invisible until the brief glitch moment */
  }
  .badword::before { color: #ff2d2d; }
  .badword::after { color: #29d3ff; }
  @media (prefers-reduced-motion: no-preference) {
    .badword { animation: bwGlitch 2.8s steps(1, end) infinite; }
    .badword::before { animation: bwSplitA 2.8s steps(1, end) infinite; }
    .badword::after { animation: bwSplitB 2.8s steps(1, end) infinite; }
  }
  /* pause when the window isn't focused (resource discipline, same as the logo);
     app-hidden already pauses ALL animation globally. */
  @media (prefers-reduced-motion: no-preference) {
    body.app-blur .badword, body.app-blur .badword::before, body.app-blur .badword::after { animation-play-state: paused !important; }
  }
  /* quiet for ~85% of the cycle, then a slightly longer double bug-out */
  @keyframes bwGlitch {
    0%, 84%, 100% { transform: translate(0, 0); }
    85% { transform: translate(-1px, 1px) skewX(-3deg); }
    88% { transform: translate(1px, -1px) skewX(2deg); }
    91% { transform: translate(-1px, 0); }
    94% { transform: translate(1px, 1px) skewX(-1deg); }
    97% { transform: translate(0, 0); }
  }
  @keyframes bwSplitA {
    0%, 84%, 100% { opacity: 0; transform: translate(0, 0); }
    85% { opacity: .65; transform: translate(-2px, 0); }
    89% { opacity: .4; transform: translate(-1px, 1px); }
    93% { opacity: .6; transform: translate(-2px, -1px); }
    96% { opacity: 0; }
  }
  @keyframes bwSplitB {
    0%, 84%, 100% { opacity: 0; transform: translate(0, 0); }
    85% { opacity: .65; transform: translate(2px, 0); }
    89% { opacity: .4; transform: translate(1px, -1px); }
    93% { opacity: .6; transform: translate(2px, 1px); }
    96% { opacity: 0; }
  }
  /* relayed from another session — clearly not something you typed here */
  .msg.xmsg {
    align-self: flex-start; max-width: min(760px, 100%);
    background: transparent; border: 1px dashed var(--line); border-radius: 3px;
    color: var(--muted); padding: 8px 12px; white-space: pre-wrap; word-wrap: break-word;
  }
  .msg.xmsg .xmsg-from { font-size: 10.5px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--faint); margin-bottom: 5px; }
  /* Auto follow-up card: a quiet system card, never John's own prompt bubble. */
  .msg.autocheck {
    align-self: flex-start; max-width: min(760px, 100%);
    background: transparent; border: 1px dashed var(--line); border-radius: 3px;
    color: var(--muted); padding: 8px 12px;
  }
  .msg.autocheck .autocheck-head { font-size: 10.5px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--faint); margin-bottom: 4px; }
  .msg.autocheck .autocheck-body { font-size: 12.5px; line-height: 1.4; }
  /* Same "⇄ from <session>" label on the QUEUE row, so a handed-off item is readable as
     someone else's ask before it ever runs — not after. Matches the card's header above. */
  .q-item .q-from { font-size: 10px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--faint); padding: 0 2px 3px; }
  /* a note added INTO a running turn (Ctrl+Enter) — same plain "›" query look as
     .msg.user (no box, no header), so it reads as yours, not a separate card */
  .msg.assistant { align-self: flex-start; word-wrap: break-word; padding: 2px 4px; letter-spacing: .2px; }
  /* Every reply carries a hanging ACCENT BAR (a short quote-rail), tinted to the MODEL that
     wrote it — Opus orange, Sonnet blue, Fable purple, Haiku mint. Distinct from your prompt's
     › so an answer reads different from a question. --model-c is set per bubble by the
     renderer; when it's unknown the bar falls back to Sol orange. Only bubbles the renderer
     tags `.arrowed` get it, so cards (research/recap/images) stay clean. (John, 2026-08-09.) */
  .msg.assistant.arrowed { position: relative; padding-left: 20px; }
  .msg.assistant.arrowed::before {
    content: ""; background: var(--model-c, var(--accent));
    position: absolute; left: 2px; top: 4px; width: 2px; height: 13.5px; border-radius: 3px;
  }
  /* Safety net (John, 2026-08-17): never paint the accent bar on a bubble with no real
     content — only the hover reply furniture (.msg-tools). A bubble that has any actual
     rendered content keeps its bar; one that has only the tools bar (or nothing) hides it,
     so a blank line never shows a lone rail even if an empty bubble slips through. */
  .msg.assistant.arrowed:not(:has(> :not(.msg-tools)))::before { display: none; }
  /* A reply that is ONLY cards (Recap / Action) must not also draw the message's own
     little accent rail above them — that stub read as a stray orange tick with nothing
     attached to it (John, 2026-08-17). The cards carry their own full-height rail. */
  .msg.assistant.arrowed:not(:has(> :not(.recap-card):not(.action-card):not(.msg-tools)))::before { display: none; }
  /* (removed 2026-08-18) A padding-left:2px override for card-only Recap/Action bubbles
     lived here. The full-width card rule now cancels the bubble's padding on the card
     itself, so the bubble must keep its normal 20px for this to land flush. */
  /* the streaming span stays plain-wrapped until it settles into markdown blocks */
  .msg.assistant .a-text { white-space: pre-wrap; }
  /* rendered markdown — real formatting, never raw ** / # / - markup */
  .msg.assistant .md-p { white-space: pre-wrap; }
  .msg.assistant .md-gap { height: .55em; }
  .msg.assistant .md-h { font-weight: 700; color: #fff; letter-spacing: .1px; margin: .35em 0 .1em; }
  .msg.assistant .md-h1 { font-size: 1.22em; }
  .msg.assistant .md-h2 { font-size: 1.12em; }
  .msg.assistant .md-h3 { font-size: 1.04em; }
  .msg.assistant .md-list { display: flex; flex-direction: column; gap: 3px; margin: .2em 0; }
  .msg.assistant .md-li { display: flex; gap: 8px; align-items: baseline; }
  .msg.assistant .md-bullet { flex: 0 0 auto; color: var(--accent); font-weight: 700; }
  .msg.assistant .md-bullet.md-num { color: var(--muted); font-variant-numeric: tabular-nums; min-width: 1.3em; }
  .msg.assistant .md-litext { flex: 1; min-width: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
  /* Blockquote callout: a note / aside / comment Claude flags as worth reading.
     Neutral GRAY card with a gray accent bar. Holds rich content, so it force-wraps
     and never runs past the pane edge. */
  .msg.assistant .md-quote {
    margin: .55em 0; padding: 8px 13px; box-sizing: border-box; max-width: 100%;
    background: rgba(255,255,255,.035); border: 1px solid rgba(255,255,255,.07);
    border-radius: 3px; color: var(--muted); overflow-wrap: anywhere;
  }
  .msg.assistant .md-quote > .md-gap:first-child,
  .msg.assistant .md-quote > .md-gap:last-child { height: 0; }
  .msg.assistant .md-quote .md-h { color: var(--text); }
  /* pipe tables — a too-wide table scrolls inside its own box, never pushing the pane */
  .msg.assistant .md-table-wrap { max-width: 100%; min-width: 0; overflow-x: auto; margin: 9px 0; }
  .msg.assistant .md-table { border-collapse: collapse; font-size: .92em; line-height: 1.45; }
  .msg.assistant .md-table th, .msg.assistant .md-table td { border: 1px solid var(--line); padding: 6px 11px; text-align: left; vertical-align: top; overflow-wrap: anywhere; }
  .msg.assistant .md-table th { background: var(--panel-2); color: #fff; font-weight: 700; white-space: nowrap; }
  .msg.assistant .md-table td { color: var(--text); }
  .msg.assistant .md-table tbody tr:nth-child(even) td { background: rgba(255,255,255,.025); }
  .msg.assistant .md-table code { white-space: nowrap; }
  .msg.assistant strong { font-weight: 700; color: #fff; }
  .msg.assistant em { font-style: italic; }
  .msg.assistant code { font-family: "SF Mono", ui-monospace, monospace; font-size: .9em; background: rgba(255,255,255,.07); border: 1px solid var(--line); border-radius: 3px; padding: 0 4px; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
  /* One continuous selection (John, 2026-08-26): a dragged highlight must read as a
     single band, not a string of islands. The inline code chips' own border + rounded
     box drew a crisp island around each one under the translucent selection. While the
     message is being selected, drop the chip border/fill so the uniform ::selection band
     runs straight across code and prose. `.selecting` is toggled on the pane during a
     drag-select (JS below); the chip look is untouched at rest. */
  .pane-body.selecting .msg.assistant code { background: transparent; border-color: transparent; }
  .msg.assistant ::selection { background: rgba(var(--accent-rgb), .32); color: #fff; }
  .msg.assistant ::-moz-selection { background: rgba(var(--accent-rgb), .32); color: #fff; }
  /* commands / links Claude hands you: same card shape as your own messages,
     but neutral gray instead of brand orange, and one-click copyable. */
  /* Recap Card — batch summary rendered from a ```recap fence. MA design: instead of
     a filled, fully-boxed card, the card IS the negative space — no background tint,
     no enclosing border, just one thin rule (間) marking the edge and generous air
     around the content. Quiet by default; the rule + label carry the color, not a fill.
     Reuses the .md-* block styles for its heading + bullets. */
  .recap-card {
    /* Recap is ALWAYS ORANGE — it does NOT follow the accent picker (John, 2026-07-30).
       Recap/Action are a semantic PAIR: Action is hard-coded gold (#e3b341) just below,
       so leaving Recap on var(--accent) made it drift to gray/pink/blue with the theme
       while its sibling stayed gold — the pair stopped reading as a pair. All three
       accent tokens are re-declared here, not just --accent-rgb: --accent and
       --accent-soft are substituted at `body` (app.css:1094), so their INHERITED values
       are already the picked colour and overriding the -rgb alone would not reach them.
       Pinned to 255, 106, 68 = the default accent orange, i.e. exactly what this card
       rendered before the picker existed. Anything nested here is orange by design. */
    --accent-rgb: 255, 88, 34;
    --accent: rgb(255, 88, 34);
    --accent-soft: rgba(255, 88, 34, .14);
    --on-accent: #1a1a1a;   /* accent is re-pinned to orange here, so ink stays dark */
    align-self: stretch;
    background: transparent;
    border: none; border-left: 2px solid rgba(var(--accent-rgb), .7);
    border-radius: 3px;
    /* Text lines up with ordinary reply text (John, 2026-08-17): a normal reply puts its
       accent bar at left:2px and its text at 20px, so 2px rail + 18px padding lands the
       card's words on exactly the same column. Right padding trimmed to match. */
    padding: 14px 18px 16px; margin: 22px 0;
  }
  .recap-card .md-h { color: var(--accent) !important; opacity: 1; margin: 0 0 8px; }
  .recap-card .md-list { margin: 0; }
  .recap-card .md-li { margin: 6px 0; }
  .recap-card .md-litext strong { color: var(--accent); opacity: 1; }
  /* auto label at the top of a Recap / Action card — quiet, wide-set, no icon, no fill */
  .recap-card .card-label, .action-card .card-label {
    font-size: 10px; font-weight: 600; letter-spacing: 1.6px; text-transform: uppercase;
    opacity: .55; margin: 0 0 10px;
  }
  .recap-card .card-label { color: var(--accent); opacity: .9; }
  /* ACTION card — GOLD, same MA shape as Recap: a single rule, open air, no box.
     Kept visually distinct from the (orange) Recap by rule + label color alone,
     so actions and summaries never blur together even without a fill or border. */
  .action-card {
    align-self: stretch;
    background: transparent;
    /* Rail is the custom ACCENT (John, 2026-08-24: "I need action to also be custom color"),
       replacing the fixed gold it wore before. */
    border: none; border-left: 2px solid rgba(var(--accent-rgb), .55);
    border-radius: 3px; padding: 14px 18px 16px; margin: 22px 0;
  }
  .action-card .card-label { color: var(--accent); }
  .action-card .md-list { margin: 0; }
  .action-card .md-li { margin: 7px 0; align-items: flex-start; }
  .action-card .md-litext strong { color: var(--accent); }
  /* The completed-item checkbox inside the Action card follows the accent too. */
  .action-card .task-card-check { border-color: rgba(var(--accent-rgb), .75); }
  .action-card .task-card-row:hover .task-card-check { border-color: var(--accent); }
  .action-card .task-card-row.done .task-card-check { background: var(--accent); border-color: var(--accent); }
  /* A link inside the Action card takes the accent instead of the default gray, so a
     tappable URL (e.g. an OTA install link) reads as an actionable part of the card. */
  .action-card .a-link { color: var(--accent); font-weight: 600; text-decoration-color: rgba(var(--accent-rgb),.55); }
  .action-card .a-link:hover { color: var(--accent); filter: brightness(1.15); }
  /* Light mode: darken ONLY the Action card's title so the raw accent (e.g. neon)
     is legible on white — nowhere else (John, 2026-08-25). */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .action-card .card-label {
    color: color-mix(in srgb, rgb(var(--accent-rgb)) 58%, #000);
  }
  /* (removed 2026-08-18) The old -18px mixed-reply pull for Recap/Action lived here. It
     parked those two cards 2px in from the column while every other card sat flush, which
     is exactly the size mismatch John called out. They now share the one full-width rule
     below ("CARDS ARE ALWAYS FULL WIDTH") with the rest of the family. */
  .recap-card .a-link { color: var(--accent); font-weight: 600; }
  .recap-card .a-link:hover { filter: brightness(1.18); }
  /* ===== CARDS ARE ALWAYS FULL WIDTH (John, 2026-08-18: "cards should be full width
     not inside parent's rules") ================================================
     A card must span the whole chat column no matter who its parent is. A NOTE or TASK
     card is appended straight to .pane-body, so it already does. A QUESTION, DOC,
     MEMORY, RAW-DATA, RECAP or ACTION card is built inside the assistant bubble and was
     inheriting that bubble's box instead: 4px of side padding, 20px more on the left for
     the accent-bar gutter, and a fit-content width capped at 760px. So the same card CSS
     drew two different sizes depending on where it was born.
     Fix in two parts: (1) any bubble holding a card stretches to the full column and
     drops the 760px cap; (2) the card cancels the bubble's horizontal padding with
     negative margins, so it lands on the exact same left and right edge as a note card.
     Descendant selectors, not `>` — a card nested one level deeper must still break out. */
  .msg.assistant:has(.ask-card, .note-card, .doc-card, .memory-card, .raw-data-card, .recap-card, .action-card) {
    align-self: stretch; max-width: none;
  }
  .msg.assistant :is(.ask-card, .note-card, .doc-card, .memory-card, .raw-data-card, .recap-card, .action-card) {
    margin-left: -4px; margin-right: -4px;
  }
  .msg.assistant.arrowed :is(.ask-card, .note-card, .doc-card, .memory-card, .raw-data-card, .recap-card, .action-card) {
    margin-left: -20px;
  }
  /* CARD SPACING (John, 2026-08-18: "too much space between two cards. Keep them tight
     but with a little bit of separation"). Every card carried its own 20-22px vertical
     margin AND sat in a flex column with a 20px gap, and flex margins never collapse —
     so two stacked cards were 60px+ apart. A card that is its own row drops the margin
     entirely and lets the column gap (the Message-spacing setting) be the one separator;
     a card nested in a bubble keeps a small margin, since nothing else separates it from
     the prose around it. */
  .pane-body > :is(.ask-card, .note-card, .doc-card, .memory-card, .raw-data-card, .task-card),
  .turn > :is(.ask-card, .note-card, .doc-card, .memory-card, .raw-data-card, .task-card) {
    margin-top: 0; margin-bottom: 0;
  }
  .msg.assistant :is(.ask-card, .note-card, .doc-card, .memory-card, .raw-data-card, .recap-card, .action-card) {
    margin-top: 10px; margin-bottom: 10px;
  }
  .msg.assistant > :is(.ask-card, .note-card, .doc-card, .memory-card, .raw-data-card, .recap-card, .action-card):first-child { margin-top: 0; }
  .msg.assistant > :is(.ask-card, .note-card, .doc-card, .memory-card, .raw-data-card, .recap-card, .action-card):last-child { margin-bottom: 0; }
  /* NOTE card — the //note surface. Same MA shape as Recap/Action (a single left
     rule, open air, no box), but BLUE (#4aa3ff = the app's synced/connected blue,
     same as the cloud connector badge) because a note rides the mainframe to every
     device. It is the user's marker, never a Claude reply. */
  /* ===== NOTE CARD — clean panel (John's reference, 2026-08-16) =================
     A plain rounded card: header strip (breadcrumb title + small chip), a full-width
     divider, then the note. Replaces the notched HUD card with its rail and diagonals.
     ONE shape for both kinds; only the accent differs — Master Controller gold, John's
     own blue. HARD RULE: body text is NEVER coloured. */
  .note-card {
    align-self: stretch;
    flex: 0 0 auto;              /* pane-body is a column flex — never let it squeeze */
    background: #0f0f10;
    border: 1px solid var(--line);
    border-radius: 3px;            /* square edges (John, 2026-08-16) */
    padding: 0; margin: 20px 0;
    --nc: #4aa3ff;               /* John's own note: the app's synced blue */
  }
  .note-card.mc-note { --nc: var(--bo-lt); }
  /* NARROW PANES (John, 2026-08-16). The header was one rigid row, so in a split pane
     "Master Controller" wrapped mid-phrase while "/ Question" stayed pinned to the first
     line and the chip crashed into both. Now the head WRAPS: the crumb holds one
     unbreakable line and the chip drops below it when there is no room, instead of
     everything fighting for the same row. */
  .note-card .nc-head {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 4px 12px;
    padding: 11px 16px;
    border-bottom: 1px solid var(--line);
  }
  .note-card .nc-crumb {
    flex: 1 1 auto; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .note-card .nc-from { color: var(--nc); font-size: 12.5px; font-weight: 600; letter-spacing: .2px; }
  .note-card .nc-sep { color: var(--faint); font-size: 12.5px; margin: 0 7px; }
  .note-card .nc-kind { color: var(--muted); font-size: 12.5px; }
  .note-card .nc-chip {
    flex: 0 0 auto; margin-left: auto;
    font-size: 9px; font-weight: 700; letter-spacing: 1.4px;
    padding: 3px 7px; border-radius: 3px;
    color: var(--nc); background: color-mix(in srgb, var(--nc) 14%, transparent);
  }
  /* A date chip reads as a timestamp, not a status tag: normal case, no wide tracking,
     and no tinted pill background so it sits quietly at the right edge. */
  .note-card .nc-chip.nc-date {
    font-size: 11px; font-weight: 600; letter-spacing: .2px;
    padding: 0; border-radius: 0;
    color: var(--muted); background: none;
  }
  .note-card .nc-body { padding: 13px 16px 15px; min-width: 0; overflow-wrap: anywhere; }
  /* THE BODY — plain text, no tint, ever. */
  .note-card .nc-body,
  .note-card .nc-body .md-p,
  .note-card .nc-body .md-litext,
  .note-card .nc-body .md-h,
  .note-card .nc-body strong { color: var(--text); }
  .note-card .nc-body .md-h { font-size: 1em; margin: 0 0 6px; }
  .note-card .nc-body .md-list { margin: 0; }
  .note-card .nc-body .md-li { margin: 5px 0; }
  .note-card .nc-body .md-bullet { color: var(--nc); }
  .note-card .nc-body .a-link { color: var(--nc); font-weight: 600; }
  .note-card .nc-body .a-link:hover { filter: brightness(1.18); }
  /* Memory card (//journal): amber, the journal's "Always do this" colour — a note
     is a marker in the thread; a memory is something the model is HANDED every turn, so
     it gets its own standing-rule colour, not the note's synced-blue. */
  /* Purple "doc updated" card: a session created or grew a Journal doc. Clickable. */
  /* Rebuilt in the app's ONE card language (John, 2026-08-17: "use our new card style,
     KILL that default style forever"). Identical bones to .note-card — square 3px panel,
     #0f0f10 surface, header strip with a divider, chip on the right — just wearing purple
     via --nc. The old rounded 12px tinted-pill look is gone for good. */
  .doc-card {
    align-self: stretch;
    flex: 0 0 auto;
    background: #0f0f10;
    border: 1px solid var(--line);
    border-radius: 3px;
    padding: 0; margin: 20px 0;
    cursor: pointer;
    --nc: #a78bfa;               /* the doc card's own purple */
    transition: border-color .12s;
  }
  .doc-card:hover { border-color: color-mix(in srgb, var(--nc) 45%, var(--line)); }
  .doc-card .nc-head,
  .doc-card-head {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 4px 12px;
    padding: 11px 16px;
    border-bottom: 1px solid var(--line);
  }
  .doc-card-ic { color: var(--nc); font-size: 13px; flex: 0 0 auto; }
  .doc-card-txt { flex: 1 1 auto; min-width: 0; padding: 13px 16px 15px; }
  .doc-card-title { color: var(--nc); font-size: 12.5px; font-weight: 600; letter-spacing: .2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .doc-card-sub { font-size: 12.5px; color: var(--muted); margin-top: 3px; }
  /* The "resume" — a sentence of what the doc holds, dimmer than the title, wraps to
     at most two lines so a long body can't blow the card up. */
  .doc-card-summary {
    font-size: 12px; color: var(--faint); line-height: 1.4; margin-top: 6px;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  /* Coalesced multi-doc card: one tappable row per doc under the "N docs · when" line. */
  .doc-card-list { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; }
  .doc-card-item {
    text-align: left; background: none; border: 0; cursor: pointer;
    font-size: 12.5px; color: var(--text); padding: 4px 8px; border-radius: 4px;
    display: flex; align-items: baseline; gap: 7px;
  }
  .doc-card-item::before {
    content: ""; flex: 0 0 auto; width: 4px; height: 4px; border-radius: 50%;
    background: var(--nc); opacity: .55; transform: translateY(-2px);
  }
  .doc-card-item-name { flex: 0 0 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 45%; }
  .doc-card-item-sum { flex: 1 1 auto; min-width: 0; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .doc-card-item:hover { background: color-mix(in srgb, var(--nc) 12%, transparent); }
  .doc-card-go {
    flex: 0 0 auto; margin-left: auto;
    font-size: 9px; font-weight: 700; letter-spacing: 1.4px; text-transform: uppercase;
    padding: 3px 7px; border-radius: 3px;
    color: var(--nc); background: color-mix(in srgb, var(--nc) 14%, transparent);
  }

  .memory-card {
    --accent-rgb: 255, 106, 68;
    --accent: #ff8a3d;
    --accent-soft: rgba(255, 138, 61, .14);
    --on-accent: #1a1a1a;   /* accent re-pinned to orange here, keep ink dark */
    align-self: stretch;
    background: transparent;
    border: none; border-left: 2px solid rgba(255, 138, 61, .5);
    border-radius: 3px;
    padding: 16px 22px 18px; margin: 22px 0;
  }
  .memory-card .card-label {
    color: #ff8a3d;
    font-size: 10px; font-weight: 600; letter-spacing: 1.6px; text-transform: uppercase;
    opacity: .6; margin: 0 0 10px;
  }
  .memory-card .md-h { color: #ff8a3d !important; opacity: .85; margin: 0 0 8px; }
  .memory-card .md-list { margin: 0; }
  .memory-card .md-li { margin: 6px 0; }
  .memory-card .md-litext strong { color: #ff8a3d; opacity: .9; }
  .memory-card .a-link { color: #ff8a3d; font-weight: 600; }
  .memory-card .a-link:hover { filter: brightness(1.18); }
  /* bullets render as slim gold checkbox squares — thinner stroke, more air, so the
     to-do list reads as calm rather than boxy */
  .action-card .md-li .md-bullet:not(.md-num) { font-size: 0; flex: 0 0 auto; margin-top: 3px; }
  .action-card .md-li .md-bullet:not(.md-num)::before {
    content: ""; display: inline-block; width: 11px; height: 11px;
    border: 1.4px solid rgba(var(--accent-rgb), .8); border-radius: 3px; box-sizing: border-box;
  }
  /* the square is tickable: hover invites a click, and a done item fills with the ACCENT
     (John, 2026-08-24: "check mark also needs to be custom selected color"). */
  .action-card .md-li.al-card-li .md-bullet:not(.md-num) { cursor: pointer; }
  .action-card .md-li.al-card-li:hover .md-bullet:not(.md-num)::before { background: rgba(var(--accent-rgb), .22); }
  .action-card .md-li.done .md-bullet:not(.md-num)::before {
    background: var(--accent);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231a1305' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
    background-size: 9px 9px; background-position: center; background-repeat: no-repeat;
  }
  .action-card .md-li.done .md-litext { opacity: .5; text-decoration: line-through; }
  /* CLEARED (removed from the Action list) — struck through like done, but dimmer and
     inert: the box stays empty because he never ticked it, he retired it. (John, 2026-07-31) */
  .action-card .md-li.cleared .md-litext { opacity: .32; text-decoration: line-through; }
  .action-card .md-li.cleared .md-bullet:not(.md-num) { cursor: default; }
  .action-card .md-li.cleared .md-bullet:not(.md-num)::before { opacity: .3; }
  .action-card .md-li.cleared:hover .md-bullet:not(.md-num)::before { background: transparent; }
  .task-card .task-card-row.cleared { cursor: default; }
  .task-card .task-card-row.cleared .task-card-text { text-decoration: line-through; color: var(--faint); opacity: .55; }

  /* Action-list popover — the running to-do list under the top-bar button. */
  .al-pop {
    position: fixed; z-index: 9000; width: 320px; max-height: 60vh; overflow-y: auto;
    background: var(--panel); border: 1px solid rgba(227,179,65,.34); border-radius: 3px;
    box-shadow: 0 12px 34px rgba(0,0,0,var(--sh50, .5)); padding: 8px; box-sizing: border-box;
  }
  .al-pop-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 10.5px; font-weight: 700; letter-spacing: .9px; text-transform: uppercase; color: #e3b341; padding: 4px 6px 8px; }
  .al-head-actions { display: flex; align-items: center; gap: 12px; margin-left: auto; }
  .al-check-all { cursor: pointer; color: var(--faint); font-weight: 600; text-transform: none; letter-spacing: 0; }
  .al-check-all:hover { color: var(--accent); }
  .al-clear-all:hover { color: #e5484d; }
  .al-tabs { display: flex; gap: 4px; padding: 0 4px 8px; }
  .al-tab { flex: 1; text-align: center; cursor: pointer; font-size: 11.5px; font-weight: 600; color: var(--faint); padding: 5px 6px; border: 1px solid var(--line); border-radius: 3px; user-select: none; }
  .al-tab:hover { color: var(--text); }
  .al-tab.on { color: #1a1a1a; background: #e3b341; border-color: #e3b341; }
  .al-add { display: flex; gap: 6px; align-items: flex-end; padding: 0 4px 8px; }
  .al-add-input { flex: 1; resize: none; min-height: 30px; max-height: 120px; font: inherit; font-size: 12.5px; line-height: 1.4; color: var(--text); background: var(--hover); border: 1px solid var(--line); border-radius: 3px; padding: 6px 8px; box-sizing: border-box; }
  .al-add-input:focus { outline: none; border-color: rgba(227,179,65,.6); }
  .al-add-btn { flex: 0 0 auto; cursor: pointer; font-size: 12px; font-weight: 700; color: #1a1a1a; background: #e3b341; border: none; border-radius: 3px; padding: 7px 12px; }
  .al-add-btn:hover { filter: brightness(1.06); }
  .al-empty { color: var(--faint); font-size: 12.5px; line-height: 1.5; padding: 4px 6px 8px; }
  .al-item { display: flex; align-items: flex-start; gap: 9px; padding: 7px 6px; border-radius: 3px; cursor: pointer; }
  .al-item:hover { background: var(--hover); }
  .al-check { flex: 0 0 auto; width: 15px; height: 15px; margin-top: 1px; border: 1.7px solid #e3b341; border-radius: 3px; box-sizing: border-box; }
  .al-item.done .al-check {
    background: #e3b341;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231a1305' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
    background-size: 11px 11px; background-position: center; background-repeat: no-repeat;
  }
  .al-text { font-size: 13px; line-height: 1.4; color: var(--text); }
  .al-item.done .al-text { opacity: .5; text-decoration: line-through; }
  .al-text strong { color: #edc85f; }
  .al-done-head { display: flex; align-items: center; justify-content: space-between; font-size: 10px; font-weight: 700; letter-spacing: .8px; text-transform: uppercase; color: var(--faint); padding: 10px 6px 4px; margin-top: 4px; border-top: 1px solid var(--line); }
  .al-clear { cursor: pointer; color: var(--faint); font-weight: 600; text-transform: none; letter-spacing: 0; }
  .al-clear:hover { color: var(--accent); }
  /* //task batch 2: John's own tasks pinned at the top — gold card, grouped by
     session + time, header jumps back to the source session. */
  .al-tasks { border: 1px solid rgba(227,179,65,.42); background: rgba(227,179,65,.06); border-radius: 3px; padding: 4px 4px 6px; margin: 0 2px 8px; }
  .al-tasks-head { font-size: 10px; font-weight: 700; letter-spacing: .8px; text-transform: uppercase; color: #e3b341; padding: 5px 6px 2px; }
  .al-group-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 7px 6px 2px; font-size: 10.5px; color: var(--faint); }
  .al-group-head.jump { cursor: pointer; }
  .al-group-head.jump:hover .al-group-sess { color: var(--accent); text-decoration: underline; }
  .al-group-sess { font-weight: 600; color: var(--muted); max-width: 210px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .al-group-time { flex: 0 0 auto; }
  .cmd-card {
    align-self: stretch; display: flex; align-items: center; gap: 10px;   /* vertically centered */
    background: #17181a; border: 1px solid #34363a; border-radius: 3px;
    border-left: 3px solid #6b6d72;              /* the medium-gray line */
    padding: 10px 12px; margin: 12px 0;          /* breathing room before + after */
    font-family: 'Brunea', 'Bitcount', ui-monospace, monospace;
    font-size: 12.5px; letter-spacing: .3px; color: #d7d8da;
    cursor: pointer; transition: background .12s, border-color .12s;   /* whole card copies */
  }
  .cmd-card:hover { background: #1c1d20; border-color: #3f4145; }
  .cmd-card:hover .cmd-copy { background: #2c2d31; color: #e8e9ea; }
  .cmd-card:active { background: #202124; }
  .cmd-card .cmd-body { flex: 1; min-width: 0; white-space: pre-wrap; overflow-wrap: anywhere; text-align: left; }
  /* terminal command: orange `$` prompt gutter + accent left edge, so it reads as
     "run this in a shell". align-items:flex-start keeps the $ on the first line. */
  .cmd-card.cmd-terminal { align-items: flex-start; border-left-color: var(--accent); }
  .cmd-card .cmd-prompt {
    flex: 0 0 auto; color: var(--accent); font-weight: 700; user-select: none;
    line-height: inherit; margin-top: 0;
  }
  .cmd-copy {
    flex: 0 0 auto; cursor: pointer; user-select: none;
    border: 1px solid #3a3c40; background: #222327; color: #b9babd;
    border-radius: 3px; padding: 2px 8px; font-size: 11px; line-height: 1.5;
    font-family: inherit; letter-spacing: .3px; transition: background .12s, color .12s, border-color .12s;
  }
  .cmd-copy:hover { background: #2c2d31; color: #e8e9ea; }
  .cmd-copy.copied { color: #45e3b0; border-color: #2a5a4c; background: #10261f; }
  /* ---- raw data card: JSON/API payloads, collapsed by default (never shown unasked) ---- */
  .raw-data-card {
    align-self: stretch; background: #17181a; border: 1px solid #34363a; border-radius: 3px;
    border-left: 3px solid #6b6d72; margin: 12px 0; overflow: hidden;
  }
  .raw-data-row {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 10px 12px; cursor: pointer; user-select: none;
    font-family: 'Brunea', 'Bitcount', ui-monospace, monospace; font-size: 12.5px; letter-spacing: .3px;
  }
  .raw-data-label { color: #8a8c90; }
  .raw-data-toggle {
    flex: 0 0 auto; border: 1px solid #3a3c40; background: #222327; color: #b9babd;
    border-radius: 3px; padding: 2px 8px; font-size: 11px; line-height: 1.5;
  }
  .raw-data-row:hover .raw-data-toggle { background: #2c2d31; color: #e8e9ea; }
  .raw-data-body {
    padding: 0 12px 12px; margin: 0; white-space: pre-wrap; overflow-wrap: anywhere;
    font-family: 'Brunea', 'Bitcount', ui-monospace, monospace; font-size: 12px; color: #d7d8da;
  }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .raw-data-card { background: var(--panel); border-color: var(--line); border-left-color: #c2c2c2; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .raw-data-label { color: #7a7a7a; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .raw-data-toggle { background: var(--panel); border-color: var(--line); color: #545454; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .raw-data-row:hover .raw-data-toggle { background: var(--hover); color: #2a2a2a; }
  /* ---- question block: Claude asks the user a question that blocks progress ---- */
  /* ===== QUESTION CARD — same clean panel as the note card (John, 2026-08-16) ====
     Square panel, header strip (breadcrumb + chip), divider, then the question and its
     buttons. A question is ALWAYS Luminair asking John, so it wears Master Control
     GOLD, never the blue that means a note John wrote himself. Body text stays plain. */
  .ask-card {
    align-self: stretch; flex: 0 0 auto; margin: 20px 0;
    background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px;
    padding: 0;
    --ac: var(--bo-lt);
  }
  /* Same wrap rule as .nc-head — see the note there. */
  .ask-head {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 4px 12px;
    padding: 11px 16px; border-bottom: 1px solid var(--line);
  }
  .ask-crumb {
    flex: 1 1 auto; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .ask-from { color: var(--ac); font-size: 12.5px; font-weight: 600; letter-spacing: .2px; }
  .ask-sep { color: var(--faint); font-size: 12.5px; margin: 0 7px; }
  .ask-kind { color: var(--muted); font-size: 12.5px; }
  .ask-chip {
    flex: 0 0 auto; margin-left: auto; font-size: 9px; font-weight: 700; letter-spacing: 1.4px;
    padding: 3px 7px; border-radius: 3px;
    color: var(--ac); background: color-mix(in srgb, var(--ac) 14%, transparent);
  }
  .ask-body { padding: 13px 16px 15px; }
  /* the question itself — plain text, never tinted */
  .ask-q { color: var(--text); font-size: 13.5px; line-height: 1.5; overflow-wrap: anywhere; }
  .ask-q code { background: rgba(255,255,255,.07); color: var(--text); padding: 1px 5px; border-radius: 3px; font-size: 12px; }
  .ask-q strong { color: var(--text); }
  .ask-actions { display: flex; gap: 8px; margin-top: 13px; flex-wrap: wrap; }
  .ask-btn {
    flex: 0 1 auto; min-width: 0; white-space: nowrap;   /* wrap the ROW, never a label */
    cursor: pointer; border-radius: 3px; padding: 6px 14px;
    font-family: inherit; font-size: 12.5px; letter-spacing: .2px;
    border: 1px solid var(--line); background: transparent; color: var(--muted);
    transition: background .12s, border-color .12s, color .12s;
  }
  .ask-btn:hover { background: rgba(255,255,255,.05); border-color: var(--ac); color: var(--text); }
  .ask-yes { background: var(--ac); border-color: var(--ac); color: #14100a; font-weight: 700; }
  .ask-yes:hover { filter: brightness(1.1); }
  .ask-no { background: transparent; border-color: var(--line); color: var(--muted); }
  .ask-no:hover { background: rgba(255,255,255,.05); color: var(--text); }
  .ask-reply { margin-left: auto; }
  /* Answered state: the chosen button reads as the recorded answer (filled + check), the
     other stays a quiet "change to…" affordance, and a status line says what you said. */
  .ask-card.answered .ask-btn.chosen { cursor: default; background: var(--ac); border-color: var(--ac); color: #14100a; font-weight: 700; }
  .ask-card.answered .ask-btn.chosen::before { content: '✓ '; }
  .ask-card.answered .ask-btn.chosen:hover { filter: none; }
  .ask-card.answered .ask-yes:not(.chosen) { background: transparent; border-color: var(--line); color: var(--muted); font-weight: 500; }
  .ask-card.answered .ask-yes:not(.chosen):hover { background: rgba(255,255,255,.05); border-color: var(--ac); color: var(--text); }
  .ask-card.answered .ask-chip { background: var(--ac); color: #14100a; }
  .ask-answered { margin-top: 9px; font-size: 11.5px; color: var(--ac); font-weight: 600; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .ask-card.answered .ask-btn.chosen { color: #fff; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .ask-card.answered .ask-yes:not(.chosen) { background: var(--panel); border-color: var(--line); color: #545454; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .ask-card.answered .ask-chip { color: #fff; }
  /* the composer chip that shows you're answering a specific question block */
  /* Message id + reply affordance (John, 2026-08-16). Quiet by default — it only
     appears on hover, so the transcript reads exactly as before until you reach for it. */
  .msg { position: relative; }
  /* Hover furniture sits BELOW the message, not over its last line (John, 2026-08-31:
     "these icons come on top of the text, they should come below it"). Anchored to the
     bubble's bottom edge and pushed just past it into the inter-message gap. */
  .msg-tools {
    position: absolute; top: 100%; right: 4px; margin-top: 0;
    /* The old 3px margin gap sat OUTSIDE this element: moving the cursor toward the
       buttons crossed unhovered space, ended .msg:hover, and the buttons vanished
       before you could click (John, 2026-09-02). Replace the gap with padding that
       belongs to .msg-tools, so the hover surface is continuous from the bubble to
       the buttons, and keep them up while the cursor is on the tools themselves. */
    padding-top: 5px;
    display: flex; align-items: center; gap: 5px;
    opacity: 0; transition: opacity .12s ease;
    pointer-events: none; z-index: 2;
  }
  .msg:hover .msg-tools, .msg-tools:hover { opacity: 1; pointer-events: auto; }
  .msg-id {
    font-size: 9.5px; font-weight: 700; letter-spacing: .5px;
    color: var(--faint); font-variant-numeric: tabular-nums; user-select: none;
  }
  .msg-reply {
    width: 18px; height: 18px; padding: 0; line-height: 1;
    border: 1px solid var(--line); border-radius: 3px; background: var(--panel);
    color: var(--muted); font-size: 12px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
  }
  .msg-reply:hover { color: var(--accent); border-color: var(--accent); }
  .msg-pin {
    width: 18px; height: 18px; padding: 0; line-height: 1;
    border: 1px solid var(--line); border-radius: 3px; background: var(--panel);
    color: var(--muted); font-size: 10px; cursor: pointer; opacity: .75;
    display: flex; align-items: center; justify-content: center;
  }
  .msg-pin:hover { opacity: 1; border-color: var(--accent); }
  .msg-pin.pinning { opacity: .4; cursor: default; }
  .msg-pin.pinned { opacity: 1; border-color: #ffb454; background: rgba(255,180,84,.14); }
  .reply-chip {
    display: none; align-items: center; gap: 8px;
    margin: 0 0 7px 0; padding: 6px 10px;
    background: #0f0f10; border: 1px solid var(--line); border-left: 2px solid var(--bo-lt);
    border-radius: 3px; font-size: 12px; color: var(--muted);
  }
  .reply-chip.show { display: flex; }
  .reply-chip .rc-icon { color: var(--bo-lt); font-weight: 700; flex: 0 0 auto; }
  .reply-chip .rc-q { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #cdd8ee; }
  .reply-chip .rc-x { flex: 0 0 auto; cursor: pointer; color: #7a86a0; padding: 0 2px; user-select: none; }
  .reply-chip .rc-x:hover { color: #eaf0fb; }
  /* inline links: on-brand neutral text, orange on hover, with a tiny copy glyph */
  .a-link { color: #d7d8da; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; overflow-wrap: anywhere; }
  .a-link:hover { color: var(--accent); }
  .a-copy { margin-left: 3px; cursor: pointer; color: #6b6d72; font-size: 11px; user-select: none; vertical-align: baseline; }
  .a-copy:hover { color: #cfd0d2; }
  /* old-school blinking block cursor shown while a pane is thinking */
  .term-cursor {
    display: inline-block;
    width: .52em; height: 1.02em;
    /* CRT block: our color, with fine horizontal scanlines cut through it + a soft bloom */
    background:
      repeating-linear-gradient(to bottom, transparent 0 2px, rgba(0,0,0,.30) 2px 3px),
      var(--accent);
    box-shadow: none;
    vertical-align: -.16em;
    margin-left: 2px;
    animation: term-blink 1.06s steps(1, end) infinite;
  }
  /* same personality as the logo: every few seconds the block glitches for a
     blink — a jump, a skew, a slice — then goes back to steady blinking */
  @media (prefers-reduced-motion: no-preference) {
    .term-cursor { animation: term-blink 1.06s steps(1, end) infinite, cursorGlitch 5.7s steps(1, end) infinite; }
  }
  /* thinking indicator: five little squares, the glow sweeping back and forth */
  /* scanner + time/tokens share one row: animation left, meta right after it */
  /* Bottom margin gives the thinking readout its OWN clearance so it always scrolls
     slightly ABOVE the bottom fade band (12px mask above the composer) instead of
     dissolving into it — John, 2026-07-25. This lift rides on the readout itself, so
     it holds whether or not the pane's running-state padding is in play. */
  .think-row { align-self: flex-start; display: flex; align-items: center; gap: 7.65px; margin: 4px 4px 26px 4px; }
  .term-cursor.standalone {
    margin: 0;
    width: auto; height: auto; border-radius: 3px;
    background: none; box-shadow: none;
    display: inline-flex; align-items: center; gap: 1.53px;
    vertical-align: baseline; animation: none;
  }
  .term-cursor.standalone .sq {
    /* the scanner takes the ACTIVE MODEL's color (falls back to the accent).
       Geometry + timing tuned in the KITT Lab (John, 2026-07-27): flat 13×5
       rectangles like the real car's front bar. --scan stays var(--accent) here
       (NOT the Lab's hardcoded #ff6a44) so per-model coloring survives; the JS
       sets --scan per model inline (renderer.js), and #ff6a44 IS the accent
       default, so the default look is identical. */
    --scan: var(--accent);
    /* Size is CONSTANT (no transform:scale) — off squares are the SAME size as lit
       ones; only the glow/opacity sweeps (John, 2026-07-28). Width trimmed 13→11 so
       the row is a touch shorter. */
    width: 8.42px; height: 3.83px; border-radius: 3px;
    background: var(--scan);
    /* No glow (John, 2026-08-24: "kitt remove the glow"). The bar used a double halo
       (0 0 1.91px + 0 0 3.06px var(--scan)); the sweep is carried entirely by opacity,
       so dropping it keeps the animation identical, just flat. */
    box-shadow: none;
    opacity: 0.06;
  }
  /* K.I.T.T. / K2000 scanner: a single bright head sweeps 1→5→1 dragging a
     comet tail behind it. Each square snaps ON the instant the head arrives,
     then fades out over the next ~2 slots (the trail), while the squares AHEAD
     of the head stay dark until it reaches them — so the glow always leans
     opposite the direction of travel, exactly like the car's front bar.
     Sinusoidal (cosine) arrival times, 1.1s bounce: sq1 @0/100%, sq2 @16.7/83.3,
     sq3 @25/75, sq4 @33.3/66.7, sq5 @50%. The uneven spacing (wide at the ends,
     tight in the middle) is what makes the head slow at each end like real KITT. */
  /* Apply the sweep UNCONDITIONALLY — NOT gated behind
     `prefers-reduced-motion: no-preference` (John, 2026-07-25). macOS System
     Settings > Accessibility > Display > Reduce Motion forces `reduce` here,
     which was silently stripping the whole KITT sweep and freezing it to a
     single dim square — the desktop half of the "no animation" bug already
     fixed on mobile (mobile/src/styles.css, "matching what desktop shows" —
     except desktop never actually matched). This scanner is a functional
     run-in-progress indicator, not decorative, so it always plays, on both
     platforms alike. */
  /* Sweep speed tracks the running model's weight: a light/cheap model scans FAST,
     a heavy/costly one scans SLOW. renderer sets --kitt-dur per model (John, 2026-08-15). */
  .term-cursor.standalone .sq { animation: var(--kitt-dur, 1.35s) linear infinite; }
  .term-cursor.standalone .sq:nth-child(1) { animation-name: kitt1; }
  .term-cursor.standalone .sq:nth-child(2) { animation-name: kitt2; }
  .term-cursor.standalone .sq:nth-child(3) { animation-name: kitt3; }
  .term-cursor.standalone .sq:nth-child(4) { animation-name: kitt4; }
  .term-cursor.standalone .sq:nth-child(5) { animation-name: kitt5; }
  /* Comet-tail sweep tuned in the KITT Lab (John, 2026-07-27): the head snaps ON
     the instant it arrives, then decays over the following slots as a trailing
     tail — leaning opposite the direction of travel, like the car's front bar.
     These are John's EXACT exported keyframes; edit only via the Lab so the app,
     the mobile app and the Lab stay in lockstep. */
  @keyframes kitt1 { 0% { opacity:0.06; } 22% { opacity:0.06; } 24% { opacity:1; } 26% { opacity:0.932; } 28% { opacity:0.802; } 30% { opacity:0.677; } 32% { opacity:0.559; } 34% { opacity:0.449; } 36% { opacity:0.35; } 38% { opacity:0.263; } 40% { opacity:0.191; } 42% { opacity:0.133; } 44% { opacity:0.092; } 46% { opacity:0.067; } 48% { opacity:0.06; } 68% { opacity:0.06; } 70% { opacity:1; } 72% { opacity:0.912; } 74% { opacity:0.78; } 76% { opacity:0.65; } 78% { opacity:0.526; } 80% { opacity:0.408; } 82% { opacity:0.299; } 84% { opacity:0.201; } 86% { opacity:0.115; } 88% { opacity:0.06; } 100% { opacity:0.06; } }
  @keyframes kitt2 { 0% { opacity:0.06; } 26% { opacity:0.06; } 28% { opacity:1; } 30% { opacity:0.912; } 32% { opacity:0.794; } 34% { opacity:0.684; } 36% { opacity:0.585; } 38% { opacity:0.498; } 40% { opacity:0.426; } 42% { opacity:0.368; } 44% { opacity:0.327; } 46% { opacity:0.302; } 48% { opacity:0.06; } 64% { opacity:0.06; } 66% { opacity:1; } 68% { opacity:0.94; } 70% { opacity:0.81; } 72% { opacity:0.677; } 74% { opacity:0.545; } 76% { opacity:0.415; } 78% { opacity:0.291; } 80% { opacity:0.173; } 82% { opacity:0.064; } 84% { opacity:0.06; } 100% { opacity:0.06; } }
  @keyframes kitt3 { 0% { opacity:0.06; } 30% { opacity:0.06; } 32% { opacity:1; } 34% { opacity:0.919; } 36% { opacity:0.82; } 38% { opacity:0.733; } 40% { opacity:0.661; } 42% { opacity:0.603; } 44% { opacity:0.562; } 46% { opacity:0.537; } 48% { opacity:0.06; } 60% { opacity:0.06; } 62% { opacity:1; } 64% { opacity:0.951; } 66% { opacity:0.831; } 68% { opacity:0.705; } 70% { opacity:0.575; } 72% { opacity:0.442; } 74% { opacity:0.31; } 76% { opacity:0.18; } 78% { opacity:0.06; } 100% { opacity:0.06; } }
  @keyframes kitt4 { 0% { opacity:0.06; } 34% { opacity:0.06; } 36% { opacity:1; } 38% { opacity:0.968; } 40% { opacity:0.896; } 42% { opacity:0.838; } 44% { opacity:0.797; } 46% { opacity:0.772; } 48% { opacity:0.06; } 54% { opacity:0.06; } 56% { opacity:1; } 58% { opacity:1; } 60% { opacity:0.929; } 62% { opacity:0.828; } 64% { opacity:0.716; } 66% { opacity:0.596; } 68% { opacity:0.47; } 70% { opacity:0.34; } 72% { opacity:0.207; } 74% { opacity:0.075; } 76% { opacity:0.06; } 100% { opacity:0.06; } }
  @keyframes kitt5 { 0% { opacity:0.06; } 40% { opacity:0.06; } 42% { opacity:1; } 48% { opacity:1; } 50% { opacity:0.99; } 52% { opacity:0.962; } 54% { opacity:0.918; } 56% { opacity:0.858; } 58% { opacity:0.783; } 60% { opacity:0.694; } 62% { opacity:0.593; } 64% { opacity:0.481; } 66% { opacity:0.361; } 68% { opacity:0.235; } 70% { opacity:0.105; } 72% { opacity:0.06; } 100% { opacity:0.06; } }
  @keyframes term-blink { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }
  @keyframes cursorGlitch {
    0%, 55%, 100% { transform: none; clip-path: none; }
    56% { transform: translate(1px, -1px) skewX(-8deg); }
    57.5% { transform: translate(-1px, 0) skewX(5deg); clip-path: inset(30% 0 40% 0); }
    59% { transform: none; clip-path: none; }
    86% { transform: none; }
    87% { transform: translateX(-1px); clip-path: inset(55% 0 10% 0); }
    88.5% { transform: none; clip-path: none; }
  }
  /* live "12s · 1.4k tokens" line under the thinking cursor */
  .think-meta {
    color: var(--faint); font-size: 9.35px; letter-spacing: .25px;
    font-variant-numeric: tabular-nums;
    margin: 0; user-select: none; white-space: nowrap;
  }
  /* ---- Bottom status bar REMOVED COMPLETELY (John, 2026-07-25) -------------
     The queued state is already carried by the inline thinking cursor + the
     "N queued" chip; the standalone bar above the composer was redundant, so it
     (and its .locked/.lock-scan/lockQueued styles) is deleted entirely. */
  .msg.user.queued { opacity: .5; border-style: dashed; display: flex; gap: 8px; align-items: flex-start; }
  .msg.user.queued > span:first-child { flex: 1; min-width: 0; white-space: pre-wrap; word-wrap: break-word; }
  .queued-x { flex: 0 0 auto; cursor: pointer; color: var(--faint); font-weight: 700; line-height: 1.4; }
  .queued-x:hover { color: var(--accent); }
  .tool {
    align-self: flex-start; background: var(--tool); border: 1px solid var(--tool-line);
    border-radius: 3px; padding: 7px 11px; font-family: "SF Mono", ui-monospace, monospace;
    font-size: 12px; color: #cfcfcf; max-width: min(760px, 100%); overflow-wrap: anywhere;
    /* a tool firing should feel like it POWERS ON, not like a static label appears:
       the chip charges up (border+glow snap to accent, then settle) while an
       energizing light sweep runs across it once. No icon — the motion IS the cue. */
    /* Contain the sweep band with clip-path, NOT overflow:hidden. overflow:hidden makes the
       chip its own clip layer, which (a) held stale tiles → chips drawn as cropped slivers
       near the scroll boundary, and (b) can shave a line of the command itself. clip-path
       clips the ::before sweep to the rounded box while the text — which only ever wraps,
       never overflows — can never be cut. (John, 2026-08-28: "bash cropped, never again".) */
    position: relative; clip-path: inset(0 round 3px);
    animation: tool-activate 620ms cubic-bezier(.2,.8,.2,1) both;
  }
  .tool::before {   /* the energizing sweep — a single band of accent light crossing the chip */
    content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
    background: linear-gradient(100deg, transparent 18%, rgba(var(--accent-rgb),.38) 50%, transparent 82%);
    transform: translateX(-120%);
    animation: tool-sweep 620ms ease-out 40ms both;
  }
  .tool b { color: var(--accent); font-weight: 600; animation: tool-charge 620ms ease-out both; }
  .tool.repulse { animation: tool-repulse 420ms ease-out both; }   /* same action fired again: quick re-glow, no full re-power */
  /* Replayed history chips: NO entrance animation/sweep — they must paint final instantly,
     so a repaint near the scroll boundary can never catch one mid-flight as a sliver. */
  .tool.no-anim, .tool.no-anim::before { animation: none; }
  .tool.no-anim { opacity: 1; transform: none; }
  body.hide-tools .tool { display: none; }   /* Settings → Chat → Show tool calls off */
  .tool.note b { color: var(--faint); }   /* engine/background-task notes: quieter than real tool calls */
  .tool.note { color: var(--faint); }
  /* notes reuse the .tool chip but must stay quiet — no power-on/sweep/charge on them */
  .tool.note, .tool.note::before, .tool.note b { animation: none; }
  /* Branch-out self-check catch — gold-branded so a self-corrected mistake STANDS OUT
     (not a quiet grey note), and never hidden by "hide tool calls": a safety catch
     must always be visible. */
  .tool.note.bo-lesson {
    color: var(--bo-txt);
    background: linear-gradient(180deg, rgba(var(--bo-rgb), .15), rgba(var(--bo-rgb), .06));
    border-color: rgba(var(--bo-rgb), .5);
    box-shadow: inset 0 0 0 1px rgba(var(--bo-rgb), .08);
  }
  .tool.note.bo-lesson b { color: var(--bo-lt); }
  /* Light theme: the near-white gold text washes out on a pale fill — swap to deep gold
     for readable contrast, and lean the fill/border a touch stronger. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .tool.note.bo-lesson {
    color: var(--bo-deep);
    background: linear-gradient(180deg, rgba(var(--bo-rgb), .22), rgba(var(--bo-rgb), .10));
    border-color: rgba(var(--bo-rgb), .6);
    box-shadow: inset 0 0 0 1px rgba(var(--bo-rgb), .12);
  }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .tool.note.bo-lesson b { color: var(--bo-deep); }
  body.hide-tools .tool.note.bo-lesson { display: block; }
  .tool .tool-x { color: var(--faint); font-weight: 600; }
  @keyframes tool-activate {
    0%   { opacity: 0; transform: translateY(4px) scale(.985);
           border-color: rgba(var(--accent-rgb),.95); box-shadow: 0 0 0 0 rgba(var(--accent-rgb),0); }
    38%  { border-color: rgba(var(--accent-rgb),.8); box-shadow: none; }
    100% { opacity: 1; transform: none;
           border-color: var(--tool-line); box-shadow: 0 0 0 0 rgba(var(--accent-rgb),0); }
  }
  @keyframes tool-sweep {
    0%   { transform: translateX(-120%); opacity: 0; }
    18%  { opacity: 1; }
    100% { transform: translateX(120%); opacity: 0; }
  }
  @keyframes tool-charge {   /* the tool name flares bright, then cools to its normal accent */
    0%   { text-shadow: none; filter: brightness(1.75); letter-spacing: .4px; }
    100% { text-shadow: none; filter: none; letter-spacing: 0; }
  }
  @keyframes tool-repulse {
    0%   { box-shadow: none; border-color: rgba(var(--accent-rgb),.7); }
    100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb),0); border-color: var(--tool-line); }
  }
  @media (prefers-reduced-motion: reduce) {
    .tool, .tool::before, .tool b, .tool.repulse { animation: none; }
  }
  /* NEW CARD LANGUAGE (John, 2026-08-18: "OLD design update the card"). Was a filled
     accent-soft box with a full 1px border — the old style being retired everywhere.
     Now the recap/action card shape: transparent, a single left rail, text aligned to
     the same column as a normal reply. Kept RED, not accent, because an error is a
     semantic state, not themed chrome. */
  .err {
    align-self: stretch;
    background: transparent;
    border: none; border-left: 2px solid rgba(224, 85, 74, .5);
    border-radius: 3px;
    color: #e0857a;
    padding: 12px 18px 12px 18px; margin: 12px 0;
    max-width: min(760px, 100%); overflow-wrap: anywhere; line-height: 1.5;
  }
  .notice { align-self: flex-start; background: #0f0f10; border: 1px solid var(--line); color: #9aa0a8; border-radius: 3px; padding: 7px 12px; font-size: 12.5px; max-width: min(760px, 100%); overflow-wrap: anywhere; }
  /* Shared-access-revoked card: one calm card, shown once (John, 2026-09-04). */
  .shared-revoked-card { align-self: stretch; display: flex; align-items: flex-start; gap: 13px; background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 15px 16px; margin: 12px 0; max-width: min(760px, 100%); }
  .shared-revoked-card .src-ic { flex: none; width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center; color: #e0a44a; background: rgba(224,164,74,.12); border: 1px solid rgba(224,164,74,.28); }
  .shared-revoked-card .src-txt { flex: 1; min-width: 0; }
  .shared-revoked-card .src-t { font-size: 13.5px; font-weight: 700; color: var(--text); margin-bottom: 3px; }
  .shared-revoked-card .src-d { font-size: 12.5px; color: var(--muted); line-height: 1.5; }
  .shared-revoked-card .src-x { flex: none; align-self: center; }
  /* Connector notices carry a real SVG icon (not a generic emoji) — align it with the label. */
  .notice.ntc-ico { display: inline-flex; align-items: center; gap: 7px; }
  .notice .ntc-ic { flex: 0 0 auto; opacity: .85; }
  .notice .ntc-tx { min-width: 0; }
  /* Master Control notification — a calm notice wearing MC's gold (--bo-*) so it reads
     as an action the controller took for you (e.g. auto-switching accounts). (John, 2026-07-28) */
  /* OPAQUE, not 8% alpha (John, 2026-08-16 — screenshot of a Master Control confirm with
     the previous reply legible straight through it). A card that asks a question has to be
     a solid surface: at .08 alpha it tinted whatever sat behind it instead of covering it,
     so any overlap in the transcript rendered as two texts stacked on top of each other.
     color-mix keeps the exact same gold tint, just composited onto the pane instead of onto
     whatever happens to be underneath. */
  /* MASTER CONTROL / receipt / task cards now wear the SAME clean panel style as .note-card
     (John, 2026-08-31 "update them all") — neutral dark panel + hairline border + square
     edges, accent for the eyebrow/dot instead of the old gold --bo shell. */
  .notice.mc-notice {
    background: #0f0f10; border: 1px solid var(--line);
    color: var(--text); padding: 9px 13px 10px; box-shadow: none;
    /* .ask-yes fills with var(--ac), which is only defined on .ask-card — without it
       here the Yes button had no background and was invisible (John, 2026-09-01).
       Give the MC card its own accent (the MC purple) so Yes reads as the primary. */
    --ac: #7c4ff5;
  }
  .mc-notice .mc-ntc-head { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
  .mc-notice .mc-ntc-dot {
    flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
    box-shadow: none; animation: micpulse 1.6s ease-in-out infinite;
  }
  .mc-notice .mc-ntc-eyebrow { font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--accent); }
  .mc-notice .mc-ntc-close {
    margin-left: auto; flex: 0 0 auto; width: 18px; height: 18px; padding: 0;
    background: transparent; border: 0; border-radius: 3px;
    color: var(--faint); font-size: 14px; line-height: 1; cursor: pointer;
    opacity: 0.45; transition: opacity .12s ease, color .12s ease, background .12s ease;
  }
  .mc-notice:hover .mc-ntc-close { opacity: 0.85; }
  .mc-notice .mc-ntc-close:hover { color: #e5484d; background: rgba(229,72,77,.12); opacity: 1; }
  .tool.note { display: flex; align-items: center; gap: 6px; }
  .tool.note .note-tx { flex: 1 1 auto; min-width: 0; }
  .tool.note .note-close {
    margin-left: auto; background: transparent; border: 0; border-radius: 3px;
    color: var(--faint); font-size: 13px; line-height: 1; cursor: pointer;
    opacity: 0; transition: opacity .12s ease; padding: 0 4px;
  }
  .tool.note:hover .note-close { opacity: 0.6; }
  .tool.note .note-close:hover { opacity: 1; color: #e5484d; }
  .mc-notice .mc-ntc-body { min-width: 0; font-size: 12.5px; line-height: 1.42; color: var(--text); overflow-wrap: anywhere; }
  .mc-notice .mc-ntc-actions { display: flex; gap: 8px; margin-top: 10px; }
  .mc-notice .ask-yes { color: #fff; font-weight: 700; }   /* white ink reads on the purple fill */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .notice.mc-notice { background: var(--panel); border-color: var(--line); }
  /* The inline //task card (John, 2026-07-30). Reuses .mc-notice's gold shell so every
     yellow surface in the app reads as one family; adds only the tickable rows. */
  .task-card .task-card-list { display: flex; flex-direction: column; gap: 4px; margin-top: 2px; }
  .task-card .task-card-row { display: flex; align-items: flex-start; gap: 8px; cursor: pointer; padding: 2px 0; min-width: 0; }
  .task-card .task-card-check {
    flex: 0 0 auto; width: 13px; height: 13px; margin-top: 2px; border-radius: 3px;
    border: 1.5px solid rgba(var(--bo-rgb), .75); background: transparent;
    position: relative; transition: background .12s ease, border-color .12s ease;
  }
  .task-card .task-card-row:hover .task-card-check { border-color: var(--bo-lt); }
  /* min-width:0 + wrap so a long task can't push the card past the pane edge. */
  .task-card .task-card-text { flex: 1 1 auto; min-width: 0; font-size: 12.5px; line-height: 1.42; color: var(--text); overflow-wrap: anywhere; }
  .task-card .task-card-row.done .task-card-check { background: var(--bo-lt); border-color: var(--bo-lt); }
  .task-card .task-card-row.done .task-card-check::after {
    content: ''; position: absolute; left: 3.5px; top: .5px; width: 3px; height: 7px;
    border: solid #201800; border-width: 0 1.8px 1.8px 0; transform: rotate(42deg);
  }
  .task-card .task-card-row.done .task-card-text { text-decoration: line-through; color: var(--faint); }
  /* left-aligned at the same spot the running scanner/meta sat, so it doesn't jump to center */
  .done { align-self: flex-start; text-align: left; color: var(--muted); font-size: 11.5px; padding: 8px 4px 6px 4px; }
  /* honest fallback when a session body never finished loading — a plain, tappable retry
     card (never a console step). Watchdog-driven; see armLoadWatchdog in renderer.js. */
  .load-retry { display: flex; flex-direction: column; align-items: flex-start; gap: 9px; padding: 14px 4px; }
  .load-retry .lr-msg { color: var(--muted); font-size: 12.5px; }
  .load-retry .lr-btn {
    -webkit-app-region: no-drag; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600;
    padding: 5px 13px; border-radius: 3px; color: var(--accent);
    background: rgba(var(--accent-rgb), .14); border: 1px solid rgba(var(--accent-rgb), .4);
  }
  .load-retry .lr-btn:hover { background: rgba(var(--accent-rgb), .22); }
  /* one-tap "Continue →" button on a finished turn — fires the literal Continue prompt.
     Tinted to the turn's MODEL colour (--rc/--rc-rgb, set via tintToModel() in addDone) —
     Sonnet blue, Fable purple, Opus orange — so the button reads as "resume THIS model",
     not a generic accent chip. Falls back to the theme accent if untinted. */
  .done-continue {
    display: inline-flex; align-items: center; gap: 4px; vertical-align: middle;
    margin-left: 10px; padding: 2px 8px 2px 10px; border-radius: 3px;
    font: inherit; font-size: 11px; font-weight: 600; line-height: 1.6; cursor: pointer;
    color: var(--rc, var(--accent)); background: rgba(var(--rc-rgb, var(--accent-rgb)), .14);
    border: 1px solid rgba(var(--rc-rgb, var(--accent-rgb)), .38); -webkit-app-region: no-drag;
  }
  .done-continue:hover { background: rgba(var(--rc-rgb, var(--accent-rgb)), .2); }
  .done-continue svg { display: block; }
  .pane.running .done-continue { display: none; }   /* hide while a reply is streaming */
  .empty { margin: auto; text-align: center; color: var(--muted); max-width: 400px; line-height: 1.6; }
  .empty h2 { color: var(--text); font-size: 17px; margin-bottom: 8px; font-weight: 600; }

  /* ---- First-run onboarding (zero accounts): same empty layout, bottom row is the setup path ---- */
  .empty.ftu-empty { max-width: 760px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 40px; }
  .empty.ftu-empty h2 span::before { content: 'Welcome to Luminair'; }
  .ftu-actions { display: grid; grid-template-columns: repeat(3, minmax(0,190px)); gap: 34px; text-align: left; }
  .ftu-act { display: block; text-align: left; border: 0; background: transparent; padding: 0; cursor: pointer; }
  .ftu-act small { display: block; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--faint); margin-bottom: 8px; }
  .ftu-act span { font-size: 14px; color: var(--muted); transition: color .12s; }
  .ftu-act:hover span, .ftu-act.done span { color: var(--text); }
  .ftu-act.done small { color: var(--accent); }

  /* ── Organize experience (first-run, after import) ── */
  .org-overlay { position: fixed; inset: 0; z-index: 9985; display: flex; align-items: center; justify-content: center; padding: 32px; background: color-mix(in srgb, var(--bg) 82%, #000); backdrop-filter: blur(6px); animation: orgFade .18s ease; }
  @keyframes orgFade { from { opacity: 0; } to { opacity: 1; } }
  .org-card { width: 100%; max-width: 760px; background: var(--panel); border: 1px solid var(--line); border-radius: 18px; padding: 30px 30px 24px; box-shadow: 0 24px 80px rgba(0,0,0,var(--sh55, .55)); }
  .org-head { text-align: center; margin-bottom: 22px; }
  .org-title { color: var(--text); font-size: 24px; font-weight: 700; letter-spacing: -.01em; margin: 6px 0 8px; }
  .org-sub { color: var(--muted); font-size: 13.5px; line-height: 1.5; max-width: 520px; margin: 0 auto; }
  .org-teach { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
  @media (max-width: 640px) { .org-teach { grid-template-columns: 1fr; } }
  .org-tile { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; padding: 18px 16px; border: 1px solid var(--line); border-radius: 14px; background: color-mix(in srgb, var(--panel-2) 60%, transparent); }
  .org-tile-ic { width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center; font-size: 17px; color: var(--accent); background: rgba(var(--accent-rgb), .10); border: 1px solid rgba(var(--accent-rgb), .35); margin-bottom: 4px; }
  .org-tile-name { color: var(--text); font-size: 14px; font-weight: 600; }
  .org-tile-desc { color: var(--muted); font-size: 12px; line-height: 1.45; flex: 1 1 auto; }
  .org-tile-btn { margin-top: 10px; width: 100%; border: none; border-radius: 8px; padding: 8px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer; background: var(--accent); color: #fff; }
  .org-tile-btn:hover { filter: brightness(1.08); }
  .org-tile-btn.ghost { background: transparent; color: var(--text); border: 1px solid var(--line); }
  .org-tile-btn:disabled { opacity: .5; cursor: not-allowed; filter: none; }
  .org-actions { display: flex; justify-content: flex-end; align-items: center; gap: 12px; margin-top: 24px; }
  .org-skip { background: none; border: none; color: var(--muted); font-size: 13px; cursor: pointer; padding: 8px 4px; }
  .org-skip:hover { color: var(--text); }
  .org-done { border: none; border-radius: 9px; padding: 10px 20px; font-size: 13.5px; font-weight: 700; cursor: pointer; background: var(--accent); color: #fff; }
  .org-done:hover { filter: brightness(1.08); }
  /* momentary pulse on the sidebar when "Show me" teaches the drag gesture */
  aside.org-drag-hint { animation: orgDragHint 1.3s ease 2; }
  @keyframes orgDragHint { 0%, 100% { box-shadow: inset 0 0 0 0 transparent; } 50% { box-shadow: inset -3px 0 0 0 var(--accent); } }
  /* re-entry for users who chose "Not now" — sits under the (empty) Unsorted block */
  .unsorted-import { display: block; width: calc(100% - 16px); margin: 6px 8px 10px; padding: 8px 10px; border: 1px dashed var(--line); border-radius: 8px; background: transparent; color: var(--muted); font-size: 12px; text-align: left; cursor: pointer; }
  .unsorted-import:hover { border-color: rgba(var(--accent-rgb), .5); color: var(--text); background: rgba(var(--accent-rgb), .06); }

  footer { flex: 0 0 auto; border-top: 1px solid var(--line); background: var(--panel); padding: 12px 16px 16px; }
  .ts-tip { position: fixed; z-index: 9999; pointer-events: none; background: var(--panel-2); color: var(--muted); border: 1px solid var(--line); border-radius: 3px; padding: 2px 7px; font-size: 11px; line-height: 1.4; white-space: nowrap; box-shadow: 0 4px 14px rgba(0,0,0,var(--sh40, .4)); opacity: 0; transition: opacity .1s ease; }
  /* brief top-center notification (e.g. "Session will move when idle") */
  .ow-toast { position: fixed; top: 12px; left: 50%; transform: translate(-50%, -10px); z-index: 10000; pointer-events: none; background: var(--panel-2); color: var(--text); border: 1px solid var(--accent); border-radius: 3px; padding: 8px 15px; font-size: 12.5px; max-width: 80vw; box-shadow: 0 10px 34px rgba(0,0,0,var(--sh55, .55)); opacity: 0; transition: opacity .18s ease, transform .18s ease; }
  .ow-toast.show { opacity: 1; transform: translate(-50%, 0); }

  /* sidebar bottom-left update notice: quiet grey while it downloads, gold call-to-action when ready.
     Flex-row discipline (Part 2): icon is flex:0 0 auto, text is flex 1 / min-width:0 + ellipsis, so a
     long version string truncates and never runs past the 258px sidebar edge. */
  .sb-update { display: flex; align-items: center; gap: 8px; align-self: stretch; width: auto; margin: auto 8px 6px; padding: 8px 14px;
    border-radius: 3px; border: 1px solid var(--accent); background: var(--accent-soft);
    color: var(--text); cursor: pointer; text-align: left; font: inherit;
    transition: filter .15s ease, background .15s ease; }
  .sb-update:hover { filter: brightness(1.14); }
  /* Dev staged-build card. It must never read as the public update, but purple is not a
     Luminair colour — the palette is accent orange, gold for Branch Out, blue for Fathom,
     and purple belongs to the Journal. So the separation is carried by weight instead of
     hue: the public card wears the accent fill and border, this one is a neutral outline
     with no fill, and the copy ("Staged build ready") says the rest. (John, 2026-09-23.) */
  .sb-staged { background: transparent; border-color: var(--line); }
  /* Staged card NEVER moves — kill every animation/transform on the card and its icon,
     in every state (John, 2026-09-01: "I don't like that it moves"). */
  .sb-staged, .sb-staged.pulse, .sb-staged.downloading,
  .sb-staged .sb-update-ic, .sb-staged.pulse .sb-update-ic { animation: none !important; transform: none !important; }
  .sb-staged, .sb-staged .sb-update-ic, .sb-staged .sb-update-title { color: var(--text); }
  .sb-staged .sb-update-sub { color: var(--muted); }
  .sb-update[hidden] { display: none; }
  /* BETA update card — amber, distinct from the accent-colored production card, with a
     small BETA tag and a skip ✕ (John, 2026-09-02). */
  .sb-update.beta { background: rgba(224,168,0,.16); border-color: rgba(224,168,0,.6); }
  .sb-update.beta, .sb-update.beta .sb-update-ic, .sb-update.beta .sb-update-title, .sb-update.beta .sb-update-sub { color: #e9b64a; }
  .sb-update.beta.pulse { animation: none; }   /* beta shouldn't shout like production */
  .sb-update-tag { flex: 0 0 auto; align-self: center; font-size: 8.5px; font-weight: 800; letter-spacing: .5px;
    padding: 1px 5px; border-radius: 999px; background: rgba(224,168,0,.22); color: #e9b64a; }
  .sb-update-tag[hidden] { display: none; }
  .sb-update-x { flex: 0 0 auto; align-self: center; width: 16px; height: 16px; line-height: 16px; text-align: center;
    font-size: 11px; border-radius: 3px; opacity: .55; cursor: pointer; }
  .sb-update-x:hover { opacity: 1; background: rgba(255,255,255,.12); }
  .sb-update-x[hidden] { display: none; }
  body.collapsed .sb-update-tag, body.collapsed .sb-update-x { display: none; }
  /* "Download Update" card, pinned above the account footer. Slight pulse + a gently
     bobbing download arrow to catch the eye without shouting. Click applies the update. */
  .sb-update.pulse { animation: sb-update-pulse 1.9s ease-in-out infinite; }
  .sb-update.pulse .sb-update-ic { animation: sb-update-bob 1.9s ease-in-out infinite; }
  @keyframes sb-update-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), .5); }
    60%  { box-shadow: none; }
    100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0); }
  }
  @keyframes sb-update-bob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(2px); } }
  .sb-update.downloading { cursor: default; border-color: rgba(255,255,255,.13); background: rgba(255,255,255,.045); }
  .sb-update.downloading:hover { filter: none; }
  /* Icon matches the title text colour, not the accent (John, 2026-08-24: "icon same as
     color text") — so it stays legible on the accent-soft pill under any accent. */
  .sb-update-ic { width: 20px; height: 20px; flex: 0 0 auto; color: var(--text); }
  .sb-update.downloading .sb-update-ic { color: #9a9a9a; }
  .sb-update-txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
  .sb-update-title { font-size: 12px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sb-update-sub { font-size: 10.5px; opacity: .72; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* collapsed rail (56px): icon only, centered */
  body.collapsed .sb-update { justify-content: center; padding: 9px 0; margin: auto 6px 6px; }
  body.collapsed .sb-update-ic { width: 26px; height: 26px; }
  body.collapsed .sb-update-txt { display: none; }
  /* A visible update/staged button owns the free space above it (margin-top:auto) and sits
     right above the footer line; drop the footer's own auto-margin so the two don't split it
     (John, 2026-09-14). When no button shows, the footer keeps its margin-top:auto below. */
  .sb-update:not([hidden]) ~ .side-footer { margin-top: 0; }
  /* Release pipeline pill — same footprint as the update card so the sidebar's
     bottom stack reads as one column. Square status dot, per the app-wide rule. */
  /* Deploy/build JOB CARD — lives in the session that launched it, like a branch-out. */
  .deploy-card { flex: 0 0 auto; margin: 8px 12px 0; padding: 10px 12px; display: flex; flex-direction: column; gap: 9px;
    background: color-mix(in srgb, var(--text) 5%, var(--panel)); border: 1px solid var(--line); border-radius: 6px; }
  .deploy-card[hidden] { display: none; }
  /* Inside the Jobs popover: no card chrome, it IS the job detail. */
  .deploy-card.in-jobs { margin: 9px 0 2px; padding: 0; background: transparent; border: none; }
  .dc-head { display: flex; align-items: center; gap: 7px; }
  .dc-dot { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; background: var(--accent); }
  .dc-dot.run { background: var(--accent); animation: sb-release-blink 1.2s ease-in-out infinite; }
  .dc-dot.ok { background: var(--accent); }
  .dc-dot.fail { background: #ff5f56; }
  .dc-title { color: var(--text); font-weight: 700; font-size: 12px; flex: 1 1 auto; }
  .dc-cpu { color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
  .dc-targets { display: flex; flex-direction: column; gap: 10px; }
  .sb-release { display: flex; flex-direction: column; gap: 8px; margin: 0 8px 8px; padding: 9px 11px;
    background: color-mix(in srgb, var(--text) 6%, var(--panel)); border: 1px solid var(--line);
    border-radius: 3px; font-size: 11.5px; }
  .sb-release[hidden] { display: none; }
  .sb-release-head { display: flex; align-items: center; gap: 7px; }
  .sb-release-dot { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; background: #8a8a8a; }
  .sb-release.running .sb-release-dot { background: var(--accent); animation: sb-release-blink 1.2s ease-in-out infinite; }
  .sb-release.ok .sb-release-dot { background: var(--accent); }
  .sb-release.fail .sb-release-dot { background: #ff5f56; }
  @keyframes sb-release-blink { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
  .sb-release-title { color: var(--text); font-weight: 700; flex: 1 1 auto; }
  .sb-release-cpu { color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; flex: 0 0 auto; }
  .sb-release-targets { display: flex; flex-direction: column; gap: 9px; }
  /* one card per build target */
  .rt-card { display: flex; flex-direction: column; gap: 5px; }
  .rt-top { display: flex; align-items: baseline; gap: 6px; }
  .rt-name { color: var(--text); font-weight: 600; font-size: 11px; flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rt-meta { color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; flex: 0 0 auto; }
  .rt-card.done .rt-meta { color: var(--accent); }
  .rt-card.failed .rt-meta { color: #ff5f56; }
  .rt-bar { height: 5px; border-radius: 3px; background: color-mix(in srgb, var(--text) 12%, transparent); overflow: hidden; }
  .rt-fill { height: 100%; border-radius: 3px; transition: width .5s ease; }
  .rt-fill.run { background: var(--accent); background-image: linear-gradient(90deg, transparent, rgba(255,255,255,.35), transparent); background-size: 40% 100%; background-repeat: no-repeat; animation: rt-sheen 1.3s linear infinite; }
  .rt-fill.done { background: var(--accent); }
  .rt-fill.fail { background: #ff5f56; }
  @keyframes rt-sheen { 0% { background-position: -40% 0; } 100% { background-position: 140% 0; } }
  .rt-steps { display: flex; flex-wrap: wrap; align-items: center; gap: 3px; }
  .rt-step { font-size: 9px; letter-spacing: .2px; color: var(--faint); padding: 1px 4px; border-radius: 3px; }
  .rt-step.done { color: var(--accent); }
  .rt-step.now { color: var(--on-accent); background: var(--accent); font-weight: 700; }
  .rt-step.fail { color: #fff; background: #ff5f56; font-weight: 700; }
  .rt-arrow { color: var(--faint); font-size: 9px; }
  .rt-detail { color: var(--muted); font-size: 10px; font-family: 'SF Mono', ui-monospace, monospace; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  body.collapsed .sb-release-targets, body.collapsed .sb-release-cpu, body.collapsed .sb-release-title { display: none; }
  body.collapsed .sb-release { align-items: center; padding: 7px 0; }
  .ts-tip.on { opacity: 1; }
  /* Styled tooltip shown on hover over ANY button — replaces native OS tooltips
     (killed in renderer.js) so every control tells you what it is, in-theme. */
  /* Neutral grey, NO orange accent rail (John, 2026-08-18: "I like the gray one
     better for tooltip. No orange line."). A tooltip is chrome, not a signal —
     the accent is reserved for things that mean something. */
  .ow-tip {
    position: fixed; z-index: 10000; pointer-events: none; max-width: 280px;
    background: #2a2a2c; color: #e8e8ea;
    border: 1px solid rgba(255,255,255,.10);
    border-radius: 6px; padding: 5px 9px;
    font-family: var(--ui-font); font-size: 11.5px; line-height: 1.35; letter-spacing: .2px;
    white-space: normal; word-break: break-word;
    box-shadow: 0 8px 22px rgba(0,0,0,var(--sh50, .5));
    opacity: 0; transform: translateY(3px); transition: opacity .12s ease, transform .12s ease;
  }
  /* Tooltip UI was removed; stale markup or an older renderer must stay invisible. */
  .ow-tip { display: none !important; }
  .ow-tip.below { transform: translateY(-3px); }
  .ow-tip.on { opacity: 1; transform: translateY(0); }
  /* The greys above are literals, not tokens, so light mode needs its own pair —
     otherwise a dark bubble floats on a white UI. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .ow-tip { background: #3a3a3c; color: #f5f5f7; border-color: rgba(0,0,0,.18); }
  /* Command-line composer: no input box, just a terminal prompt + the user's own
     orange blinking caret. John types INTO a command line, not a text field. */
  /* q-bar now renders INSIDE the card (renderer, 2026-09-20). Keep it a full-width row
     at the top of the card for the default skin. */
  .composer { flex-wrap: wrap; }
  .composer > .q-bar { flex: 0 0 100%; order: -1; }
  .composer { display: flex; gap: 8px; align-items: flex-end; background: transparent; border: none; border-radius: 3px; padding: 4px 2px 12px; }
  /* Constant model-tinted prompt marker to the LEFT of the input (John, 2026-09-01) —
     always visible, coloured to the model that will run (--model-c, set by
     renderQBarModel; falls back to brand accent). Sits on the text baseline. */
  .composer::before {
    /* SAME chevron, SAME size as the posted-query marker (.msg.user::before: 7x22px SVG
       mask) so the composer > is identical to the one on a sent query (John, 2026-09-02). */
    content: ""; flex: 0 0 auto; align-self: flex-start;
    /* margin-top 8px centres the 22px chevron on the 21px text line (9px pad + 10.5) —
       10px sat ~1.5px low (John, 2026-09-02). */
    width: 7px; height: 22px; margin-top: 8px;
    /* Match the caret (Preference/accent colour), NOT the model tint (John, 2026-09-11). */
    background: var(--accent);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 5 9 12 3 19'/%3E%3C/svg%3E") no-repeat center / contain;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 5 9 12 3 19'/%3E%3C/svg%3E") no-repeat center / contain;
    -webkit-user-select: none; user-select: none; pointer-events: none;
  }
  /* the orange › prompt — this line belongs to the user */
  .composer .cmd-prompt { flex: 0 0 auto; color: var(--accent); font-weight: 700; font-size: 15px; line-height: 1.5; font-family: ui-monospace, 'Brunea', monospace; -webkit-user-select: none; user-select: none; }
  /* textarea + a highlight layer behind it (colors the leading /command) share one box */
  .composer .ta-wrap { flex: 1; min-width: 0; position: relative; display: flex; }
  /* caret is ORANGE and a solid block: it's the user's cursor, not Claude's */
  /* CARET: use the REAL native caret (brand orange), NOT the old measured CRT block.
     The fake .ta-caret was positioned by measuring a mirror div and drifted a few
     characters from the true insertion point (the cursor looked like it was in one
     place but text landed 4-5 chars further). The browser's own caret is always at the
     exact spot under every font / paste / wrap, so it's the source of truth now. The
     fake block is hidden below; the mirror JS is left in place but no longer shown. */
  /* min-height FLOOR (John, 2026-07-29 — "caret is a tiny dot, half cut at the bottom").
     autoGrowInput() sizes this box from scrollHeight; when that measurement runs before
     layout/webfont settle (pane create / session restore — hence intermittent), it locked
     in a sub-line height and overflow-y:hidden clipped the caret down to a dot. Flooring the
     box at one full line + padding (border-box, so padding is included) guarantees a full,
     unclipped caret in every state; multi-line auto-grow still expands above this floor. */
  /* STANDARD caret, not caret-shape:block (John, 2026-09-01, after ~5 rounds). A native
     block caret is ALWAYS the full line-height (1.5em) tall — never a glyph-height
     rectangle — so under overflow:hidden it reads as a tall bar clipped at top/bottom no
     matter how the padding is split (verified at 4/4, 7/3, and 8/8). The browser's own
     I-beam is sized to the glyph, tracks the exact insertion point, and can never clip.
     Reliability over the terminal look: this is the cursor that is always correct. */
  .composer textarea { flex: 1; background: transparent; border: none; color: var(--text); caret-color: var(--accent); caret-shape: block; font: inherit; font-family: var(--chat-font); resize: none; outline: none; min-height: calc(1.5em + 18px); max-height: none; overflow-y: hidden; line-height: 1.5; padding: 9px 0; position: relative; z-index: 1; }
  /* while a /command is highlighted: hide the textarea's own text (both color and
     the WebKit text-fill, which can otherwise keep it visible) so the orange
     backdrop shows through; keep the caret visible. */
  .composer .ta-wrap.hl-on textarea { color: transparent; -webkit-text-fill-color: transparent; caret-color: var(--accent); }
  /* invisible twin of the textarea, used only to measure where the caret sits */
  .composer .ta-caret-mirror {
    position: absolute; inset: 0; z-index: 0; pointer-events: none; visibility: hidden;
    /* MUST mirror the textarea's metrics EXACTLY (font-family + padding), otherwise the
       measured block drifts from the real insertion point (John, 2026-09-02). */
    font: inherit; font-family: var(--chat-font); line-height: 1.5; padding: 9px 0; color: transparent;
    white-space: pre-wrap; overflow-wrap: break-word; word-break: normal; overflow: hidden;
  }
  /* the real typing cursor: same glowing CRT block as the thinking cursor */
  .composer .ta-caret {
    position: absolute; top: 0; left: 0; z-index: 2; display: none; pointer-events: none;
    width: .6em; height: 1.2em; margin-top: .15em; will-change: background-color;   /* flat block, centred on the 1.5em line */
    background: var(--accent);   /* FLAT color, no CRT scanlines (John, 2026-09-02) */
    box-shadow: none;
    /* REVERSE-VIDEO block, terminal-style: the glyph the block sits on is drawn
       INSIDE it (JS fills .textContent + sizes width to that glyph), so a solid block
       never hides a character — you read it dark-on-orange, like a real cursor. */
    color: var(--bg); font: inherit; line-height: 1.2em; text-align: center;
    overflow: hidden; white-space: pre; box-sizing: border-box;
    /* OPAQUE blink: the block stays solid and swaps colour (accent ↔ page bg) rather
       than fading to transparent, so you never see the line behind it on the off beat. */
    animation: caretPulse 1.06s steps(1, end) infinite;
  }
  /* colour swaps with the block so the covered glyph stays legible on BOTH beats:
     on-beat = dark glyph on orange; off-beat = orange glyph on page-bg (reads as normal text). */
  @keyframes caretPulse {
    0%,50% { background-color: var(--accent); box-shadow: none; color: var(--bg); }
    50.01%,100% { background-color: var(--bg); box-shadow: none; color: var(--accent); }
  }
  /* The FAT block cursor IS the measured .ta-caret again (John, 2026-09-02: the native
     block caret cannot be widened — its width is the next glyph / a space). The mirror now
     matches the textarea's font + padding exactly, so it no longer drifts (pixel-tested
     against the native caret in test/ui/composer-caret.test.mjs). Native caret hidden. */
  .composer .ta-wrap.caret-on .ta-caret { display: block; }
  .composer .ta-wrap.caret-on textarea { caret-color: transparent; }
  /* RESTING cursor (John, 2026-08-25): when a composer is NOT focused, the native caret
     vanishes — so show a STATIC, 20%-opacity block at the text start, no blink. It marks
     "this is where the cursor is" without competing with the one blinking active session.
     .caret-on is only set while the composer is focused with a collapsed caret, so its
     absence = unfocused/resting. */
  /* THE ONE RULE (John, 2026-09-03: "some sessions get the unfocused caret placeholder,
     some don't... I never want to come back to this"). The resting block shows in EVERY
     composer that is (a) NOT focused and (b) EMPTY — nothing else. It is keyed on the
     browser's own :focus + :placeholder-shown, never on a JS-maintained class, so a stale
     .caret-on can't suppress it. Running vs idle makes NO difference (the old
     `.pane.running ... ::after { display:none }` was exactly the inconsistency). A
     composer holding draft text shows no resting block because the cursor is at the END
     of that text, not the start — a block at left:0 would be a lie. */
  .composer .ta-wrap:has(textarea:not(:focus):placeholder-shown)::after {
    content: ""; position: absolute; left: 0; top: 0; margin-top: calc(.15em + 9px);
    width: .6em; height: 1.2em; background: var(--accent); opacity: .2;
    pointer-events: none; z-index: 1;
  }
  /* while moving/typing: hold the caret solid (accent, no blink) */
  .composer .ta-wrap.caret-solid .ta-caret { animation: none; background-color: var(--accent); box-shadow: none; color: var(--bg); }
  .composer textarea::placeholder { color: var(--muted); }
  /* Empty composer: nothing to edit, so make it fully unselectable — kills the
     stray grey highlight you could otherwise drag over the "Command…" placeholder.
     Selection comes right back the moment there's real text (placeholder gone). */
  .composer textarea:placeholder-shown { -webkit-user-select: none; user-select: none; }
  .composer textarea::placeholder { -webkit-user-select: none; user-select: none; }
  .composer textarea:disabled { -webkit-text-fill-color: var(--faint); color: var(--faint); }
  .composer .ta-hl {
    position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
    /* MUST match the textarea's font EXACTLY (John, 2026-08-26). The textarea overrides to
       var(--chat-font) but this layer only had `font: inherit` (composer's proportional UI
       font), so once a command highlighted — textarea text hidden, this layer shown — the
       visible text rendered narrower than the real glyphs and the native block caret jumped
       far right of it ("cursor went way off when I added a skill"). */
    font: inherit; font-family: var(--chat-font); line-height: 1.5; padding: 9px 0; color: var(--text);   /* 9px = the textarea's own padding; 4px drew the highlighted text 5px above the caret */
    white-space: pre-wrap; overflow-wrap: break-word; word-break: normal;
  }
  .composer .ta-hl .hl-cmd { color: #ffaf2b; font-weight: 600; }   /* Claude command = Opus yellow */
  .composer .ta-hl .hl-owm { color: var(--accent); font-weight: 600; }   /* Luminair command = orange */
  .composer .ta-hl .hl-macro { color: #5b8def; font-weight: 600; }   /* /// macro = Sonnet blue (John, 2026-07-31) */

  /* ===== message queue (chip above composer + right-side panel) ===== */
  /* ALWAYS ON now (John, 2026-08-16): the model selector on the left has no empty state
     of its own — a session always has a real model — so this row no longer hides itself.
     Two sides: the static model chip (left) and the queue/jobs/branching chips, which
     still come and go, in their own sub-container (right).
     Scoped to `.pane-composer .q-bar` specifically — `.q-bar` is a name .q-item (a queue
     row) ALSO uses for its own inner grip/model/actions strip; an unscoped rule here would
     leak `justify-content: space-between` onto that unrelated row. */
  .pane-composer .q-bar { display: flex; align-items: center; justify-content: flex-start; gap: 6px; padding: 0 2px 7px; margin-top: -3px; }
  .q-bar-chips { display: flex; align-items: center; gap: 6px; min-width: 0; margin-left: auto; }
  /* Model selector — SAME box as .q-chip (matched dimension for dimension per John's
     request), a dot standing in for the count badge. Neutral grey at rest; the moment
     renderQBarModel runs it recolours to the model's own hue via inline styles, exactly
     like the pane-head chip it mirrors. */
  .q-model-def {
    -webkit-app-region: no-drag; display: inline-flex; align-items: center; gap: 6px;
    background: var(--panel-2); color: var(--muted); border: 1px solid var(--line);
    border-radius: 3px; padding: 0 11px 0 7px; font-size: 11.5px; font-weight: 600; cursor: pointer;
    /* Pinned height shared with .q-chip so the model chip, Branching, and the jobs/queue
       chips are the exact same height whatever they contain (John, 2026-09-09). */
    height: 24px; box-sizing: border-box; line-height: 1;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
  }
  .q-model-def:hover { filter: brightness(1.15); }
  .q-attach {
    -webkit-app-region: no-drag; display: inline-flex; align-items: center; justify-content: center;
    background: var(--panel-2); color: var(--muted); border: 1px solid var(--line);
    border-radius: 3px; height: 24px; width: 24px; box-sizing: border-box; margin-left: 0;   /* leading edge: match the right-side send padding (John, 2026-09-15, was 5px) */
    font-size: 16px; font-weight: 500; line-height: 1; cursor: pointer;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
  }
  .q-attach:hover { filter: brightness(1.15); color: var(--text); }
  .q-model-def-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
  .q-model-def-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 120px; }
  .q-chip {
    /* FOLLOWS THE ACCENT PICKER (John, 2026-08-20: "the queue also has to follow the
       custom color") — reverses the 2026-07-30 call to pin it orange. The sibling chips
       stay semantic and fixed (branch-out gold --bo-*, Fathom blue --fx-*, jobs gold);
       only the plain queue chip now rides the real var(--accent) / --accent-rgb like
       everything else in the header, instead of a local orange override. */
    -webkit-app-region: no-drag; display: inline-flex; align-items: center; gap: 6px;
    background: var(--accent-soft); color: var(--accent); border: 1px solid rgba(var(--accent-rgb),.4);
    /* SQUARE CHIP, ROUND COUNT INSIDE — copied from the phone, which John prefers
       (2026-08-16: "I actually LOVE the square chips, and round dot inside"). Same numbers
       as mobile/src/styles.css .q-chip so the two apps read identically. */
    border-radius: 3px; padding: 0 11px 0 7px; font-size: 11.5px; font-weight: 600; cursor: pointer;
    /* Pinned height: the 18px round count inside the jobs/queue chips used to make those
       chips taller than Branching and the model chip. 24px outer fits the badge, and
       every chip in the row now measures the same (John, 2026-09-09). */
    height: 24px; box-sizing: border-box; line-height: 1;
  }
  .q-chip:hover { background: rgba(var(--accent-rgb),.22); }
  /* branch-out running: the branch-out GOLD pill that reopens the panel. Uses --bo-lt
     (bright, saturated gold) not --bo-txt (near-white pale gold) so it reads clearly as
     the branch-out signature colour, never green/cream. (John, 2026-07-31: "not the right
     colour" — it was showing green/washed-out; branch-out is ALWAYS gold.) */
  .q-chip.q-branching { color: var(--bo-lt); background: rgba(var(--bo-rgb),.16); border-color: rgba(var(--bo-rgb),.5); }
  .q-chip.q-branching:hover { background: rgba(var(--bo-rgb),.26); }
  .q-branching-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--bo-lt); box-shadow: none; animation: micpulse 1.1s ease-in-out infinite; flex: 0 0 auto; }
  /* Queued behind another session's branch-out on this project — parked, not live.
     Hollow, steady dot (no pulse) so "Waiting" reads as in-line, distinct from active "Branching". */
  .q-chip.q-branching.q-waiting { opacity: .9; }
  .q-chip.q-branching.q-waiting .q-branching-dot { background: transparent; border: 1.5px solid var(--bo-lt); box-shadow: none; animation: none; }
  /* The queued-count badge always wears the app THEME's accent (same as the send button),
     never the session window's custom tint (John, 2026-09-03: "the queued circle should not
     follow the sessions window custom color but the theme color like the send button"). */
  .q-chip .q-n { background: var(--accent); color: var(--on-accent); border-radius: 999px; min-width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; font-size: 10.5px; padding: 0 4px; }
  /* Fathom feedback count — GOLD, rides beside the orange queue count inside the orange chip (John, 2026-07-27) */
  .q-chip .q-n-fathom { background: var(--fx-lt); color: #0a1730; margin-left: 3px; box-shadow: none; }
  .q-chip .q-caret { font-size: 14px; line-height: 1; opacity: .85; }
  /* Compact by default: just the number + arrow. The word "queued" only appears
     when the composer is wide enough (container query on .pane-composer). */
  .q-chip .q-word { display: none; }
  @container comp (min-width: 440px) { .q-chip .q-word { display: inline; } }
  /* Queue chip: white word + caret (like the jobs chip) on the orange pill; the
     number badge stays orange. John, 2026-07-26. */
    /* Admin-console gate card (two-step / fresh sign-in needed): guidance + the fix, not a dead end. */
  .admin-gate { text-align: left; }
  .admin-gate-title { font-weight: 700; color: var(--text); margin-bottom: 4px; }
  .admin-gate-why { color: var(--dim); margin-bottom: 8px; }
  .admin-gate-steps { margin: 0 0 10px 18px; padding: 0; color: var(--dim); }
  .admin-gate-steps li { margin: 2px 0; }
  .admin-gate-acts { display: flex; gap: 8px; }
  /* Queue chip now reads like a folder's queued badge (John, 2026-09-14: "I like the
     one in the folders — remove the arrow, redesign the round chip to look like that").
     Bare (no chip box), squared accent-soft count pill matching .session .row-q, no caret. */
  /* Queue chip = the same 24px outlined square as the + attach button next to it
     (John, 2026-09-14: "same size as the + button, bring the outline back"). The
     count is the chip's own text, no inner badge, so it reads like a folder badge. */
  .q-chip.q-queue { min-width: 24px; height: 24px; padding: 0 5px; gap: 4px; justify-content: center; border-radius: 3px; border: 1px solid rgba(var(--accent-rgb),.4); background: var(--accent-soft); color: var(--accent); }
  .q-chip.q-queue:hover { background: rgba(var(--accent-rgb),.22); }
  .q-chip.q-queue .q-n { min-width: 0; height: auto; padding: 0; border-radius: 0; background: transparent; color: inherit; font-size: 11px; font-weight: 700; line-height: 1; box-shadow: none; }
  .q-chip.q-queue .q-caret { display: none; }
  /* Background chip — a neutral indigo, distinct from the orange queue chip and the
     green Branching pill. Opens the Background popup (live progress of running jobs). */
  /* Jobs chip is GOLD (the branch-out / deep-research family color), not purple. */
  .q-chip.q-bg { color: var(--bo-txt); background: rgba(var(--bo-rgb),.13); border-color: rgba(var(--bo-rgb),.46); }
  .q-chip.q-bg:hover, .q-chip.q-bg.pop-open { background: rgba(var(--bo-rgb),.24); }
  /* The jobs badge keeps its OWN gold — it must NOT inherit the session's model window
     colour (John, 2026-09-03: "the job dot should not adopt the session window color"). */
  .q-chip.q-bg .q-n { background: var(--bo-lt); color: #201800; }
  /* Untinted light-mode default: --bo-lt is a DARK stroke-gold (#946707) meant for thin
     glyphs, so as a solid fill under near-black text it reads muddy (John, 2026-08-24:
     "this is ugly"). Give the fill a pale gold with deep-gold text. A session tint still
     wins via --pane-tint-solid, so this only styles the plain, untinted badge. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .q-chip.q-bg .q-n { background: #f2dd9a; color: #5a3d00; }
  .q-chip.q-bg .q-bg-dot { display: none; }
  .q-chip.q-bg-run .q-bg-dot { display: inline-block; width: 7px; height: 7px; border-radius: 2px; background: var(--bo-lt); box-shadow: none; animation: micpulse 1.15s ease-in-out infinite; }
  /* Background popup reuses .mc-pop's box, dressed as one of the new cards
     (John, 2026-08-31): panel-2 surface, titled header, chip-style status pill. */
  .bg-pop { width: 320px; background: var(--panel-2); }
  .bg-pop .mc-pop-head { padding: 11px 14px 10px; }
  .bg-pop .mc-pop-title { font-size: 13px; font-weight: 800; letter-spacing: .2px; }
  /* The popup box (max-height set inline to fit the viewport) owns the scroll, so the
     inner list must NOT cap its own height — otherwise an expanded job detail nests a
     second scroll region and its buttons can hide below the fold. */
  .bg-pop .auto-list { max-height: none; overflow: visible; }
  /* Status becomes a card chip (matches .ask-chip): uppercase, tinted, rounded. */
  .mc-pop-status {
    font-size: 9px; font-weight: 700; letter-spacing: 1.4px; text-transform: uppercase;
    padding: 3px 7px; border-radius: 3px; color: var(--muted); background: var(--hover);
  }
  .mc-pop-status.live { color: var(--bo-txt); background: rgba(var(--bo-rgb), .14); }

  /* per-pane queue panel: lives inside its own session frame, clipped to it,
     so several sessions can each have their queue open without mixing. */
  .pane-queue {
    position: absolute; top: 0; right: 0; bottom: 0; width: var(--queue-w, 300px); max-width: 88%;
    background: var(--panel); border-left: 1px solid var(--line);
    transform: translateX(100%); transition: transform .2s ease;
    z-index: 8; display: flex; flex-direction: column;
    container-type: inline-size;   /* header adapts to the panel's real width */
  }
  /* Only cast the panel's drop shadow when it's actually OPEN. When closed it's
     parked off-screen right (translateX 100%), and its leftward blur was bleeding
     a dark band onto the pane's right edge — John didn't want that. */
  .pane.queue-open .pane-queue { transform: none; box-shadow: -14px 0 40px rgba(0,0,0,var(--sh40, .4)); }
  .pane.queue-open .pane-head .pclose { display: none !important; }
  /* drag the panel's left border to resize it; double-click to reset. Width is
     shared across every pane's queue panel (like the sidebar) and persists via
     --queue-w. body.resizing-queue suppresses the panel's own slide transition
     while dragging so it tracks the cursor with no lag. */
  .q-resizer { position: absolute; top: 0; left: -3px; bottom: 0; width: 6px; cursor: col-resize; z-index: 9; background: transparent; transition: background .12s ease; }
  .q-resizer:hover, body.resizing-queue .q-resizer { background: var(--accent-soft); }
  body.resizing-queue { cursor: col-resize; user-select: none; -webkit-user-select: none; }
  body.resizing-queue .pane-queue { transition: none; }
  .q-head { flex: 0 0 auto; display: flex; align-items: center; gap: 11px; padding: 13px 12px; border-bottom: 1px solid var(--line); }
  /* responsive header: as the panel narrows, shed the least-needed bits first */
  @container (max-width: 300px) {
    .q-head { gap: 8px; padding: 12px 10px; }
    .q-auto-lbl { display: none; }          /* the toggle alone still reads as auto-send */
  }
  @container (max-width: 250px) {
    .q-head { gap: 6px; }
    .q-count-badge { padding: 1px 6px; }
    .q-title { font-size: 13px; }
  }
  .q-title-wrap { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }
  .q-title { font-size: 14px; font-weight: 600; }
  .q-count-badge { background: var(--panel-2); border: 1px solid var(--line); color: var(--muted); border-radius: 3px; font-size: 11px; padding: 1px 8px; font-variant-numeric: tabular-nums; }
  .q-x { background: transparent; border: none; color: var(--faint); font-size: 14px; width: 26px; height: 26px; border-radius: 3px; cursor: pointer; flex: 0 0 auto; }
  .q-x:hover { color: var(--text); background: var(--hover); }
  /* Text button, not a trash glyph (John, 2026-09-22): auto width so the word fits. */
  .q-clear { background: transparent; border: 1px solid var(--line); color: var(--muted); border-radius: 3px; height: 28px; padding: 0 10px; font: inherit; font-size: 12px; cursor: pointer; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; }
  .q-clear:hover { color: #e5484d; border-color: rgba(229,72,77,.5); background: rgba(229,72,77,.08); }
  /* global-pause banner inside the queue panel (shows when the "pause all queues"
     switch holds this session even though its own flow toggle reads ON) */
  .q-globalpause { display: flex; flex-direction: column; gap: 8px; align-items: flex-start;
    background: rgba(229,150,72,.12); border: 1px solid rgba(229,150,72,.45); border-radius: 3px;
    padding: 10px 12px; margin-bottom: 10px; }
  .q-gp-txt { font-size: 12px; line-height: 1.45; color: var(--text); overflow-wrap: anywhere; }
  .q-gp-resume { align-self: stretch; background: #e59648; color: #1a1a1a; border: none; border-radius: 3px;
    padding: 7px 10px; font-size: 12px; font-weight: 700; cursor: pointer; }
  .q-gp-resume:hover { filter: brightness(1.08); }
  /* auto-send switch */
  .q-auto { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; font-size: 12px; color: var(--muted); user-select: none; flex: 0 0 auto; }
  .q-auto input { position: absolute; opacity: 0; width: 0; height: 0; }
  .q-auto-track { width: 30px; height: 17px; border-radius: 999px; background: var(--line); position: relative; transition: background .15s; flex: 0 0 auto; }
  .q-auto-track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px; border-radius: 50%; background: #cfcfcf; transition: transform .15s; }
  .q-auto input:checked + .q-auto-track { background: var(--accent); }
  .q-auto input:checked + .q-auto-track::after { transform: translateX(13px); background: #fff; }
  .q-auto input:checked ~ .q-auto-lbl { color: var(--text); }
  /* The per-session [Controller] title-bar toggle was removed — MC is one global switch
     (the yellow chip by "//"), not per-session. */
  /* Controller ON no longer recolors the focused session (John, 2026-07-25: keep the
     session glow ORANGE, not gold). The controller's live signal is the gold MC chip,
     the "Controlling" word, and the ledger — the pane keeps its normal accent glow. */
  .q-body { flex: 1; overflow-y: auto; padding: 10px; }
  .q-empty { color: var(--faint); font-size: 12px; text-align: center; padding: 40px 16px; line-height: 1.6; }
  /* GOLD Fathom feedback cards in the queue panel (John, 2026-07-27) */
  .q-fathom { margin-bottom: 10px; padding: 8px; background: rgba(var(--fx-rgb),.08); border: 1px solid rgba(var(--fx-rgb),.34); border-radius: 3px; }
  .q-fathom-head { display: flex; align-items: center; gap: 7px; margin-bottom: 7px; padding: 0 2px; }
  .q-fathom-ttl { color: var(--fx-txt); font-size: 11.5px; font-weight: 800; letter-spacing: .02em; }
  .q-fathom-n { background: var(--fx-lt); color: #0a1730; border-radius: 3px; min-width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center; font-size: 10.5px; font-weight: 700; padding: 0 4px; }
  .q-fathom-clear { margin-left: auto; background: transparent; color: var(--fx-txt); border: 1px solid rgba(var(--fx-rgb),.45); border-radius: 3px; font-size: 10.5px; font-weight: 700; padding: 3px 8px; cursor: pointer; }
  .q-fathom-clear:hover { background: rgba(var(--fx-rgb),.18); }
  .q-fx-item { padding: 8px 9px; margin-bottom: 6px; background: var(--panel-2); border: 1px solid rgba(var(--fx-rgb),.28); border-left: 3px solid var(--fx-lt); border-radius: 3px; }
  .q-fx-item:last-child { margin-bottom: 0; }
  .q-fx-top { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
  .q-fx-verdict { font-size: 9.5px; font-weight: 800; letter-spacing: .05em; color: #0a1730; background: var(--fx-lt); border-radius: 3px; padding: 1px 6px; }
  .q-fx-item.v-love .q-fx-verdict { background: #58c98a; }
  .q-fx-item.v-kill .q-fx-verdict { background: #e0704f; color: #fff; }
  .q-fx-item.v-change .q-fx-verdict { background: #e3b341; }
  .q-fx-board { font-size: 10px; color: var(--faint); text-transform: lowercase; }
  .q-fx-done { margin-left: auto; background: transparent; color: var(--fx-txt); border: 1px solid rgba(var(--fx-rgb),.4); border-radius: 3px; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; cursor: pointer; flex-shrink: 0; }
  .q-fx-done:hover { background: rgba(var(--fx-rgb),.2); }
  .q-fx-title { font-size: 11.5px; color: var(--text); line-height: 1.4; overflow-wrap: anywhere; }
  .q-fx-note { font-size: 12px; color: var(--text); line-height: 1.45; margin-top: 3px; overflow-wrap: anywhere; }
  /* Queue rows: one clean line — grip · prompt · (actions on hover). Neutral black/gray
     at rest; the orange send button only appears when you hover the row, so the resting
     list is calm and never orange-speckled (John, 2026-08-04). */
  /* A queued request is a CARD: title bar on top, request text full-width below. The
     buttons live in the bar in normal flow — never floating over the words. */
  .q-item { position: relative; display: flex; flex-direction: column; align-items: stretch; gap: 8px; padding: 9px 10px 11px; margin-bottom: 8px; background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; transition: background .12s ease, border-color .12s ease; }
  .q-bar { display: flex; align-items: center; gap: 6px; min-width: 0; }
  /* Per-item model pin. Neutral when it follows the session; in the model's own colour
     once pinned, so you can read a queue's model mix at a glance. */
  /* SHRINKS instead of overflowing (John, 2026-09-06: "on tiny session width, the buttons
     are fighting") — at 0 0 auto this chip held its full content width no matter how
     narrow the queue panel got, so it and the action buttons fought over space and
     visually crammed together. flex-shrink + min-width:0 let it give way; the name
     underneath already ellipsizes. */
  .q-model { flex: 0 1 auto; min-width: 0; display: inline-flex; align-items: center; gap: 5px; max-width: 150px; background: transparent; border: 1px solid var(--line); border-radius: 3px; padding: 2px 8px 2px 6px; font-size: 10.5px; font-weight: 700; color: var(--faint); cursor: pointer; white-space: nowrap; transition: color .12s ease, border-color .12s ease, background .12s ease; }
  .q-model:hover { color: var(--text); border-color: #3a3a3a; background: var(--hover); }
  .q-model-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .5; flex: 0 0 auto; }
  .q-model-name { overflow: hidden; text-overflow: ellipsis; }
  .q-model.pinned { color: var(--qm); border-color: color-mix(in srgb, var(--qm) 45%, transparent); background: color-mix(in srgb, var(--qm) 12%, transparent); }
  .q-model.pinned .q-model-dot { opacity: 1; }
  .q-item:hover { background: var(--hover); border-color: #3a3a3a; }
  .q-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
  /* actions sit over the row's right edge, hidden until hover, with a fade so long
     prompts slide cleanly underneath instead of being permanently squeezed. */
  /* In the bar, pushed right — always present (no hover-reveal, no overlay, no gradient
     fade over the text). Slightly muted at rest so the card reads calm, full on hover. */
  .q-actions { margin-left: auto; display: flex; align-items: center; gap: 5px; opacity: 1; transition: opacity .12s ease; }
  .q-item:hover .q-actions, .q-item:focus-within .q-actions { opacity: 1; }
  .q-item.dragging { opacity: .4; }
  .q-item.drop-before, .q-item.drop-after { position: relative; }
  .q-item.drop-before::before, .q-item.drop-after::after {
    content: ''; position: absolute; left: 0; right: 0; height: 2px; background: var(--accent); border-radius: 3px;
  }
  .q-item.drop-before::before { top: -5px; }
  .q-item.drop-after::after { bottom: -5px; }
  .q-drag { cursor: grab; color: var(--faint); font-size: 14px; line-height: 1.5; padding: 2px; flex: 0 0 auto; user-select: none; }
  .q-drag:active { cursor: grabbing; }
  .q-team-from { min-width: 0; display: inline-flex; align-items: center; gap: 5px; color: var(--accent); font-size: 10.5px; font-weight: 750; white-space: nowrap; overflow: hidden; }
  .q-team-from svg { width: 13px; height: 13px; flex: none; }
  .q-team-from span { overflow: hidden; text-overflow: ellipsis; }
  .q-item.team-query { border-left: 3px solid var(--accent); }
  /* picture glyph: only rendered (as a real <button>) when the request carries an image;
     otherwise it's an empty spacer so the drag handle stays lined up either way */
  /* Every action reads as a real button at rest (John, 2026-08-12: "I need each
     button to look like buttons"): a 24px box with a resting surface + border, not
     a naked hover-only icon. Shared base here; per-button colour/hover below. */
  .q-actions button { flex: 0 0 auto; width: 27px; height: 27px; border-radius: 3px;
    background: rgba(255,255,255,.09); border: 1px solid #3a3a3a; color: var(--muted); cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center; line-height: 1;
    transition: color .12s ease, background .12s ease, border-color .12s ease, filter .12s ease; }
  .q-actions button svg { width: 13px; height: 13px; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .q-actions button:not(.q-send) { background: rgba(0,0,0,.05); border-color: #d0d0d0; }
  /* Belt and braces: the primary action keeps the accent fill and its readable ink in
     every theme, whatever else targets .q-actions button later. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .q-actions button.q-send { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  .q-imgflag { min-width: 15px; }
  .q-imgflag.empty { display: inline-block; }
  button.q-imgflag { color: var(--muted); }
  button.q-imgflag svg { width: 13px; height: 13px; }
  button.q-imgflag:hover { color: var(--accent); background: var(--hover); border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
  .q-item.paused .q-imgflag { color: var(--accent); }
  .q-text { width: 100%; min-width: 0; font-size: 12.5px; color: var(--text); line-height: 1.45; outline: none; overflow-wrap: anywhere; white-space: pre-wrap; border-radius: 3px; padding: 2px 2px; }
  .q-text:focus { background: var(--bg); box-shadow: inset 0 0 0 1px var(--accent); }
  /* Faint "📎 image" hint for an image-only queue item — drawn, never real text, so
     editing/blur can't write the glyph back as the item's prompt. */
  .q-text:empty::before { content: attr(data-ph); color: var(--faint); pointer-events: none; }
  .q-del { color: var(--muted); font-size: 15px; }
  /* send-next: the composer's orange send button, shrunk, last in the title bar.
     Keeps its solid accent fill so it stays the primary action of the row. */
  /* .q-actions prefix so this keeps the accent fill over the shared .q-actions button
     base (which otherwise wins on specificity and greyed the send button out). */
  .q-actions button.q-send {
    order: 9;
    background: var(--accent); color: var(--on-accent); border-color: var(--accent);
    font-size: 13px; font-weight: 700;
  }
  .q-actions button.q-send:hover { filter: brightness(1.07); background: var(--accent); border-color: var(--accent); }
  .q-del:hover { color: #e5484d; background: rgba(229,72,77,.12); border-color: rgba(229,72,77,.5); }
  /* hold-for-later: pause a queued item; when held, gray the text but keep a bright white play icon */
  .q-pause { color: var(--muted); }
  .q-pause svg { width: 13px; height: 13px; }
  .q-pause:hover { color: var(--text); background: var(--hover); border-color: #3a3a3a; }
  .q-item.paused { border-style: dashed; }
  .q-item.paused .q-text { color: var(--faint); }
  .q-item.paused .q-text:focus { color: var(--text); }
  /* Held item: the Play button IS the paused signal now (no chip), so make it the
     bright accent-tinted resume action instead of a faint ghost icon. */
  .q-item.paused .q-pause { color: var(--accent); background: rgba(var(--accent-rgb),.16); border-color: rgba(var(--accent-rgb),.5); }
  .q-item.paused .q-pause:hover { color: var(--accent); background: rgba(var(--accent-rgb),.26); border-color: rgba(var(--accent-rgb),.7); }
  /* ⋯ fold-out: hidden while the panel is roomy (the four buttons show inline).
     When the panel gets too narrow to fit them (John, 2026-08-12: "buttons issue
     when tight window — just have a ... like we have on sessions"), the container
     query below hides the four buttons and shows only this ⋯, which opens the same
     actions as a menu — the exact fold-to-⋯ move a tight session head makes. */
  .q-actions button.q-more { display: none; color: var(--faint); font-size: 16px; line-height: 0; padding-bottom: 4px; }
  .q-actions button.q-more:hover { color: var(--text); background: var(--hover); border-color: #3a3a3a; }
  @container (max-width: 290px) {
    /* Keep DELETE (✕) visible even when narrow — John wants to remove a queued item
       directly, not hunt for it in the ⋯ menu (2026-08-27). The rest still fold. */
    .q-actions .q-imgflag, .q-actions .q-pause, .q-actions button.q-send { display: none; }
    .q-actions button.q-more { display: inline-flex; }
  }
  /* Tiny panel: even model-chip + ✕ + ⋯ crowd each other — drop the chip's text label,
     keep just its coloured dot, so the row always has room to breathe. */
  @container (max-width: 220px) {
    .q-model { max-width: 24px; padding: 4px 6px; gap: 0; }
    .q-model-name { display: none; }
  }
  /* branch-out button + minimal progress */
  /* Branch-out wears the custom ACCENT, not the gold (John, 2026-08-24: "Branch out in
     custom color"). Re-scoping the --bo family on every branch-out container cascades to
     the button, running pill, live card, recap and the sidebar merge state. */
  .q-branchout, .q-chip.q-branching, .q-bo, .bo-super, .bo-hero, .bo-recap, .bo-recap-card, .side-branches.merging, .mcr-card {
    --bo-rgb: var(--accent-rgb); --bo: var(--accent); --bo-lt: var(--accent); --bo-txt: var(--accent);
  }
  .q-branchout { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; margin-bottom: 8px; padding: 9px; background: rgba(var(--bo-rgb),.14); color: var(--bo-txt); border: 1px solid rgba(var(--bo-rgb),.5); border-radius: 3px; font-size: 12.5px; font-weight: 700; cursor: pointer; }
  .q-branchout:hover { background: rgba(var(--bo-rgb),.24); border-color: rgba(var(--bo-rgb),.7); }
  .q-branchout svg { width: 14px; height: 14px; }
  /* NEW CARD LANGUAGE (John, 2026-08-18) — same shape as Recap / Action / the doc card:
     no fill, no enclosing box, one vertical rail carrying the colour, generous air.
     Branch-out's identity colour is the Master Controller gold (--bo), so the rail is
     gold here rather than orange. Replaces the old filled panel-2 + full 1px border. */
  .q-bo {
    background: transparent;
    border: none; border-left: 2px solid rgba(var(--bo-rgb), .45);
    border-radius: 3px;
    padding: 12px 14px 13px; margin-bottom: 10px; font-size: 12px;
  }
  /* The same card, dropped into the TRANSCRIPT so a live branch-out is visible while you
     keep chatting. It scrolls with the conversation like any other message; the queue
     panel keeps its own pinned copy at the top. */
  .msg.bo-live { align-self: stretch; width: 100%; max-width: 100%; padding: 0; margin: 14px 0; }
  .msg.bo-live .q-bo { margin-bottom: 0; }
  .msg.bo-live .q-bo-card-label {
    font-size: 10px; font-weight: 600; letter-spacing: 1.6px; text-transform: uppercase;
    color: var(--bo-txt); opacity: .55; margin: 0 0 10px;
  }
  .q-bo-head { display: flex; align-items: center; gap: 7px; font-weight: 600; color: var(--text); }
  .q-bo-head.done { color: #45e3b0; } .q-bo-head.err { color: #e5484d; }
  .q-bo-spin { width: 11px; height: 11px; border-radius: 50%; border: 2px solid var(--line); border-top-color: var(--accent); animation: boSpin .8s linear infinite; flex: 0 0 auto; }
  @keyframes boSpin { to { transform: rotate(360deg); } }
  .q-bo-groups { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
  .q-bo-g { font-size: 10.5px; padding: 2px 7px; border-radius: 3px; border: 1px solid var(--line); color: var(--faint); }
  .q-bo-g.running { color: var(--accent); border-color: rgba(var(--accent-rgb),.5); }
  .q-bo-g.done { color: #45e3b0; border-color: rgba(69,227,176,.5); }
  .q-bo-g.error { color: #e5484d; border-color: rgba(229,72,77,.5); }
  .q-bo-g.research { border-style: dashed; }   /* research groups read differently from code */
  .q-bo-g.research.running { color: #74b0e6; border-color: rgba(116,176,230,.5); }
  .q-bo-g.research.done { color: #74b0e6; border-color: rgba(116,176,230,.5); }
  .q-bo-branch { margin-top: 8px; font-family: "SF Mono", ui-monospace, monospace; font-size: 11.5px; color: var(--text); background: var(--bg); border: 1px solid var(--line); border-radius: 3px; padding: 5px 8px; overflow-wrap: anywhere; }
  .q-bo-sub { margin-top: 6px; font-size: 11px; color: var(--faint); line-height: 1.4; }
  .q-bo-dismiss { margin-top: 8px; background: transparent; border: 1px solid var(--line); color: var(--muted); border-radius: 3px; padding: 5px 10px; font-size: 11.5px; cursor: pointer; }
  .q-bo-dismiss:hover { color: var(--text); background: var(--hover); }
  /* "Ready to test" actions: primary Test-it button + Dismiss, side by side */
  .q-bo-actions { display: flex; gap: 8px; align-items: center; margin-top: 8px; }
  .q-bo-actions .q-bo-dismiss { margin-top: 0; }
  .q-bo-test { background: var(--accent); border: 1px solid var(--accent); color: #fff; border-radius: 3px; padding: 5px 12px; font-size: 11.5px; font-weight: 600; cursor: pointer; }
  .q-bo-test:hover { filter: brightness(1.08); }
  .q-bo-test:disabled { opacity: .6; cursor: default; filter: none; }
  .q-bo-test.stop { background: transparent; color: var(--accent); }
  /* live status line under the card */
  .bo-test-status { display: flex; align-items: center; gap: 6px; margin-top: 8px; font-size: 11px; line-height: 1.4; color: var(--faint); overflow-wrap: anywhere; }
  .bo-test-status.err { color: #e5484d; }
  .bo-test-status.ok { color: #45e3b0; }
  .bo-test-log { color: var(--muted); font-family: "SF Mono", ui-monospace, monospace; font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
  .bo-test-link { font-family: "SF Mono", ui-monospace, monospace; color: var(--accent); user-select: all; overflow-wrap: anywhere; }
  .bo-test-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: #45e3b0; box-shadow: 0 0 0 0 rgba(69,227,176,.6); animation: boTestPulse 1.8s ease-out infinite; }
  @keyframes boTestPulse { 0% { box-shadow: 0 0 0 0 rgba(69,227,176,.5); } 70% { box-shadow: none; } 100% { box-shadow: 0 0 0 0 rgba(69,227,176,0); } }
  /* branch-out as a super-agent tree: orchestrator on top, worker subagents under it.
     It's appended first in the queue list so it naturally sits at the top — it must
     NOT be sticky/fixed, or it blocks scrolling to the queued items underneath it. */
  /* Active branch-out = a self-contained top card: header + progress squares + Cancel
     stay put; only the agent list scrolls. So scrolling doesn't drag the whole thing. */
  .q-bo.bo-active { display: flex; flex-direction: column; max-height: 100%; overflow: hidden; }
  .q-bo.bo-active > .bo-super,
  .q-bo.bo-active > .ag-grid,
  .q-bo.bo-active > .bo-cancel { flex: 0 0 auto; }
  .q-bo.bo-active > .bo-subs { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; }
  /* Gold signature for the live branch-out card (research card keeps its own colour). */
  .q-bo.bo-active { border-color: rgba(var(--bo-rgb), .42); background: linear-gradient(180deg, rgba(var(--bo-rgb), .07), rgba(var(--bo-rgb), 0) 60%), var(--panel-2); }
  .q-bo.bo-active .q-bo-spin { border-top-color: var(--bo-lt); }
  .q-bo.bo-active .bo-super { border-bottom-color: rgba(var(--bo-rgb), .28); }
  .q-bo.bo-active .bo-super-title { color: var(--bo-txt); }
  .q-bo.bo-active .bo-super-sub { color: var(--bo-txt); opacity: .82; }
  /* ---- agent grid: one square per agent, lighting up as it works ---- */
  .ag-grid { display: flex; flex-wrap: wrap; gap: 3px; margin: 10px 0 2px; cursor: pointer; }
  /* Every square is the SAME 9×9 box. A bright fill (green/orange) IRRADIATES on the
     dark bg — it optically blooms and reads BIGGER than a dark gray 9×9 box even at
     identical geometry (this is why green kept looking oversized, every version).
     Fix (John, 2026-07-27): a 1px INSET dark bezel on EVERY square crops that bloom by
     darkening the perimeter, so the bright core is contained and all squares read the
     same size. NO outer rings, NO glow — both ADD apparent size. Do NOT re-add an outer
     ring or glow to the running/done squares, and do NOT special-case green. */
  .ag-sq { width: 9px; height: 9px; border-radius: 3px; background: #2c2c2c; flex: 0 0 auto; box-sizing: border-box; box-shadow: inset 0 0 0 1px rgba(0,0,0,var(--shEdge, .32)); }
  .ag-sq.running { background: var(--accent); animation: micpulse 1.1s ease-in-out infinite; }
  /* padding:0/align-self/font-size REASSERTED (John, 2026-09-06): the generic bare `.done` chat rule
     (padding 8px 4px 6px, align-self flex-start, 11.5px font) also matches `.ag-sq.done` and made the
     green square 17px tall while running/queued stayed 9px. Same trap .auto-dot.done fell into. */
  .ag-sq.done { background: #45e3b0; padding: 0; align-self: auto; font-size: 0; line-height: 0; text-align: left; }
  .ag-sq.error { background: #e5484d; }
  .ag-hint { font-size: 10px; color: var(--faint); margin-top: 6px; }
  /* ---- agents drawer: per-agent detail, slides in on the pane's right ---- */
  .agents-drawer {
    position: absolute; top: 34px; right: 0; bottom: 0; width: 280px; z-index: 8;
    background: var(--panel); border-left: 1px solid var(--line);
    transform: translateX(100%); transition: transform .18s ease;
    display: flex; flex-direction: column;
  }
  .pane.agents-open .agents-drawer { transform: none; }
  .agents-head { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--line); font-size: 11px; font-weight: 700; letter-spacing: .6px; color: var(--muted); }
  .agents-head .agents-x { margin-left: auto; cursor: pointer; color: var(--faint); font-size: 13px; padding: 2px 5px; border-radius: 3px; }
  .agents-head .agents-x:hover { color: var(--text); background: var(--hover); }
  .agents-body { flex: 1; overflow-y: auto; padding: 8px 9px; display: flex; flex-direction: column; gap: 2px; }
  /* deep-research card — on-brand: a soft accent outline + glow, real padding, and
     clear sections (header │ agent squares │ cancel). Everything below is SCOPED to
     .research-card so the shared branch-out panel keeps its own look. */
  /* Qualified with .msg.assistant so the card's own padding beats the generic
     `.msg.assistant { padding: 2px 4px }` rule (higher specificity) — otherwise the
     header jams into the top-left corner (John, 2026-07-25). */
  /* Same surface as the Context Card banner (.ctx-pop): a flat accent-tinted panel,
     thin accent border, 10px radius, NO glow / NO drop-shadow / NO animated sweep, and
     brand orange (--accent) — NOT model-tinted. The added elements (progress/RAM meter,
     agent grid, cancel button) sit on this clean surface. (John, 2026-07-27) */
  .msg.assistant.research-card, .msg.assistant.research-done {
    align-self: stretch; width: 100%; box-sizing: border-box;
    position: relative; overflow: hidden;
    background: rgba(var(--accent-rgb), .015);
    border: 1px solid rgba(var(--accent-rgb), .30); border-radius: 3px;
    padding: 16px 18px 16px; font-size: 12px; color: #fff;
    box-shadow: none;
  }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .msg.assistant.research-card,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .msg.assistant.research-done {
    background: rgba(var(--accent-rgb), .07); border-color: rgba(var(--accent-rgb), .28); color: var(--text);
  }
  .msg.assistant.research-done { padding: 14px 18px; }
  .research-done .bo-super { border-bottom: none; padding-bottom: 0; margin-bottom: 0; align-items: center; }
  /* header: spinner + title + subtitle, with a divider + breathing room below */
  .research-card .bo-super {
    display: flex; align-items: flex-start; gap: 11px;
    padding-bottom: 14px; margin-bottom: 14px;
    border-bottom: 1px solid rgba(var(--rc-rgb, var(--accent-rgb)), .16);
  }
  .rc-titlerow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .research-card .bo-super-title { font-size: 13.5px; font-weight: 700; letter-spacing: .2px; color: var(--text); }
  /* Claude-native deep-research card: a small neutral "Claude" tag distinguishes it
     from the Luminair // card, and a live feed mirrors the real web activity. */
  .cdr-tag {
    font-size: 9px; font-weight: 700; letter-spacing: .8px; text-transform: uppercase;
    color: var(--faint); line-height: 1; white-space: nowrap; flex-shrink: 0;
    padding: 3px 7px; border-radius: 3px;
    border: 1px solid var(--line); background: rgba(255,255,255,.03);
  }
  .cdr-feed {
    margin-top: 11px; display: flex; flex-direction: column; gap: 5px;
    border-top: 1px solid rgba(var(--rc-rgb, var(--accent-rgb)), .12); padding-top: 10px;
  }
  .cdr-line {
    display: flex; align-items: center; gap: 8px; min-width: 0;
    font-size: 11px; color: #b4b4b4; animation: cdrIn .25s ease;
  }
  @keyframes cdrIn { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }
  .cdr-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* the finished card is .research-done (not .research-card) — make sure ITS summary
     wraps too, so "· report below" never clips off a narrow pane. */
  .cdr-card .bo-super-sub {
    white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere;
  }
  .cdr-ic {
    flex-shrink: 0; width: 13px; height: 13px; border-radius: 3px; position: relative;
    background: rgba(var(--rc-rgb, var(--accent-rgb)), .14);
    border: 1px solid rgba(var(--rc-rgb, var(--accent-rgb)), .3);
  }
  /* search = a tiny magnifier dot; source = a page tick — drawn in the model tint */
  .cdr-ic.search::after {
    content: ''; position: absolute; left: 3px; top: 3px; width: 4px; height: 4px;
    border: 1.2px solid var(--rc); border-radius: 50%;
    box-shadow: 3.5px 3.5px 0 -1px var(--rc);
  }
  .cdr-ic.source::after {
    content: ''; position: absolute; left: 4px; top: 3px; width: 5px; height: 7px;
    border: 1.2px solid var(--rc); border-radius: 3px;
  }
  .research-card .bo-super-sub {
    font-size: 11px; color: var(--muted); margin-top: 5px; line-height: 1.5;
    white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere;   /* let "24k tok" wrap, never clip */
  }
  .research-card .ag-grid { gap: 5px; margin: 0; }
  /* No per-card square override: running is solid brand orange with the same inset
     bezel as every other square (the old override set an undefined --rc fill → hollow
     square + a 9px glow that bloomed; both removed 2026-07-27). Squares MUST always match. */
  .research-card .ag-hint { font-size: 10.5px; margin-top: 10px; color: var(--faint); }
  /* Live RAM meter (John, 2026-07-25) — watch memory climb toward the emergency line */
  .mem-meter { margin-top: 14px; }
  .mem-bar {
    position: relative; height: 8px; border-radius: 3px; overflow: hidden;
    background: rgba(var(--rc-rgb, var(--accent-rgb)), .12);
    border: 1px solid rgba(var(--rc-rgb, var(--accent-rgb)), .18);
  }
  .mem-fill {
    height: 100%; border-radius: 3px; position: relative;
    transition: width .5s ease, background-color .5s ease;
    background-image: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.28) 50%, rgba(255,255,255,0));
    background-size: 42% 100%; background-repeat: no-repeat;
    animation: rcShim 1.8s linear infinite;
  }
  @keyframes rcShim { 0% { background-position: -45% 0; } 100% { background-position: 145% 0; } }
  .mem-meter.ok    .mem-fill { background-color: #34c07a; }
  .mem-meter.warn  .mem-fill { background-color: #e6a417; }
  .mem-meter.danger .mem-fill { background-color: #e5484d; }
  /* the emergency-stop line drawn across the track */
  .mem-limit { position: absolute; top: -2px; bottom: -2px; width: 2px; background: rgba(229,72,77,.7); transform: translateX(-1px); }
  .mem-label { margin-top: 5px; font-size: 10.5px; color: var(--muted); display: flex; align-items: baseline; gap: 4px; flex-wrap: wrap; }
  .mem-label b { color: var(--text); font-weight: 600; }
  .mem-meter.warn  .mem-label b { color: #e6a417; }
  .mem-meter.danger .mem-label b { color: #e5484d; }
  .mem-cap { margin-left: auto; color: var(--faint); font-size: 9.5px; flex-shrink: 0; }
  .research-card .bo-cancel {
    margin-top: 15px; width: 100%; background: transparent; border: 1px solid var(--line);
    color: var(--muted); border-radius: 3px; padding: 8px 12px; font-size: 12px; font-weight: 500;
    cursor: pointer; transition: color .12s, border-color .12s, background .12s;
  }
  .research-card .bo-cancel:hover:not(:disabled) { color: #e5484d; border-color: rgba(229,72,77,.5); background: rgba(229,72,77,.08); }
  .bo-cancel { margin-top: 9px; background: transparent; border: 1px solid var(--line); color: var(--muted); border-radius: 3px; padding: 5px 11px; font-size: 11.5px; cursor: pointer; }
  .bo-cancel:hover { color: var(--text); background: var(--hover); }
  .bo-cancel:disabled { opacity: .5; cursor: default; }
  .bo-super { display: flex; align-items: center; gap: 9px; padding-bottom: 9px; border-bottom: 1px solid var(--line); }
  .bo-super-ic { width: 15px; height: 15px; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; font-size: 12px; }
  .bo-super-ic.done { color: #45e3b0; }
  .bo-super-meta { flex: 1; min-width: 0; }
  .bo-super-title { font-weight: 700; font-size: 12px; color: var(--text); letter-spacing: .2px; }
  .bo-super-sub { font-size: 10.5px; color: var(--faint); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .bo-subs { position: relative; display: flex; flex-direction: column; gap: 2px; margin-top: 8px; }
  .bo-subs.hid { display: none; }
  /* MINIMAL WORKFLOW GRAPH: colour is the whole message, every label is a hover tooltip. */
  .bo-graphwrap { margin: 8px 0 2px; cursor: pointer; }
  .bo-graph { display: block; width: 100%; height: auto; overflow: visible; }
  .bo-gx { fill: none; stroke: var(--line); stroke-width: .8; vector-effect: non-scaling-stroke; }
  .bo-gx.run { stroke: var(--accent); }
  .bo-gx.done { stroke: #45e3b0; opacity: .55; }
  .bo-gx.err { stroke: #e5484d; opacity: .7; }
  .bo-gn { fill: var(--line); stroke: var(--panel); stroke-width: 1; vector-effect: non-scaling-stroke; }
  .bo-gn.ctl { fill: var(--txt); }
  .bo-gn.run { fill: var(--accent); animation: bo-work 1.2s ease-in-out infinite; }
  .bo-gn.done { fill: #45e3b0; }
  .bo-gn.err { fill: #e5484d; }
  .bo-gn.wait { fill: var(--line); }
  /* One fold for every textual detail under the graph. */
  .bo-listtog { display: flex; align-items: center; gap: 4px; width: 100%; margin-top: 6px; padding: 4px 0;
    background: none; border: 0; color: var(--dim); font: inherit; font-size: 11.5px; text-align: left; cursor: pointer; }
  .bo-listtog:hover { color: var(--txt); }
  .bo-listtog .bo-chev { transition: transform .12s ease; }
  .bo-listtog.open .bo-chev { transform: rotate(90deg); }
  .bo-sub { display: flex; align-items: flex-start; gap: 8px; padding: 6px 7px 6px 8px; border-radius: 3px; }
  .bo-sub:hover { background: var(--hover); }
  .bo-sub .adot { margin-top: 4px; }
  /* inline branch-out card rows are single-line now → center the dot, drop the multi-line offset */
  .bo-subs .bo-sub { align-items: center; padding-left: 0; }
  .bo-subs .bo-sub .adot { margin-top: 0; }
  .bo-sub-meta { flex: 1; min-width: 0; }
  .bo-sub-top { display: flex; align-items: baseline; gap: 8px; }
  .bo-sub-name { flex: 1; min-width: 0; font-size: 12px; color: #e6e6e6; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .bo-sub-desc { font-size: 10.5px; color: var(--faint); line-height: 1.35; margin-top: 2px; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  /* live "what's going on" peek: the agent's latest output line, one line, ellipsised. */
  .bo-sub-live { font-size: 10.5px; color: var(--accent); opacity: .92; line-height: 1.35; margin-top: 3px; font-family: "SF Mono", ui-monospace, monospace; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .bo-sub .astatus { margin-top: 3px; }
  /* per-agent request count — how many queued requests this one agent took on */
  .bo-sub-model { flex: 0 0 auto; font-size: 11px; font-weight: 700; letter-spacing: .2px; color: var(--m-col, var(--muted)); background: color-mix(in srgb, var(--m-col, var(--muted)) 12%, transparent); border: 1px solid color-mix(in srgb, var(--m-col, var(--muted)) 35%, transparent); border-radius: 3px; padding: 2px 7px; white-space: nowrap; }
  .bo-sub-model.clk { cursor: pointer; }
  .bo-sub-model.clk:hover, .bo-sub-model.clk:focus-visible { background: color-mix(in srgb, var(--m-col, var(--muted)) 24%, transparent); outline: none; }
  .bo-sub-model.edited { box-shadow: 0 0 0 1px color-mix(in srgb, var(--m-col, var(--muted)) 60%, transparent); }
  .bo-sub-req { flex: 0 0 auto; font-size: 12.5px; font-weight: 800; letter-spacing: .3px; text-transform: uppercase; color: var(--bo-lt, var(--accent)); background: rgba(var(--bo-rgb, var(--accent-rgb)), .14); border: 1px solid rgba(var(--bo-rgb, var(--accent-rgb)), .3); border-radius: 3px; padding: 2px 9px; font-variant-numeric: tabular-nums; }
  /* pillar 2: per-branch verify verdict badge (✓ verified / ✗ failed / ⚠ unverified) */
  .bo-vbadge { flex: 0 0 auto; font-size: 9.5px; font-weight: 700; letter-spacing: .3px; text-transform: uppercase; border-radius: 3px; padding: 1px 6px; border: 1px solid; }
  .bo-vbadge.pass { color: #34c759; background: rgba(52,199,89,.13); border-color: rgba(52,199,89,.32); }
  .bo-vbadge.fail { color: #ff5c4d; background: rgba(255,92,77,.13); border-color: rgba(255,92,77,.34); }
  .bo-vbadge.unv  { color: #e0a44a; background: rgba(224,164,74,.13); border-color: rgba(224,164,74,.32); }
  /* verify summary on the Ready-to-test card */
  .q-bo-verify { margin-top: 7px; font-size: 11px; font-weight: 600; padding: 5px 8px; border-radius: 3px; border: 1px solid; }
  .q-bo-verify.pass { color: #34c759; background: rgba(52,199,89,.10); border-color: rgba(52,199,89,.28); }
  .q-bo-verify.fail { color: #ff5c4d; background: rgba(255,92,77,.10); border-color: rgba(255,92,77,.30); }
  .q-bo-verify.unv  { color: #e0a44a; background: rgba(224,164,74,.10); border-color: rgba(224,164,74,.28); }
  /* a group row is clickable → opens its task-list popup */
  .bo-sub.clk { cursor: pointer; }
  .bo-sub.clk:hover { background: var(--hover); }
  /* collapsible agent rows: chevron + that agent's requests nested as queue cards (John, 2026-09-18) */
  .bo-chev { flex: 0 0 auto; width: 10px; font-size: 15px; line-height: 1; color: var(--faint); transform: rotate(0deg); transition: transform .12s ease; }
  .bo-sub.open .bo-chev { transform: rotate(90deg); }
  .bo-sub-items { display: flex; flex-direction: column; gap: 6px; margin: 2px 0 8px; }
  .q-item.bo-nested { margin-bottom: 0; padding: 7px 9px 9px; cursor: default; }
  .q-item.bo-nested .q-text { cursor: default; }
  .q-item.bo-nested .q-model { cursor: default; }
  .q-item.bo-nested.done { opacity: .62; }
  .q-item.bo-nested.active { border-color: rgba(var(--bo-rgb, var(--accent-rgb)), .55); }
  .q-item.bo-nested.error { border-color: rgba(255,92,77,.5); }
  .q-status { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; font-size: 10px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; border-radius: 3px; padding: 2px 7px; border: 1px solid; }
  .q-status.wait { color: var(--faint); border-color: var(--line); }
  .q-status.active { color: var(--bo-lt, var(--accent)); background: rgba(var(--bo-rgb, var(--accent-rgb)), .14); border-color: rgba(var(--bo-rgb, var(--accent-rgb)), .35); }
  .q-status.done { color: #34c759; background: rgba(52,199,89,.13); border-color: rgba(52,199,89,.32); }
  .q-status.error { color: #ff5c4d; background: rgba(255,92,77,.13); border-color: rgba(255,92,77,.34); }
  .q-status .q-bo-spin { width: 9px; height: 9px; }
  /* ---- branch-out per-agent task-list popup ---- */
  .bo-tasks-pop {
    position: fixed; z-index: 62; max-width: 340px; min-width: 220px;
    background: var(--panel); border: 1px solid var(--line); border-left: 2px solid var(--accent);
    border-radius: 3px; padding: 8px; box-shadow: 0 12px 30px rgba(0,0,0,var(--sh50, .5));
    font-family: var(--ui-font);
  }
  .btp-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 2px 4px 7px; border-bottom: 1px solid var(--line); margin-bottom: 5px; }
  .btp-title { font-size: 12px; font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
  .btp-count { flex: 0 0 auto; font-size: 10px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
  .btp-list { display: flex; flex-direction: column; gap: 1px; max-height: 300px; overflow-y: auto; }
  .btp-task { display: flex; align-items: flex-start; gap: 8px; padding: 5px 6px; border-radius: 3px; font-size: 12px; line-height: 1.35; }
  .btp-mark { flex: 0 0 16px; width: 16px; text-align: center; font-size: 11px; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; }
  .btp-text { flex: 1; min-width: 0; color: var(--text); overflow-wrap: anywhere; }
  .btp-task.done .btp-mark { color: #4ea1ff; }
  .btp-task.done .btp-text { color: var(--muted); }
  .btp-task.active { background: rgba(var(--accent-rgb), .12); }
  .btp-task.active .btp-mark { color: var(--accent); }
  .btp-task.active .btp-text { color: var(--text); font-weight: 600; }
  .btp-task.wait .btp-text { color: var(--muted); }
  .btp-empty { font-size: 12px; color: var(--muted); padding: 6px; }
  /* pillar 3: reviewer findings inside the agent's task popup */
  .btp-review { margin-top: 7px; padding: 6px 7px; border-radius: 3px; font-size: 11.5px; font-weight: 600; }
  .btp-review.clean { color: #34c759; background: rgba(52,199,89,.10); }
  .btp-review-head { margin-top: 8px; margin-bottom: 3px; padding: 5px 6px; border-radius: 3px; font-size: 11.5px; font-weight: 700; color: #ff5c4d; background: rgba(255,92,77,.10); border: 1px solid rgba(255,92,77,.24); }
  .btp-find { display: flex; align-items: flex-start; gap: 7px; padding: 5px 6px; border-radius: 3px; font-size: 12px; line-height: 1.35; }
  .btp-sev { flex: 0 0 auto; font-size: 9px; font-weight: 800; letter-spacing: .4px; padding: 1px 5px; border-radius: 3px; margin-top: 1px; }
  .btp-find.high .btp-sev { color: #ff5c4d; background: rgba(255,92,77,.16); }
  .btp-find.med  .btp-sev { color: #e0a44a; background: rgba(224,164,74,.16); }
  .btp-find.low  .btp-sev { color: var(--muted); background: rgba(150,150,150,.14); }
  .btp-find-txt { flex: 1; min-width: 0; color: var(--text); overflow-wrap: anywhere; }
  .btp-find-loc { display: block; font-family: "SF Mono", ui-monospace, monospace; font-size: 10px; color: var(--muted); margin-top: 1px; overflow-wrap: anywhere; }
  /* pillar 3: review flag chip on the group row + roll-up on the Ready-to-test card */
  .bo-rbadge { flex: 0 0 auto; font-size: 9.5px; font-weight: 800; letter-spacing: .3px; border-radius: 3px; padding: 1px 6px; color: #ff5c4d; background: rgba(255,92,77,.14); border: 1px solid rgba(255,92,77,.34); font-variant-numeric: tabular-nums; }
  .q-bo-review { margin-top: 7px; font-size: 11px; font-weight: 600; padding: 5px 8px; border-radius: 3px; border: 1px solid; }
  .q-bo-review.clean  { color: #34c759; background: rgba(52,199,89,.10); border-color: rgba(52,199,89,.26); }
  .q-bo-review.issues { color: #ff5c4d; background: rgba(255,92,77,.10); border-color: rgba(255,92,77,.30); }
  /* MC Optimization Function: gold/orange so it reads as advisory, distinct from red review */
  .btp-opt { margin-top: 7px; padding: 6px 7px; border-radius: 3px; font-size: 11.5px; font-weight: 600; }
  .btp-opt.clean { color: #34c759; background: rgba(52,199,89,.10); }
  .btp-review-head.opt { color: var(--accent, #ff6a44); background: rgba(var(--accent-rgb),.10); border-color: rgba(var(--accent-rgb),.26); }
  .btp-sev.opt { color: #e0a44a; background: rgba(224,164,74,.16); }
  .btp-sev.opt.optimize { color: var(--accent, #ff6a44); background: rgba(var(--accent-rgb),.16); }
  .btp-find.opt-adv .btp-find-txt { color: var(--muted); }
  .btp-opt-tag { display: inline-block; font-size: 9.5px; font-weight: 700; letter-spacing: .3px; text-transform: uppercase; color: #e0a44a; background: rgba(224,164,74,.14); border-radius: 3px; padding: 0 5px; margin-left: 4px; }
  .btp-opt-fix { display: block; font-size: 11px; color: var(--text); opacity: .82; margin-top: 2px; overflow-wrap: anywhere; }
  /* MC #5: one-tap apply on an optimization finding */
  .btp-opt-apply { flex: none; align-self: flex-start; margin-left: 6px; font: inherit; font-size: 10.5px; font-weight: 700; color: var(--accent); background: rgba(255, 106, 68,.12); border: 1px solid rgba(255, 106, 68,.35); border-radius: 3px; padding: 1px 8px; cursor: pointer; }
  .btp-opt-apply:hover { background: rgba(255, 106, 68,.22); }
  .btp-opt-applied { flex: none; align-self: flex-start; margin-left: 6px; font-size: 10.5px; font-weight: 700; color: #6fd18c; }
  .bo-obadge { flex: 0 0 auto; font-size: 9.5px; font-weight: 800; letter-spacing: .3px; border-radius: 3px; padding: 1px 6px; color: var(--accent, #ff6a44); background: rgba(var(--accent-rgb),.14); border: 1px solid rgba(var(--accent-rgb),.34); font-variant-numeric: tabular-nums; }
  .q-bo-review.opt { color: var(--accent, #ff6a44); background: rgba(var(--accent-rgb),.10); border-color: rgba(var(--accent-rgb),.30); }
  .q-bo-review.opt.clean { color: #34c759; background: rgba(52,199,89,.10); border-color: rgba(52,199,89,.26); }
  /* AUDIT FIX O-H1: a failed/skipped optimization pass reads as a WARNING, never a clean ✓. */
  .q-bo-review.opt.err { color: #e0a44a; background: rgba(224,164,74,.10); border-color: rgba(224,164,74,.30); }
  .btp-opt.err { color: #e0a44a; background: rgba(224,164,74,.10); }
  .bo-obadge.err { color: #e0a44a; background: rgba(224,164,74,.14); border-color: rgba(224,164,74,.34); }
  /* pillar 1: best-of-N judge-ranked approaches list */
  .vr-list { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
  .vr-row { display: flex; align-items: flex-start; gap: 9px; padding: 8px 9px; border-radius: 3px; background: var(--panel-2, #161616); border: 1px solid var(--line); }
  .vr-row.win { border-color: rgba(var(--accent-rgb), .5); background: rgba(var(--accent-rgb), .08); }
  .vr-rank { flex: 0 0 auto; width: 22px; text-align: center; font-size: 13px; font-weight: 800; color: var(--muted); font-variant-numeric: tabular-nums; }
  .vr-row.win .vr-rank { font-size: 15px; }
  .vr-meta { flex: 1; min-width: 0; }
  .vr-top { display: flex; align-items: center; gap: 6px; }
  .vr-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 700; color: var(--text); }
  .vr-score { flex: 0 0 auto; font-size: 10px; font-weight: 800; color: var(--accent); background: rgba(var(--accent-rgb), .14); border-radius: 3px; padding: 1px 7px; font-variant-numeric: tabular-nums; }
  .vr-why { font-size: 11px; color: var(--muted); line-height: 1.35; margin-top: 2px; overflow-wrap: anywhere; }
  /* pillar 8: fleet token-spend bar + budget */
  .bo-spend { margin: 8px 0 4px; }
  .bo-spend-top { display: flex; justify-content: space-between; gap: 8px; font-size: 10.5px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
  .bo-spend-bar { margin-top: 4px; height: 4px; border-radius: 3px; background: rgba(150,150,150,.18); overflow: hidden; }
  .bo-spend-fill { height: 100%; border-radius: 3px; background: var(--accent); transition: width .3s ease; }
  .bo-spend.near .bo-spend-fill { background: #e0a44a; }
  .bo-spend.over .bo-spend-fill { background: #ff5c4d; }
  .bo-spend.near .bo-spend-top, .bo-spend.over .bo-spend-top { color: #e0a44a; }
  .bo-spend.over .bo-spend-top { color: #ff5c4d; }
  .bo-spend-note { margin-top: 4px; font-size: 10.5px; font-weight: 600; color: #ff5c4d; }
  /* pillar 7: retry-one-agent button on an errored group row */
  .bo-retry { flex: 0 0 auto; border: 1px solid rgba(var(--accent-rgb), .4); background: rgba(var(--accent-rgb), .12); color: var(--accent); font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 3px; cursor: pointer; align-self: center; }
  .bo-retry:hover { background: rgba(var(--accent-rgb), .24); }
  .bo-retry:disabled { opacity: .5; cursor: default; }
  /* ---- THE BIG MOMENT: N sub-agents ✕ M requests, in parallel ---- */
  .bo-hero {
    position: relative;
    /* 2×1 block: each stat gets its own equal half (1fr) and centers inside it, with
       the ✕ in the middle auto column. (Flex+justify-center used to pull both numbers
       toward the ✕ instead of centering each in its own half.) */
    display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 14px;
    margin: 11px 0 4px; padding: 14px 10px; border-radius: 3px;
    background: linear-gradient(135deg, rgba(var(--bo-rgb), .18), rgba(var(--bo-rgb), .05));
    border: 1px solid rgba(var(--bo-rgb), .38);
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.02);
  }
  .bo-hero.done { animation: none; background: linear-gradient(135deg, rgba(69,227,176,.13), rgba(69,227,176,.03)); border-color: rgba(69,227,176,.34); box-shadow: none; }
  .bo-hero-stat { display: flex; flex-direction: column; align-items: center; line-height: 1; }
  .bo-hero-n { font-size: 26px; font-weight: 800; color: var(--bo-txt, var(--text)); font-variant-numeric: tabular-nums; letter-spacing: -.5px; }
  .bo-hero.done .bo-hero-n { color: #45e3b0; }
  .bo-hero-lab { font-size: 9.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: color-mix(in srgb, var(--bo-txt, var(--text)) 80%, transparent); margin-top: 4px; white-space: nowrap; }
  .bo-hero.done .bo-hero-lab { color: color-mix(in srgb, #45e3b0 85%, var(--text)); }
  .bo-hero-x { font-size: 13px; font-weight: 700; color: var(--faint); opacity: .7; }
  /* Narrow queue panel (John drags it thin): the horizontal "7 ✕ 3" band no longer
     fits — labels used to wrap and the band overflowed + got clipped by the card's
     overflow:hidden, so it read as off-center/weird. The panel is a size container
     (container-type: inline-size on .pane-queue), so below ~250px we STACK the two
     stats vertically, drop the ✕, and everything stays centered and un-clipped. */
  @container (max-width: 250px) {
    .bo-hero { grid-template-columns: 1fr; gap: 6px; padding: 14px 8px; }
    .bo-hero-x { display: none; }
  }
  @keyframes boHeroIn { from { opacity: 0; transform: translateY(-6px) scale(.96); } to { opacity: 1; transform: none; } }
  .bo-cancel { margin-top: 10px; width: 100%; background: transparent; border: 1px solid var(--line); color: var(--muted); border-radius: 3px; padding: 6px 10px; font-size: 11.5px; cursor: pointer; }
  .bo-cancel:hover:not(:disabled) { color: #e5484d; border-color: rgba(229,72,77,.5); background: rgba(229,72,77,.08); }
  .bo-cancel:disabled { opacity: .6; cursor: default; }
  /* ---- branch-out RECAP card: persistent outcome, dropped into the transcript ---- */
  /* Branch-out recap — "Option A" layout (stat tiles + branch ledger), in brand GOLD.
     Signature colour is the app's --bo gold; success stays green + conflict amber as
     semantic status colours (a merged branch reads green, a conflict reads amber). */
  /* SAME CARD LANGUAGE AS THE LIVE BRANCH-OUT CARD (.q-bo) — John, 2026-09-06: "those colors
     are horrible, padding also is pretty bad, follow the design of the branch out card".
     No fill, no box, no gradients, no gold spine, no shadow: one accent rail on the left,
     the same 12/14/13 padding, the same 12px type. Wears the accent (list above), not raw gold. */
  .bo-recap-card {
    align-self: stretch; width: 100%; box-sizing: border-box; position: relative; overflow: hidden;
    background: transparent;
    border: none; border-left: 2px solid rgba(var(--bo-rgb), .45); border-radius: 3px;
    padding: 12px 14px 13px; font-size: 12px; color: var(--text); box-shadow: none;
  }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .bo-recap-card { box-shadow: none; }
  .bo-recap-card::before { content: none; }
  /* header: glyph + title/sub + status badge */
  .bo-recap-head { display: flex; align-items: center; gap: 9px; padding-bottom: 9px; border-bottom: 1px solid var(--line); }
  .bo-recap-glyph { width: 15px; height: 15px; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; background: none; box-shadow: none; color: var(--bo-lt); }
  .bo-recap-glyph svg { width: 14px; height: 14px; color: var(--bo-lt); }
  .bo-recap-htxt { min-width: 0; flex: 1; }
  .bo-recap-title { font-weight: 700; font-size: 12px; letter-spacing: .2px; color: var(--text); }
  .bo-recap-sub { margin-top: 1px; font-size: 10.5px; line-height: 1.4; color: var(--faint); overflow-wrap: anywhere; }
  .bo-recap-sub b { color: var(--bo-txt); font-weight: 650; }
  /* success badge reads green (matches the merged tile); conflicts flip it amber */
  .bo-recap-badge { flex: 0 0 auto; align-self: center; font-size: 10px; font-weight: 650; letter-spacing: .2px; padding: 2px 8px;
    border-radius: 3px; background: rgba(69,227,176,.12); color: #45e3b0;
    border: 1px solid rgba(126,224,168,.3); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .bo-recap-badge.warn { background: rgba(224, 160, 74, .14); color: #e0a04a; border-color: rgba(224, 160, 74, .4); }
  /* stat tiles — neutral surrounds so the green "merged" tile carries the eye */
  .bo-recap-stats { display: flex; gap: 0; margin: 11px 0 4px; padding: 14px 10px; border-radius: 3px;
    background: linear-gradient(135deg, rgba(var(--bo-rgb), .18), rgba(var(--bo-rgb), .05)); border: 1px solid rgba(var(--bo-rgb), .38); }
  .bo-recap-stat { flex: 1; min-width: 0; background: none; border: none; padding: 0; text-align: center; display: flex; flex-direction: column; align-items: center; line-height: 1; }
  .bo-recap-stat .n { font-size: 26px; font-weight: 800; line-height: 1; letter-spacing: -.5px; font-variant-numeric: tabular-nums; color: var(--bo-txt, var(--text)); }
  .bo-recap-stat .l { margin-top: 4px; font-size: 9.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--text); white-space: nowrap; }
  .bo-recap-stat.good .n { color: #45e3b0; }
  .bo-recap-stat.warn .n { color: #e0a04a; }
  /* branch field row */
  /* Card actions: Merge (accent-tinted, like the Branch out button) + Discard (neutral, red on hover). */
  .bo-recap-actions { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
  .bo-recap-act { flex: 0 0 auto; border-radius: 3px; padding: 5px 11px; font-size: 11.5px; font-weight: 700; cursor: pointer; }
  .bo-recap-act.merge { background: rgba(var(--bo-rgb), .14); color: var(--bo-txt); border: 1px solid rgba(var(--bo-rgb), .5); }
  .bo-recap-act.merge:hover:not(:disabled) { background: rgba(var(--bo-rgb), .24); border-color: rgba(var(--bo-rgb), .7); }
  .bo-recap-act.discard { background: transparent; border: 1px solid var(--line); color: var(--muted); font-weight: 600; }
  .bo-recap-act.discard:hover:not(:disabled) { color: #e5484d; border-color: rgba(229,72,77,.5); background: rgba(229,72,77,.08); }
  .bo-recap-act:disabled { opacity: .6; cursor: default; }
  .bo-recap-act-msg { flex: 1 1 100%; min-width: 0; font-size: 11px; color: #e0a04a; line-height: 1.4; overflow-wrap: anywhere; }
  .bo-recap-act-msg:empty { display: none; }
  .bo-recap-actions .bo-recap-line { margin-top: 0; }
  .bo-recap-branch { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
  .bo-recap-k { font-size: 10px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--bo-lt); flex: 0 0 auto; }
  .bo-recap-branch code { flex: 1; min-width: 0; font-family: "SF Mono", ui-monospace, monospace; font-size: 12px; color: var(--bo-txt); background: rgba(var(--bo-rgb), .08); border: 1px solid rgba(var(--bo-rgb), .26); border-radius: 3px; padding: 6px 8px; font-size: 10.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .bo-recap-copy { flex: 0 0 auto; align-self: stretch; background: rgba(var(--bo-rgb), .1); border: 1px solid rgba(var(--bo-rgb), .32); color: var(--bo-txt); border-radius: 3px; padding: 4px 10px; font-size: 10.5px; font-weight: 600; cursor: pointer; }
  .bo-recap-copy:hover { border-color: rgba(var(--bo-rgb), .6); background: rgba(var(--bo-rgb), .2); }
  /* branch ledger */
  .bo-recap-ledgerh { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; margin-bottom: 4px; }
  .bo-recap-ledgerh .lt { font-size: 10.5px; font-weight: 700; letter-spacing: .7px; text-transform: uppercase; color: var(--faint); }
  .bo-recap-ledger { border: 1px solid rgba(var(--bo-rgb), .15); border-radius: 3px; overflow: hidden; }
  .bo-recap-brow { display: flex; align-items: center; gap: 11px; padding: 10px 13px; border-top: 1px solid rgba(var(--bo-rgb), .10); }
  .bo-recap-brow:first-child { border-top: none; }
  .bo-recap-brow:hover { background: rgba(var(--bo-rgb), .05); }
  .bo-recap-dot { width: 16px; height: 16px; flex: 0 0 auto; border-radius: 50%; display: grid; place-items: center; background: rgba(126,224,168,.16); }
  .bo-recap-dot svg { width: 9px; height: 9px; color: #7ee0a8; }
  .bo-recap-dot.warn { background: rgba(224,160,74,.16); } .bo-recap-dot.warn svg { color: #e0a04a; }
  .bo-recap-bmid { flex: 1; min-width: 0; }
  .bo-recap-bname { font-size: 12.5px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .bo-recap-bmeta { margin-top: 2px; font-size: 10.5px; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .bo-recap-btag { flex: 0 0 auto; font-size: 10px; font-weight: 650; padding: 2px 8px; border-radius: 3px; background: rgba(126,224,168,.12); color: #7ee0a8; border: 1px solid rgba(126,224,168,.25); white-space: nowrap; }
  .bo-recap-btag.warn { background: rgba(224,160,74,.12); color: #e0a04a; border-color: rgba(224,160,74,.28); }
  .bo-recap-more { padding: 9px 13px; border-top: 1px solid rgba(var(--bo-rgb), .10); font-size: 11px; color: var(--bo-lt); text-align: center; }
  /* keep the legacy single-line variants working (used before groups data lands) */
  .bo-recap-line { margin-top: 8px; font-size: 11.5px; line-height: 1.45; color: var(--muted); overflow-wrap: anywhere; }
  .bo-recap-line.ok { color: #45e3b0; font-weight: 600; } .bo-recap-line.warn { color: #e0a04a; }
  .bo-recap-hint { color: var(--faint); }
  /* footer */
  .bo-recap-foot { display: flex; align-items: center; gap: 8px; margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--line); font-size: 10.5px; color: var(--faint); line-height: 1.4; }
  .bo-recap-foot code { font-size: 10.5px; }
  .bo-recap-shield { width: 12px; height: 12px; color: #45e3b0; opacity: .8; flex: 0 0 auto; }
  .bo-recap-foot code { font-family: "SF Mono", ui-monospace, monospace; color: var(--bo-lt); }
  .composer button { background: var(--accent); color: var(--on-accent); border: none; border-radius: 3px; width: 36px; height: 36px; font-size: 16px; cursor: pointer; flex: 0 0 auto; font-weight: 700; }
  .composer button:disabled { opacity: .4; cursor: default; }
  /* the orange button: small send arrow, or a mic when the composer is empty */
  .composer .psend { width: 28px; height: 28px; border-radius: 3px; font-size: 13px; display: inline-flex; align-items: center; justify-content: center; }
  .composer .psend.recording { animation: micpulse 1.1s ease-in-out infinite; }
  .composer .psend.busy { opacity: .5; }   /* transcribing */
  /* Voice dictation status pill — floats above the composer so there's a clear
     signal that push-to-talk is listening / transcribing (was: no feedback). */
  .pane-composer { position: relative; }
  /* THE DICTATION BAR (John, 2026-08-17: "something minimal, keep the sound wave,
     something above the input in a larger chip style. Black background"). This replaces
     the top-of-screen notch for local dictation — see the note on voiceStatus() in
     renderer.js for why an in-pane element fixes the "Fn leaves the app" bug outright.
     Full-width above the composer, near-black, with the live waveform as the centrepiece. */
  .voice-status {
    display: none; position: absolute; left: 10px; right: 10px; bottom: calc(100% + 8px); z-index: 8;
    align-items: center; gap: 12px;
    padding: 10px 14px; border-radius: 3px; font-size: 12px; font-weight: 600; letter-spacing: .2px;
    color: var(--accent); background: var(--panel-2);
    border: 1px solid rgba(var(--accent-rgb),.34);
    box-shadow: 0 6px 16px rgba(0,0,0,var(--sh30, .3));
    white-space: nowrap; pointer-events: none;
  }
  .voice-status.show { display: flex; }
  .voice-status .vs-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex-shrink: 0; animation: micpulse 1.1s ease-in-out infinite; }
  .voice-status.busy .vs-dot { animation: micpulse .7s ease-in-out infinite; }
  /* The waveform takes the free space — it's the point of the bar. */
  .vs-wave { flex: 1 1 auto; min-width: 0; height: 26px; display: block; }
  .voice-status.busy .vs-wave { opacity: .35; }   /* transcribing: nothing live to draw */
  .voice-status .vs-label { flex: 0 0 auto; overflow: hidden; text-overflow: ellipsis; }
  /* The little ✕ that cancels dictation. Parent chip is pointer-events:none, so the
     button explicitly re-enables clicks. Hidden while transcribing — nothing to cancel. */
  .voice-status .vs-x {
    pointer-events: auto; cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
    width: 16px; height: 16px; margin-left: 1px; margin-right: -3px; padding: 0; flex-shrink: 0;
    border: none; border-radius: 50%; background: rgba(var(--accent-rgb),.18); color: var(--accent);
    font-size: 10px; line-height: 1; transition: background .12s ease;
  }
  .voice-status .vs-x:hover { background: rgba(var(--accent-rgb),.4); }
  /* Keep the ✕ available WHILE transcribing (John, 2026-08-27) so a pending transcription
     can be cancelled from the bar, not only while listening. */
  /* While dictating, the pill floats over the bottom of the transcript and ghosts
     over the trailing "Done · … tokens" line — mute that line so the pill is clean.
     visibility:hidden keeps its space so the transcript doesn't jump. */
  .done.vs-mute, .think-row.vs-mute { visibility: hidden; }
  .composer textarea.dictating { cursor: default; }

  /* BETA: Live-conversation entry button in the composer — a subtle ghost button,
     only visible when the beta is on AND the composer is empty (mic mode). */
  .composer .pvoice { display: none; background: transparent; color: var(--muted); width: 28px; height: 28px; border-radius: 3px; align-items: center; justify-content: center; }
  .composer .pvoice:hover { color: var(--accent); background: var(--hover); }
  /* Conversational (Live voice) hidden for now, John 2026-08-15 — was: body.live-voice-on .composer.mic-mode .pvoice { display: inline-flex; } */
  body.live-voice-on .composer.mic-mode .pvoice { display: none; }

  /* ===== Live conversation (voice mode) full-screen overlay ===== */
  .voice-overlay {
    position: fixed; inset: 0; z-index: 1200; display: none; flex-direction: column;
    background: radial-gradient(120% 90% at 50% 16%, #17110c 0%, var(--bg) 62%);
  }
  /* Conversation-mode reactive glyph field — flat orange-on-black shapes that bloom from
     the center with your voice (replaces the old orb). Full-bleed background; the text
     and controls layer above it. */
  .vo-field { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; cursor: pointer; background: #000; }
  .voice-overlay .vo-bar, .voice-overlay .vo-center, .voice-overlay .vo-foot { position: relative; z-index: 1; }
  .voice-overlay .vo-status, .voice-overlay .vo-said, .voice-overlay .vo-reply { text-shadow: none; }
  .voice-overlay.show { display: flex; animation: voFade .22s ease; }
  @keyframes voFade { from { opacity: 0; } to { opacity: 1; } }
  .vo-bar { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; padding: 14px 18px; -webkit-app-region: drag; }
  .vo-bar button { -webkit-app-region: no-drag; }
  .vo-x, .vo-mute { width: 40px; height: 40px; border: none; background: transparent; color: var(--text); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; border-radius: 3px; font-size: 19px; }
  .vo-x:hover, .vo-mute:hover { background: var(--hover); }
  .vo-title { font-size: 12px; letter-spacing: .18em; text-transform: uppercase; color: var(--muted); }
  .vo-mute .vo-mute-off { display: none; }
  .voice-overlay.muted .vo-mute .vo-mute-on { display: none; }
  .voice-overlay.muted .vo-mute .vo-mute-off { display: inline; }
  .vo-center { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 30px; padding: 0 40px; text-align: center; }
  /* --lvl (0..1) is a live "loudness" set by JS: mic RMS while you talk, TTS word
     beats while the AI talks. It drives the reactive scale so the orb moves WITH sound.
     Volume-scale lives on .vo-core; the per-phase "personality" keyframes live on the
     nested .vo-skin, so the two transforms multiply and never fight each other. */
  .vo-orb { position: relative; width: 200px; height: 200px; flex: 0 0 auto; cursor: pointer; --lvl: 0; }
  .vo-halo { position: absolute; inset: -16px; border-radius: 50%; pointer-events: none; background: radial-gradient(circle, color-mix(in srgb, var(--accent) 34%, transparent) 0%, transparent 68%); opacity: .4; filter: blur(5px); transform: scale(calc(1 + var(--lvl) * .5)); transition: transform .12s ease-out, opacity .3s ease; }
  .vo-core { position: absolute; inset: 42px; border-radius: 50%; transform: scale(calc(1 + var(--lvl) * .24)); transition: transform .09s ease-out; }
  .vo-skin { position: absolute; inset: 0; border-radius: 50%; background: radial-gradient(circle at 38% 32%, #ff8a3d, var(--accent) 62%, #b8390a 100%); box-shadow: none; }
  .vo-gloss { position: absolute; inset: 0; border-radius: 50%; pointer-events: none; background: radial-gradient(circle at 34% 26%, rgba(255,255,255,.5), transparent 44%); }
  .vo-ring { position: absolute; inset: 0; border-radius: 50%; border: 2px solid color-mix(in srgb, var(--accent) 34%, transparent); opacity: 0; pointer-events: none; }
  .vo-orbit { position: absolute; inset: 0; opacity: 0; pointer-events: none; }
  .vo-orbit i { position: absolute; top: 50%; left: 50%; width: 10px; height: 10px; margin: -5px; border-radius: 50%; background: var(--accent); box-shadow: none; }
  .vo-orbit i:nth-child(1) { transform: rotate(0deg)   translateX(86px); }
  .vo-orbit i:nth-child(2) { transform: rotate(120deg) translateX(86px); }
  .vo-orbit i:nth-child(3) { transform: rotate(240deg) translateX(86px); }

  /* CONNECTING — slow warm-up breathe + one faint sweeping ring */
  .voice-overlay[data-phase="connecting"] .vo-skin  { animation: voBreathe 2.4s ease-in-out infinite; }
  .voice-overlay[data-phase="connecting"] .vo-ring1 { animation: voPulse 2.6s ease-out infinite; }

  /* LISTENING (you speak) — orb scales to your voice; rings ripple outward */
  .voice-overlay[data-phase="listening"] .vo-skin  { box-shadow: none; animation: voBreathe 2s ease-in-out infinite; }
  .voice-overlay[data-phase="listening"] .vo-ring1 { animation: voPulse 2s ease-out infinite; }
  .voice-overlay[data-phase="listening"] .vo-ring2 { animation: voPulse 2s ease-out infinite .66s; }
  .voice-overlay[data-phase="listening"] .vo-ring3 { animation: voPulse 2s ease-out infinite 1.33s; }

  /* THINKING (AI reasoning) — core contracts & glows, dots orbit, dashed ring drifts */
  .voice-overlay[data-phase="thinking"] .vo-skin  { animation: voThink 1.1s ease-in-out infinite; }
  .voice-overlay[data-phase="thinking"] .vo-orbit { opacity: 1; animation: voSpin 2.4s linear infinite; }
  .voice-overlay[data-phase="thinking"] .vo-ring1 { opacity: .4; border-style: dashed; animation: voSpin 6s linear infinite reverse; }

  /* CREATING (AI actively making something — tool use) — energetic counter-rotating
     rings, fast orbit, brighter shimmer. Deliberately busier than THINKING. */
  .voice-overlay[data-phase="creating"] .vo-skin  { animation: voForge .7s ease-in-out infinite; box-shadow: none; }
  .voice-overlay[data-phase="creating"] .vo-halo  { opacity: .7; }
  .voice-overlay[data-phase="creating"] .vo-orbit { opacity: 1; animation: voSpin 1.1s linear infinite; }
  .voice-overlay[data-phase="creating"] .vo-ring1 { opacity: .6; animation: voSpin 1.6s linear infinite; }
  .voice-overlay[data-phase="creating"] .vo-ring2 { opacity: .4; border-style: dashed; animation: voSpin 2.2s linear infinite reverse; }

  /* SPEAKING (AI speaks) — pulses on each spoken word (--lvl beats), warm rings */
  .voice-overlay[data-phase="speaking"] .vo-skin  { animation: voBreathe 2.2s ease-in-out infinite; box-shadow: none; }
  .voice-overlay[data-phase="speaking"] .vo-ring1 { animation: voPulse 1.8s ease-out infinite; }
  .voice-overlay[data-phase="speaking"] .vo-ring2 { animation: voPulse 1.8s ease-out infinite .9s; }

  /* IDLE — dim, dormant, barely breathing */
  .voice-overlay[data-phase="idle"] .vo-skin { filter: saturate(.6) brightness(.8); box-shadow: none; animation: voBreathe 4s ease-in-out infinite; }

  /* ERROR — red tint, brief shudder, then settle */
  .voice-overlay[data-phase="error"] .vo-skin { background: radial-gradient(circle at 38% 32%, #ff6a5a, #d33a2a 60%, #7a1c12 100%); box-shadow: none; animation: voShake .5s ease-in-out 2; }

  @keyframes voBreathe { 0%,100% { transform: scale(1); } 50% { transform: scale(1.06); } }
  @keyframes voThink   { 0%,100% { transform: scale(.94); } 50% { transform: scale(1.04); } }
  @keyframes voForge   { 0%,100% { transform: scale(.97) rotate(0deg); } 50% { transform: scale(1.06) rotate(3deg); } }
  @keyframes voPulse   { 0% { transform: scale(.7); opacity: .6; } 100% { transform: scale(1.3); opacity: 0; } }
  @keyframes voSpin    { to { transform: rotate(360deg); } }
  @keyframes voShake   { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }
  .vo-status { font-size: 15px; color: var(--muted); min-height: 20px; font-weight: 500; }
  .vo-said { font-size: 21px; line-height: 1.35; color: var(--text); max-width: 640px; overflow-wrap: anywhere; }
  .vo-reply { font-size: 17px; line-height: 1.45; color: var(--text); opacity: .92; max-width: 640px; overflow-wrap: anywhere; max-height: 34vh; overflow-y: auto; }
  .vo-foot { flex: 0 0 auto; padding: 16px 18px 26px; display: flex; justify-content: center; }
  .vo-type-toggle { background: transparent; border: 1px solid var(--line); color: var(--muted); border-radius: 3px; padding: 10px 22px; font-size: 14px; cursor: pointer; }
  .vo-type-toggle:hover { color: var(--text); background: var(--hover); }
  .vo-typebar { display: flex; align-items: center; gap: 9px; width: 100%; max-width: 640px; }
  .vo-input { flex: 1 1 auto; min-width: 0; height: 44px; border: 1px solid var(--line); background: var(--panel-2, var(--panel)); color: var(--text); border-radius: 3px; padding: 0 16px; font-size: 15px; outline: none; }
  .vo-input:focus { border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
  .vo-send, .vo-back-voice { flex: 0 0 auto; width: 44px; height: 44px; border: none; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
  .vo-send { background: var(--accent); color: #fff; }
  .vo-back-voice { background: transparent; color: var(--muted); }
  .vo-back-voice:hover { color: var(--text); background: var(--hover); }

  /* Blocking dialogs (confirm/prompt) sit above EVERY surface that can spawn them: the
     Manage-team modal (9600) and the sign-in gates (.pw-overlay / #cc-overlay at 9999).
     At 9990 the two-step verification prompt opened BEHIND the sign-in gate, so an account
     with an authenticator code saw "nothing happen" after Google (John, 2026-09-20). */
  .overlay { position: fixed; inset: 0; background: rgba(0,0,0,.55); display: none; align-items: center; justify-content: center; z-index: 10010; }
  .overlay.show { display: flex; }
  .modal { background: var(--panel); border: 1px solid var(--line); border-radius: 3px; padding: 22px; width: 470px; max-width: 90vw; }
  .modal h3 { margin-bottom: 6px; font-size: 15px; }
  .modal p { color: var(--muted); font-size: 12.5px; margin-bottom: 14px; line-height: 1.5; }

  /* ---- "Which one should I use?" (the model picker's Help row) -------------
     A near-full-window sheet (John asked for ~90%): the whole point is seeing
     every connected model side by side, which a 470px modal cannot do. Width
     and height are both overridden off the base .modal rule above. */
  .modal.model-guide {
    width: 90vw; height: 90vh; max-width: 1100px; padding: 0;
    display: flex; flex-direction: column; overflow: hidden;
  }
  .mg-head { display: flex; align-items: center; justify-content: space-between; padding: 20px 24px 0; }
  .mg-head h3 { margin: 0; font-size: 17px; }
  .mg-close { background: none; border: none; color: var(--muted); font-size: 22px; line-height: 1; cursor: pointer; padding: 0 4px; }
  .mg-close:hover { color: var(--text); }
  .modal.model-guide .mg-lede { padding: 6px 24px 0; margin: 0 0 12px; }
  /* THE RECOMMENDATION. One obvious default above the grid so nobody has to
     compare twenty cards before doing anything (John, 2026-08-26). */
  .mg-start { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
    margin: 0 24px 14px; padding: 11px 14px; width: calc(100% - 48px);
    background: var(--panel-2, rgba(255,255,255,.04)); border: 1px solid var(--line, rgba(255,255,255,.10));
    border-radius: 10px; cursor: pointer; text-align: left; font: inherit; }
  .mg-start:hover { border-color: rgba(255,255,255,.22); }
  .mg-start-lab { color: var(--muted); font-size: 12.5px; }
  .mg-start-name { font-weight: 700; font-size: 13.5px; }
  .mg-start-why { color: var(--muted); font-size: 12.5px; }
  .mg-start-why::before { content: '· '; }
  /* Task filters: turn browsing into lookup. */
  .mg-filters { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 24px; margin-bottom: 14px; }
  .mg-filter { font: inherit; font-size: 12px; line-height: 1; padding: 7px 11px; border-radius: 999px;
    background: transparent; color: var(--muted); border: 1px solid var(--line, rgba(255,255,255,.10)); cursor: pointer; }
  .mg-filter:hover { color: var(--text); border-color: rgba(255,255,255,.22); }
  .mg-filter.on { background: var(--text); color: var(--bg, #101114); border-color: var(--text); font-weight: 600; }
  .mg-scroll { flex: 1; overflow-y: auto; padding: 0 24px 24px; }
  .mg-sec { margin-bottom: 22px; }
  .mg-sec-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
  .mg-sec-name { font-size: 12px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; }   /* company, capped — same rule as .row-menu-header */
  .mg-sec-sub { color: var(--muted); font-size: 12px; }
  /* auto-fit so two connected engines don't leave a half-empty row */
  .mg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
  .mg-card {
    display: flex; gap: 0; text-align: left; cursor: pointer; overflow: hidden;
    background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 0;
  }
  .mg-card:hover { border-color: var(--muted); }
  .mg-card.current { border-color: var(--accent); }
  .mg-bar { width: 3px; flex: none; align-self: stretch; }   /* the model's own tone, same legend as the picker */
  .mg-body { display: flex; flex-direction: column; gap: 4px; padding: 11px 13px; }
  .mg-top { display: flex; align-items: baseline; gap: 8px; }
  .mg-name { font-size: 13.5px; font-weight: 700; }
  .mg-cur { color: var(--accent); font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
  /* Jobs-to-be-done chips, tinted to the model's own colour (set inline). Outline,
     not filled, so the name still reads first; the chip border is the same hue at
     low opacity via color-mix so a full-strength border doesn't shout. */
  .mg-jobs { display: flex; flex-wrap: wrap; gap: 4px; margin: 1px 0 2px; }
  .mg-job {
    font-size: 10.5px; font-weight: 600; letter-spacing: .01em;
    padding: 2px 7px; border-radius: 3px;
    /* text is the model hue (inline); border is that same hue softened so it
       frames without competing with the model name above it. */
    border: 1px solid color-mix(in srgb, currentColor 45%, transparent);
    background: color-mix(in srgb, currentColor 8%, transparent);
    white-space: nowrap;
  }
  /* Tier mark inside the chip: I / II / III. Kept as a separate <i> so it reads
     as a rating rather than part of the job name, and so tier III can carry a
     little more weight without bolding the whole chip. */
  .mg-tier { font-style: normal; margin-left: 5px; opacity: .62; letter-spacing: .08em; font-size: 9.5px; }
  .mg-job.t3 { border-color: color-mix(in srgb, currentColor 75%, transparent); background: color-mix(in srgb, currentColor 15%, transparent); }
  .mg-job.t3 .mg-tier { opacity: 1; }
  .mg-job.t1 { opacity: .72; }
  /* The one job this model is FOR, inside a company. */
  .mg-role { color: var(--muted); font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
  .mg-best { color: var(--text); font-size: 12px; font-weight: 600; }
  .mg-why { color: var(--muted); font-size: 12px; line-height: 1.5; }
  /* Popularity: real turns run on this Mac in the last 30 days. */
  .mg-pop { display: flex; flex-direction: column; gap: 4px; margin-top: 2px; }
  .mg-pop.none { color: var(--muted); font-size: 10.5px; opacity: .65; }
  .mg-pop-track { height: 3px; border-radius: 3px; background: color-mix(in srgb, var(--text) 12%, transparent); overflow: hidden; }
  .mg-pop-fill { display: block; height: 100%; border-radius: 3px; }
  .mg-pop-lab { color: var(--muted); font-size: 10.5px; }
  /* Muse Glimmer download: a real bar plus the live byte counter, so a slow
     18 GB pull never reads as frozen (John, 2026-08-17). */
  .set-sub-title { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
  .glim-prog { margin: 8px 0 2px; }
  .glim-bar { height: 4px; border-radius: 999px; background: color-mix(in srgb, var(--text) 12%, transparent); overflow: hidden; }
  .glim-fill { height: 100%; width: 0%; border-radius: 999px; background: #4d94ff; transition: width .4s ease; }
  .glim-detail { margin-top: 5px; color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
  /* The dot next to "Downloading…" breathes while bytes are moving. */
  .set-status.dl-live::before { content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: #4d94ff; margin-right: 6px; vertical-align: middle; animation: micpulse 1.1s ease-in-out infinite; }
  .mg-empty { color: var(--muted); font-size: 12.5px; }
  .modal a { color: var(--accent); }
  .modal input { width: 100%; background: var(--panel-2); border: 1px solid var(--line); color: var(--text); border-radius: 3px; padding: 10px 12px; font-family: "SF Mono", ui-monospace, monospace; font-size: 12.5px; outline: none; text-align: left; }
  .modal input:focus { border-color: var(--accent); }
  /* Mirror to Slack dialog: the app's own controls, not native <select> and radios. */
  .slack-mirror-modal { width: 468px; }
  .slack-mirror-modal .confirm-body { margin-bottom: 20px; color: var(--muted); line-height: 1.5; }
  /* Every field is one stacked column: small caps label, full-width control, hint below.
     (Redesign 2026-09-10: the old space-between row let the delivery hint float off to
     the right as a third column.) */
  .slack-field { display: flex; flex-direction: column; align-items: stretch; gap: 7px; margin-top: 18px; }
  .slack-field-label { font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--faint); }
  .slack-dd { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: 8px; box-sizing: border-box; background: var(--panel-2); border: 1px solid var(--line); border-radius: 6px; color: var(--text); padding: 9px 11px; font: inherit; font-size: 13px; cursor: pointer; text-align: left; transition: border-color .12s; }
  .slack-dd:hover { border-color: rgba(var(--accent-rgb), .55); }
  .slack-dd .slack-dd-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .slack-dd svg { width: 14px; height: 14px; color: var(--muted); flex: 0 0 auto; }
  /* Full-width segmented control: two equal halves, not an inline pill pinned right. */
  .slack-mirror-modal .slack-seg { display: flex; width: 100%; box-sizing: border-box; border-radius: 6px; }
  .slack-mirror-modal .slack-seg button { flex: 1; text-align: center; padding: 8px 10px; font-size: 12px; }
  .slack-mirror-modal [data-k="createRow"], .slack-mirror-modal [data-k="existingRow"] { margin-top: 8px; }
  .slack-mirror-modal [data-k="createRow"] input { width: 100%; box-sizing: border-box; background: var(--panel-2); border: 1px solid var(--line); border-radius: 6px; color: var(--text); padding: 9px 11px; font: inherit; font-size: 13px; transition: border-color .12s; }
  .slack-mirror-modal [data-k="createRow"] input:focus { border-color: rgba(var(--accent-rgb), .6); }
  .slack-mirror-modal [data-k="existingRow"] .slack-dd { width: 100%; }
  .slack-hint { font-size: 11.5px; color: var(--faint); margin-top: 6px; line-height: 1.45; }
  .slack-err { margin-top: 10px; padding: 8px 10px; border-radius: 3px; font-size: 12px; line-height: 1.4; color: #e0554a; background: color-mix(in srgb, #e0554a 10%, transparent); border: 1px solid color-mix(in srgb, #e0554a 35%, transparent); }
  .modal .row2 { display: flex; gap: 10px; justify-content: flex-end; margin-top: 16px; }
  .modal .row2 button { border-radius: 3px; padding: 8px 15px; font-size: 13px; cursor: pointer; border: 1px solid var(--line); }
  .modal .cancel { background: var(--panel-2); color: var(--text); }
  .modal .save { background: var(--accent); color: var(--on-accent); border: none; font-weight: 600; }
  /* Destructive confirm button (delete session, etc.) — red, on-brand, never a native alert. */
  .modal .row2 button.danger { background: #e5484d; color: #fff; border: none; font-weight: 600; }
  .modal .row2 button.danger:hover { background: #f2555a; }
  .modal .confirm-body { color: var(--muted); font-size: 12.5px; line-height: 1.5; margin-bottom: 4px; }
  .modal .confirm-body b { color: var(--text); font-weight: 600; }
  .modal .confirm-body a.ext-link { color: var(--accent); text-decoration: none; cursor: pointer; }
  .modal .confirm-body a.ext-link:hover { text-decoration: underline; }
  /* The thing being acted on (a session title, a folder name). Titles are
     auto-derived from the transcript, so they can be enormous — a whole JSON
     stats blob with no spaces in it. Clamp to 2 lines with an ellipsis, and
     force-break unbroken runs so they wrap instead of blowing out the modal. */
  .modal .confirm-body .cm-subject {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    overflow: hidden; overflow-wrap: anywhere; word-break: break-word;
    color: var(--text); font-weight: 600; margin-bottom: 6px;
  }

  /* Nearby (zero-tap) pairing — "Allow this iPhone?" prompt */
  .nearby-pair-modal { width: 420px; }
  .nearby-pair-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }

  /* The Sandbox sheet (/sandbox) */
  .sandbox-modal { width: 500px; }
  .sandbox-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 4px 0 6px; }
  .sandbox-lbl { font-size: 13px; font-weight: 600; color: var(--text); }
  .sandbox-warn { color: #f5a623 !important; }
  .sandbox-when-on { border-top: 1px solid var(--line); margin-top: 12px; padding-top: 12px; }
  .sandbox-fieldlbl { font-size: 12px; font-weight: 600; color: var(--text); margin-top: 10px; }
  .sandbox-sub { margin: 4px 0 6px !important; }
  .sandbox-ta { width: 100%; background: var(--panel-2); border: 1px solid var(--line); color: var(--text); border-radius: 3px; padding: 9px 11px; font-family: "SF Mono", ui-monospace, monospace; font-size: 12px; outline: none; resize: vertical; line-height: 1.5; }
  .sandbox-ta:focus { border-color: var(--accent); }
  .sandbox-check { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: 12.5px; color: var(--muted); cursor: pointer; }
  .sandbox-check input { width: auto; }

  /* The Directives sheet (//directives) */
  .directives-modal { width: 500px; }
  .directives-ta { margin-top: 4px; }
  .directives-eg { margin: 8px 0 2px !important; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
  .directives-chip { display: inline-block; background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 2px 9px; font-size: 11.5px; color: var(--muted); white-space: nowrap; }

  /* account dropdown */
  .acct-wrap { position: relative; -webkit-app-region: no-drag; }
  /* fixed-positioned (set in JS): never clipped by the sidebar's overflow */
  .acct-wrap .acct-menu { position: fixed; top: auto; right: auto; }   /* JS places it; never clipped */
  body.collapsed .side-footer .acct-wrap { display: block; }
  .acct-btn {
    display: flex; align-items: center; gap: 7px;
    background: var(--panel-2); color: var(--text);
    border: 1px solid var(--line); border-radius: 3px;
    padding: 0 10px; font-size: 12.5px; cursor: pointer; max-width: 220px;
    /* Pinned to .icon-btn's 28px so it lines up with the Journal button beside it.
       It used to be padding-sized, which landed a pixel or two taller (John, 2026-08-16). */
    height: 28px; box-sizing: border-box;
  }
  .acct-btn:hover { background: var(--hover); }
  .acct-btn #acctLabel { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .acct-dot { width: 7px; height: 7px; border-radius: 2px; background: var(--accent); flex: 0 0 auto; }   /* square, not a dot (John, 2026-08-24) */
  .acct-btn.connected .acct-dot { background: #3ecf8e; }   /* connector on / account present */
  /* A real run-account is active: blink the chip dot orange so John always knows WHICH
     account he's on without opening the menu. Beats the green .connected rule (later source). */
  .acct-btn.acct-live .acct-dot { background: var(--accent); animation: micpulse 1.1s ease-in-out infinite; }
  /* All connected accounts hit their 5h/weekly limit: the button goes red and shows a
     live countdown to the soonest one reopening. */
  .acct-btn.limited { border-color: rgba(224,73,41,0.55); background: rgba(224,73,41,0.12); }
  .acct-btn.limited:hover { background: rgba(224,73,41,0.2); }
  .acct-btn.limited .acct-dot { background: #e0492a; box-shadow: none; }
  /* Full lockdown (every account capped): drop the account name + caret — switching
     accounts can't help while they're all limited — and leave just the countdown timer. */
  .acct-btn.limited #acctLabel,
  .acct-btn.limited .caret { display: none; }
  .acct-countdown {
    flex: 0 0 auto; font-variant-numeric: tabular-nums; font-weight: 600;
    font-size: 11.5px; color: #e0492a; letter-spacing: 0.2px;
  }
  /* Connect-gate tabs: pick MCP vs API key */
  .acct-btn .caret { color: var(--faint); font-size: 10px; }
  .acct-menu {
    /* Account dropdown text uses the chosen interface font, not Monorama (John,
       2026-08-24) — the small meter labels read cleaner in it. */
    font-family: var(--ui-font, ui-monospace), monospace;
    position: absolute; top: 36px; right: 0; width: 312px;
    background: var(--panel); border: 1px solid var(--line); border-radius: 3px;
    padding: 8px; display: none; z-index: 40;
    box-shadow: 0 12px 30px rgba(0,0,0,var(--sh50, .5));
    overflow-y: auto;   /* height is capped in JS; scroll rather than run off-screen */
    /* Whole menu ~15% smaller (John, 2026-08-14). Scaled around the bottom-left
       corner because that's the point JS pins to the switcher (left + bottom), so
       shrinking never drifts it off the button. transform (not zoom) keeps the JS
       placement math untouched. */
    transform: scale(.85); transform-origin: bottom left;
  }
  .acct-menu.show { display: block; }
  .acct-item {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 11px; border-radius: 3px; cursor: pointer; font-size: 15px;
  }
  /* The account actually selected right now (John, 2026-08-16: "a better visual
     representation of the Main selected model" — the dot alone gave no signal
     while idle, since selected and merely-ready both drew the same green dot).
     A thin accent bar down the left edge, NOT a filled band: the filled version
     read as messy against the usage strips sitting right under the row. */
  .acct-item.is-selected { position: relative; }
  .acct-item.is-selected::before {
    content: ''; position: absolute; left: 0; top: 4px; bottom: 4px; width: 2px;
    border-radius: 2px; background: var(--accent);
  }
  .acct-cur { color: var(--accent); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; opacity: .85; }
  /* Organization name next to an account label — tells a Team workspace apart from a
     personal one on the same email (John, 2026-09-14). */
  /* Org/email subline is quiet by default and only appears when you hover the row
     (John, 2026-09-14: "I ONLY want the email on hover"). */
  .acct-item .acct-org { color: var(--faint); font-size: 10.5px; font-weight: 500; margin-left: 5px; display: none; }
  .acct-item:hover .acct-org { display: inline; }
  /* ONE SUBCARD (John, 2026-08-16): the account title row and its usage meters are a
     single hover/click surface. The two halves must NOT light up on their own — that
     read as two separate strips. Highlight lives on the wrapper only. */
  .acct-card { border-radius: 3px; }
  .acct-card:hover { background: var(--hover); }
  .acct-card:hover .acct-item,
  .acct-card:hover .acct-limits { background: transparent; }
  .acct-item .check { width: 17px; color: var(--accent); flex: 0 0 auto; font-size: 14px; }
  /* Account rows carry no status square, so the check is always empty — collapse it
     (and its flex gap) so the name sits left instead of floating in dead space (John, 2026-08-29). */
  .acct-item .check:empty { display: none; }
  /* Per-account status dot. TWO health states only (John, 2026-08-15): green =
     ready, red = maxed out. No grey — grey used to mean "this engine publishes no
     meter", which says something about us, not about whether the account can run.
     Orange still layers on top for the account currently running / selected.
     The base colour is green so a dot can never fall back to grey. */
  .acct-item .acct-rowdot { display: inline-block; width: 10px; height: 10px; border-radius: 2px; background: #35c07f; vertical-align: middle; }
  .acct-item .acct-rowdot.active { background: var(--accent); }
  .acct-item .acct-rowdot.available { background: #35c07f; }   /* green = has headroom / active */
  .acct-item .acct-rowdot.limited { background: #e5484d; }     /* red = limit hit / not available (wins) */
  /* Provider/company header above each engine's account run — same look as the
     model picker's CLAUDE / CODEX / … group headers. */
  .acct-eng-head { display: flex; align-items: center; gap: 6px; padding: 8px 4px 3px; font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--faint); }
  .acct-eng-head .eh-swatch { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; }
  .acct-eng-head .eh-swatch.in-use { animation: micpulse 1.1s ease-in-out infinite; }
  .acct-eng-head .eh-name { flex: 1 1 auto; }
  .acct-eng-head .eh-dots { opacity: 0; color: var(--faint); font-size: 13px; padding: 0 4px; border-radius: 3px; cursor: pointer; flex: 0 0 auto; }
  .acct-eng-head:hover .eh-dots { opacity: 1; }
  .acct-eng-head .eh-dots:hover { color: var(--accent); background: var(--hover); }
  /* The account you're ACTUALLY on right now: blink orange so it's unmistakable at a
     glance. Placed AFTER .available so it wins the green (the active row also carries
     .available). A limited active account still shows steady red — that's why it'd auto-switch. */
  .acct-item .acct-rowdot.active { background: var(--accent); animation: micpulse 1.1s ease-in-out infinite; }
  .acct-item .acct-rowdot.active.limited { background: #e5484d; animation: none; }
  /* SELECTED but not running: NOTHING extra. Orange means "spending right now" and
     nothing else, so the account you merely picked must not wear an orange ring —
     that read as working and, on top of a green fill, as two states at once.
     Which account is selected is already unmistakable from the button's own label
     and the row's check column. (John, 2026-08-16.) */
  .acct-item .acct-rowdot.selected { animation: none; }
  .acct-item .check.big { width: 22px; font-size: 19px; }   /* Mobile Sync icon, a touch bigger */
  .acct-email { padding: 7px 10px 5px; color: var(--faint); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; user-select: text; }
  /* email + version row: email truncates with … , version never shrinks/hides */
  .acct-footer { display: flex; align-items: baseline; gap: 8px; padding: 7px 10px 5px; }
  .acct-footer .acct-email { padding: 0; flex: 1 1 auto; min-width: 0; }
  .acct-footer .acct-ver { flex: 0 0 auto; color: var(--faint); font-size: 10.5px; font-variant-numeric: tabular-nums; opacity: .8; }
  /* Trial countdown row — moved off the bottom account/model chip, sits above the email
     (John, 2026-09-09). Quiet accent dot + "N days left". */
  .acct-trial-row { display: flex; align-items: center; gap: 8px; padding: 6px 10px; font-size: 11.5px; color: var(--muted); }
  .acct-trial-row .acct-trial-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 6px rgba(var(--accent-rgb), .6); }
  .acct-trial-row .lbl { color: var(--text); }
  .acct-item .acct-ic { flex: 0 0 auto; color: var(--accent); display: inline-flex; align-items: center; margin-right: 2px; }
  .acct-item .lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Every chip is ONE size — the Max size (11.25px) — so Max / Pro / Free / login all
     read as the same badge (John, 2026-08-14). The transparent border on Max keeps its
     box the exact height of the outlined Pro/engine chips. */
  .acct-item .type { flex: 0 0 auto; color: var(--faint); font-size: 11.25px; cursor: pointer; padding: 3px 6px; border-radius: 3px; border: 1px solid transparent; }
  .acct-item .type:hover { color: var(--accent); background: var(--hover); }
  /* real plan badge from the profile endpoint */
  .acct-item .type.plan-max { color: #fff; background: var(--accent); font-weight: 700; }
  .acct-item .type.plan-max:hover { background: var(--accent); filter: brightness(1.1); }
  .acct-item .type.plan-pro { color: var(--accent); border: 1px solid var(--accent); }
  /* Any non-Claude engine: outlined in ITS OWN colour (set inline from the engine
     catalog, so a new engine's badge is right with no CSS here), so the row reads
     as "not Claude" at a glance. .plan-codex is the old class name, kept working. */
  .acct-item .type.plan-engine, .acct-item .type.plan-codex { color: #8a8f98; border: 1px solid currentColor; cursor: default; }
  .acct-item .type.plan-engine:hover, .acct-item .type.plan-codex:hover { background: transparent; }
  .acct-item .psync { color: var(--faint); font-size: 11.5px; opacity: .8; white-space: nowrap; }
  .acct-item .rm { opacity: 0; color: var(--faint); font-size: 15px; padding: 0 4px; border-radius: 3px; }
  .acct-card:hover .rm { opacity: 1; }
  .acct-item .rm:hover { color: var(--accent); background: var(--active); }
  .acct-sep { height: 1px; background: var(--line); margin: 5px 4px; }
  /* The Claude logins live inside one rounded panel so they read as a single group,
     visually distinct from external engines (Codex, Meta), which each stand alone
     outside the panel (John, 2026-08-14). Contiguous Claude accounts share a panel;
     a non-Claude engine breaks the run so drag-reordering can't mis-group. */
  .acct-group { border: none; border-radius: 0; background: transparent; padding: 0; margin: 0; }
  .acct-group .acct-sep.in-group { margin: 2px 10px; opacity: .3; }
  /* Clean, minimal separation between model providers: one hairline before each engine
     group but the first, with a little breathing room. No boxes. (John, 2026-08-17.) */
  .acct-group.eng-start, .acct-solo.eng-start { margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--line); }
  .acct-solo { margin: 3px 1px; }
  /* Auto Switch toggle row at the top of the accounts panel. */
  .acct-autoswitch { cursor: pointer; align-items: center; }
  .acct-autoswitch .lbl { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
  .acct-autoswitch .as-title { font-size: 15px; font-weight: 600; color: var(--text); }
  .acct-autoswitch .as-sub { font-size: 10.5px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .acct-autoswitch.on .as-title { color: var(--accent); }
  .acct-autoswitch .mc-sw.on { background: var(--accent); }   /* match the panel's orange, not gold */
  .acct-add { color: var(--accent); font-weight: 600; }

  /* Invite row — the one colored entry in the account menu, so it pops.
     Uses --accent-rgb so it tracks the live accent (incl. the green/blue themes). */
  .acct-invite {
    background: linear-gradient(90deg, rgba(var(--accent-rgb),.16), rgba(var(--accent-rgb),.05));
    border: 1px solid rgba(var(--accent-rgb),.35);
    border-radius: 3px; margin: 2px 2px 4px; font-weight: 600;
  }
  .acct-invite .acct-ic, .acct-invite .lbl { color: var(--accent); }
  .acct-invite:hover { background: linear-gradient(90deg, rgba(var(--accent-rgb),.26), rgba(var(--accent-rgb),.10)); }
  .acct-admin .acct-ic { color: var(--faint); }
  .acct-admin:hover .acct-ic { color: var(--text); }

  /* Documentation — the plain-words manual, hosted in an isolated iframe */
  .docs-overlay {
    position: fixed; inset: 0; z-index: 1002; display: flex; align-items: center; justify-content: center;
    background: rgba(0,0,0,.6); backdrop-filter: blur(3px); padding: 24px;
  }
  .docs-card {
    position: relative; width: min(960px, 94vw); height: min(88vh, 940px);
    background: var(--panel); border: 1px solid var(--line); border-radius: 3px;
    box-shadow: 0 24px 70px rgba(0,0,0,var(--sh55, .55)); overflow: hidden;
  }
  .docs-frame { width: 100%; height: 100%; border: 0; display: block; background: var(--panel); }
  .docs-x {
    position: absolute; top: 12px; right: 12px; z-index: 2; width: 30px; height: 30px; border-radius: 3px;
    border: 1px solid var(--line); background: rgba(13,13,13,.7); color: var(--faint); cursor: pointer; font-size: 13px;
    display: flex; align-items: center; justify-content: center; backdrop-filter: blur(6px);
  }
  .docs-x:hover { color: var(--text); background: rgba(255,255,255,.08); }

  /* Admin console (John-only) — mirrors the mobile AdminConsole */
  .admin-overlay {
    position: fixed; inset: 0; z-index: 1001; display: flex; align-items: center; justify-content: center;
    background: rgba(0,0,0,.55); backdrop-filter: blur(3px); padding: 24px;
  }
  .admin-card {
    /* Bigger (John, 2026-08-17): the analytics tab was scrolling sideways inside a 560px
       card — the stat tiles and the funnel table were cut off. Wider + taller so the whole
       dashboard fits without a horizontal scrollbar. */
    position: relative; width: min(1080px, 94vw); max-height: min(90vh, 960px); box-sizing: border-box;
    display: flex; flex-direction: column;
    background: var(--panel, #17181c); border: 1px solid var(--line); border-radius: 3px;
    box-shadow: 0 24px 70px rgba(0,0,0,var(--sh50, .5)); overflow: hidden;
  }
  .admin-head { display: flex; align-items: center; gap: 10px; padding: 16px 18px 12px; border-bottom: 1px solid var(--line); }
  .admin-title { flex: 1; min-width: 0; font-size: 15px; font-weight: 700; }
  .admin-x {
    flex: 0 0 auto; width: 28px; height: 28px; border-radius: 3px; border: 1px solid var(--line);
    background: transparent; color: var(--faint); cursor: pointer; font-size: 13px;
  }
  .admin-x:hover { color: var(--text); background: var(--hover); }
  .admin-tabs { display: flex; gap: 6px; padding: 12px 16px 0; }
  .admin-tab {
    flex: 0 0 auto; padding: 7px 14px; border-radius: 3px; border: 1px solid transparent;
    background: transparent; color: var(--faint); cursor: pointer; font-size: 13px; font-weight: 600;
  }
  .admin-tab:hover { color: var(--text); background: var(--hover); }
  .admin-tab.on { color: var(--accent); border-color: rgba(var(--accent-rgb),.4); background: rgba(var(--accent-rgb),.1); }
  .admin-body { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 16px 18px; }

  /* Analytics — its own overlay (openAnalytics), wider than the admin console
     because the website + email tabs put two panels side by side. */
  .an-card-wide { width: min(1240px, 96vw); }
  .an-range { display: flex; gap: 4px; flex: 0 0 auto; }
  .an-range-b {
    padding: 5px 10px; border-radius: 3px; border: 1px solid var(--line); background: transparent;
    color: var(--faint); cursor: pointer; font-size: 11.5px; font-weight: 700;
  }
  .an-range-b:hover { color: var(--text); background: var(--hover); }
  .an-range-b.on { color: var(--accent); border-color: rgba(var(--accent-rgb),.45); background: rgba(var(--accent-rgb),.1); }
  .an-tile-s { margin-top: 2px; font-size: 10.5px; color: var(--faint); }
  .an-h-note { float: right; font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--faint); opacity: .8; }
  /* Breakdown bars — label · meter · count · people · share */
  .an-bars { display: flex; flex-direction: column; gap: 3px; }
  .an-bar-row { display: flex; align-items: center; gap: 9px; padding: 3px 0; }
  .an-bar-l { flex: 0 1 38%; min-width: 0; font-size: 12px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .an-bar-m { flex: 1 1 auto; min-width: 0; }
  .an-bar-n { flex: 0 0 42px; text-align: right; font-size: 12px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
  .an-bar-u { flex: 0 0 78px; text-align: right; font-size: 11px; color: var(--faint); white-space: nowrap; font-variant-numeric: tabular-nums; }
  .an-bar-p { flex: 0 0 38px; text-align: right; font-size: 11px; font-weight: 700; color: var(--faint); font-variant-numeric: tabular-nums; }
  /* Rate blocks — one conversion/engagement number with its meter */
  .an-rate { padding: 6px 0 10px; }
  .an-rate + .an-rate { border-top: 1px solid rgba(255,255,255,.05); }
  .an-rate-h { display: flex; align-items: baseline; gap: 8px; margin-bottom: 5px; }
  .an-rate-l { flex: 1; min-width: 0; font-size: 12px; color: var(--text); }
  .an-rate-v { flex: 0 0 auto; font-size: 15px; font-weight: 800; color: var(--accent); }
  .an-rate-s { margin-top: 4px; font-size: 11px; color: var(--faint); }
  /* Funnel drop-off column (added next to conversion) */
  .an-fn-drop { flex: 0 0 46px; text-align: right; font-size: 11px; font-weight: 700; color: #e2686a; }
  /* Extra props shown inline on the email stream */
  .an-ev-props { flex: 0 0 auto; max-width: 42%; font-size: 11px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* People list */
  .an-plist { display: flex; flex-direction: column; gap: 1px; max-height: 460px; overflow-y: auto; }
  .an-p-row { display: flex; align-items: baseline; gap: 10px; padding: 6px 0; border-bottom: 1px solid rgba(255,255,255,.04); }
  .an-p-main { flex: 1; min-width: 0; }
  .an-p-id { font-size: 12.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .an-p-sub { font-size: 11px; color: var(--faint); }
  .an-p-seen { flex: 0 0 auto; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
  @media (max-width: 900px) { .an-2col { grid-template-columns: 1fr; } }

  /* Analytics tab — the Luminair dashboard (Elion Analytics) */
  .an-wrap { display: flex; flex-direction: column; gap: 12px; }
  .an-tiles { display: flex; flex-wrap: wrap; gap: 8px; }
  .an-tile {
    flex: 1 1 88px; min-width: 88px; box-sizing: border-box; padding: 10px 12px;
    border: 1px solid var(--line); border-radius: 3px; background: var(--bg, #0e0f12);
  }
  .an-tile-n { font-size: 22px; font-weight: 800; line-height: 1.05; color: var(--text); }
  .an-tile-l { margin-top: 3px; font-size: 11px; font-weight: 600; color: var(--faint); text-transform: uppercase; letter-spacing: .04em; }
  .an-card { border: 1px solid var(--line); border-radius: 3px; background: var(--bg, #0e0f12); padding: 12px 14px; }
  .an-h { font-size: 12px; font-weight: 700; color: var(--faint); text-transform: uppercase; letter-spacing: .05em; margin-bottom: 10px; }
  .an-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .an-none { font-size: 12px; color: var(--faint); padding: 6px 0; }
  /* DAU trace — dot-matrix LED spark, stretched across the card */
  .an-spark-dm { width: 100%; grid-template-columns: repeat(var(--dm-cols), 1fr); justify-items: center; }
  /* Funnel — each step is a dot-matrix meter */
  .an-fn-row { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; }
  .an-fn-label { flex: 0 0 118px; min-width: 0; font-size: 12px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .an-fn-bar { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }
  .an-fn-dm { flex: 0 0 auto; }
  .an-fn-n { flex: 0 0 auto; font-size: 11px; font-weight: 700; color: var(--text); }
  .an-fn-conv { flex: 0 0 40px; text-align: right; font-size: 12px; font-weight: 700; color: var(--faint); }
  /* Top events */
  .an-te { display: flex; flex-direction: column; gap: 2px; }
  .an-te-row { display: flex; align-items: baseline; gap: 8px; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,.04); }
  .an-te-name { flex: 1; min-width: 0; font-size: 12px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .an-te-n { flex: 0 0 auto; font-size: 12px; font-weight: 700; color: var(--accent); }
  .an-te-u { flex: 0 0 auto; font-size: 11px; color: var(--faint); }
  /* Retention grid — horizontal scroll if it outgrows the card */
  .an-ret { overflow-x: auto; }
  .an-ret-row { display: flex; }
  .an-ret-c { flex: 0 0 46px; box-sizing: border-box; padding: 6px 4px; text-align: center; font-size: 11px; color: var(--text); border: 1px solid rgba(255,255,255,.05); }
  .an-ret-cohort { flex: 0 0 78px; text-align: left; color: var(--faint); }
  .an-ret-head .an-ret-c { color: var(--faint); font-weight: 700; }
  .an-ret-cell { color: var(--text); }
  /* Recent activity stream — name (fixed) · who (flex, ellipsis) · platform · time */
  .an-stream { display: flex; flex-direction: column; gap: 1px; max-height: 340px; overflow-y: auto; }
  .an-ev-row { display: flex; align-items: baseline; gap: 8px; padding: 5px 0; border-bottom: 1px solid rgba(255,255,255,.04); }
  .an-ev-name { flex: 0 0 auto; max-width: 40%; font-size: 12px; font-weight: 700; color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .an-ev-who { flex: 1; min-width: 0; font-size: 12px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .an-ev-who.anon { color: var(--faint); font-style: italic; }
  .an-ev-plat { flex: 0 0 auto; font-size: 10px; font-weight: 600; color: var(--faint); text-transform: uppercase; letter-spacing: .04em; }
  .an-ev-t { flex: 0 0 auto; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
  .an-empty { padding: 20px 16px; text-align: center; }
  .an-empty-t { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 6px; }
  .an-empty-s { font-size: 12px; color: var(--faint); line-height: 1.5; max-width: 380px; margin: 0 auto; }
  .an-empty.err .an-empty-t { color: var(--accent); }
  .admin-search {
    width: 100%; box-sizing: border-box; padding: 9px 11px; border-radius: 3px;
    border: 1px solid var(--line); background: var(--bg, #0e0f12); color: var(--text); font-size: 13px;
  }
  .admin-search:focus { outline: none; border-color: rgba(var(--accent-rgb),.5); }
  .admin-count { color: var(--faint); font-size: 12px; margin: 10px 2px 6px; }
  .admin-list { display: flex; flex-direction: column; gap: 6px; }
  .admin-user, .admin-wl-row {
    display: flex; align-items: center; gap: 10px; width: 100%; box-sizing: border-box; text-align: left;
    padding: 9px 11px; border-radius: 3px; border: 1px solid var(--line); background: var(--bg, #0e0f12);
  }
  .admin-user { cursor: pointer; }
  .admin-user:hover { background: var(--hover); border-color: rgba(var(--accent-rgb),.3); }
  .admin-user-main { flex: 1; min-width: 0; }
  .admin-user-email { font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .admin-user-sub { font-size: 11.5px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Admin console rows hold REAL DATA John needs to copy out (emails, names, ids) —
     not UI chrome. Opt them back in from the global `* { user-select: none }` rule
     above, which otherwise makes every address in here impossible to highlight.
     (John, 2026-07-30 — "allow me to select these emails".) */
  .admin-user-email, .admin-user-sub, .admin-wl-row, .admin-wl-row *,
  .admin-profile, .admin-profile * {
    -webkit-user-select: text; user-select: text; cursor: text;
  }
  /* the × stays a button, not selectable text */
  .admin-wl-row .admin-rowx { -webkit-user-select: none; user-select: none; cursor: pointer; }
  .admin-badges { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
  .admin-ver {
    flex: 0 0 auto; font-size: 11px; font-weight: 600; color: var(--faint);
    font-variant-numeric: tabular-nums; letter-spacing: .2px; white-space: nowrap;
  }
  .admin-badge {
    flex: 0 0 auto; display: inline-block; padding: 3px 9px; border-radius: 3px; font-size: 11px; font-weight: 700;
  }
  .admin-badge.wl { color: #3ecf8e; background: rgba(62,207,142,.14); }
  .admin-badge.pro { color: var(--accent); background: rgba(var(--accent-rgb),.16); }
  .admin-badge.none { color: var(--faint); background: var(--hover); }
  .admin-badge.trial { color: #ffaf2b; background: rgba(255,175,43,.15); }
  .admin-add { display: flex; gap: 8px; margin-bottom: 10px; }
  .admin-add .admin-search { flex: 1; min-width: 0; }
  .admin-add-btn {
    flex: 0 0 auto; padding: 0 16px; border-radius: 3px; border: 1px solid rgba(var(--accent-rgb),.4);
    background: rgba(var(--accent-rgb),.14); color: var(--accent); font-weight: 700; font-size: 13px; cursor: pointer;
  }
  .admin-add-btn:hover:not(:disabled) { background: rgba(var(--accent-rgb),.24); }
  .admin-add-btn:disabled { opacity: .5; cursor: default; }
  .admin-hint { color: var(--faint); font-size: 12px; line-height: 1.5; margin: 0 2px 12px; }
  .admin-wl-list { display: flex; flex-direction: column; gap: 6px; }
  /* Whitelist multi-select: tick rows, then Copy or Remove the lot. (John, 2026-07-30) */
  .admin-wl-bar {
    display: flex; align-items: center; gap: 10px; margin: 0 2px 8px; padding: 6px 9px;
    border: 1px solid var(--line); border-radius: 3px; background: rgba(255,255,255,.02);
  }
  .admin-wl-bar[hidden] { display: none; }
  .wl-all { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; color: var(--muted); cursor: pointer; -webkit-user-select: none; user-select: none; }
  .wl-count { flex: 1; min-width: 0; font-size: 12px; color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .wl-copy, .wl-del {
    flex: 0 0 auto; font-size: 11.5px; font-weight: 600; padding: 4px 11px; border-radius: 3px;
    border: 1px solid var(--line); background: transparent; color: var(--muted); cursor: pointer; white-space: nowrap;
  }
  .wl-copy:hover:not(:disabled) { color: var(--text); border-color: rgba(var(--accent-rgb),.45); }
  .wl-del:hover:not(:disabled) { color: #ff6b5e; border-color: rgba(255,107,94,.5); }
  .wl-copy:disabled, .wl-del:disabled { opacity: .4; cursor: default; }
  .wl-check, .wl-all-box { flex: 0 0 auto; width: 15px; height: 15px; margin: 0; accent-color: var(--accent); cursor: pointer; }
  .admin-wl-row.sel { border-color: rgba(var(--accent-rgb),.45); background: rgba(var(--accent-rgb),.07); }
  .admin-rowx {
    flex: 0 0 auto; width: 26px; height: 26px; border-radius: 3px; border: 1px solid var(--line);
    background: transparent; color: var(--faint); cursor: pointer; font-size: 15px; line-height: 1;
  }
  .admin-rowx:hover { color: #ff6b5e; border-color: rgba(255,107,94,.5); }
  .admin-rowx:disabled { opacity: .4; cursor: default; }
  .admin-section-h { font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--faint); margin: 14px 2px 8px; }
  .admin-empty { color: var(--faint); font-size: 13px; text-align: center; padding: 22px 8px; }
  .admin-empty.err { color: #ff6b5e; }

  /* User profile — slide-over layered on the admin card (behavior + billing + invites) */
  .admin-profile {
    position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column;
    background: var(--panel, #17181c); animation: prof-in .16s ease;
  }
  @keyframes prof-in { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: none; } }
  .prof-head { flex: 0 0 auto; padding: 14px 16px 10px; border-bottom: 1px solid var(--line); }
  .prof-back {
    -webkit-app-region: no-drag; padding: 6px 12px 6px 8px; border-radius: 3px; border: 1px solid var(--line);
    background: transparent; color: var(--faint); cursor: pointer; font-size: 13px; font-weight: 600;
  }
  .prof-back:hover { color: var(--accent); border-color: rgba(var(--accent-rgb),.4); background: rgba(var(--accent-rgb),.1); }
  .prof-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 16px 20px; }
  .prof-id { margin-bottom: 14px; }
  .prof-email { font-size: 16px; font-weight: 800; color: var(--text); word-break: break-word; }
  .prof-sub { margin-top: 2px; font-size: 12.5px; color: var(--faint); }
  .prof-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
  .prof-chip {
    flex: 0 0 auto; padding: 3px 9px; border-radius: 3px; font-size: 11px; font-weight: 600;
    color: var(--faint); background: var(--hover); text-transform: capitalize;
  }
  .prof-tiles { display: flex; gap: 8px; }
  .prof-tile {
    flex: 1 1 0; min-width: 0; box-sizing: border-box; padding: 10px 12px;
    border: 1px solid var(--line); border-radius: 3px; background: var(--bg, #0e0f12);
  }
  .prof-tile-n { font-size: 20px; font-weight: 800; line-height: 1.05; color: var(--text); }
  .prof-tile-l { margin-top: 3px; font-size: 10.5px; font-weight: 600; color: var(--faint); text-transform: uppercase; letter-spacing: .04em; }
  .prof-meta { margin: 10px 2px 2px; font-size: 12px; color: var(--faint); }
  .prof-sec-h { font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--faint); margin: 16px 2px 8px; }
  /* Journey milestones — dot + name (flex) + when (fixed) */
  .prof-miles { display: flex; flex-direction: column; gap: 2px; }
  .prof-mile { display: flex; align-items: center; gap: 9px; padding: 6px 0; border-bottom: 1px solid rgba(255,255,255,.04); opacity: .55; }
  .prof-mile.on { opacity: 1; }
  .prof-mile-dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 3px; background: var(--line); }
  .prof-mile.on .prof-mile-dot { background: var(--accent); box-shadow: none; }
  .prof-mile-name { flex: 1; min-width: 0; font-size: 12.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .prof-mile-when { flex: 0 0 auto; font-size: 11.5px; color: var(--faint); font-variant-numeric: tabular-nums; }
  /* Invited-by / invited rows */
  .prof-invby { font-size: 13px; color: var(--text); padding: 2px 2px 4px; word-break: break-word; }
  .prof-inv-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid rgba(255,255,255,.04); }
  .prof-inv-email { flex: 1; min-width: 0; font-size: 12.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Per-event counts */
  .prof-pe-row { display: flex; align-items: baseline; gap: 8px; padding: 5px 0; border-bottom: 1px solid rgba(255,255,255,.04); }
  .prof-pe-name { flex: 1; min-width: 0; font-size: 12.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .prof-pe-n { flex: 0 0 auto; font-size: 12.5px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
  /* Timeline — name (flex) · platform · time */
  .prof-tl-row { display: flex; align-items: baseline; gap: 8px; padding: 5px 0; border-bottom: 1px solid rgba(255,255,255,.04); }
  .prof-tl-name { flex: 1; min-width: 0; font-size: 12.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .prof-tl-plat { flex: 0 0 auto; font-size: 10px; font-weight: 600; color: var(--faint); text-transform: uppercase; letter-spacing: .04em; }
  .prof-tl-t { flex: 0 0 auto; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }

  /* Invite panel */
  .invite-overlay {
    position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center;
    background: rgba(0,0,0,.55); backdrop-filter: blur(3px); padding: 24px;
  }
  .invite-card {
    position: relative; width: min(440px, 92vw); box-sizing: border-box;
    background: var(--panel, #17181c); border: 1px solid var(--line); border-radius: 3px;
    padding: 34px 32px 30px; text-align: center;
    box-shadow: 0 24px 70px rgba(0,0,0,var(--sh50, .5));
    overflow: hidden; transition: width .4s cubic-bezier(.2,.8,.2,1), box-shadow .4s ease;
  }
  /* Invite-sent celebration (John, 2026-07-25): the card collapses to one exciting
     confirmation, then auto-closes. */
  .invite-card.invite-celebrate {
    width: min(340px, 90vw);
    box-shadow: none;
  }
  .invite-boom { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 14px 4px; }
  .invite-check {
    width: 68px; height: 68px; border-radius: 50%; display: flex; align-items: center;
    justify-content: center; font-size: 34px; color: #fff; background: var(--accent);
    box-shadow: 0 0 0 0 rgba(var(--accent-rgb),.55);
    animation: invitePop .5s cubic-bezier(.2,.9,.3,1.5) both, invitePulse 1.4s ease-out .5s 2;
  }
  .invite-boom-title { font-size: 22px; font-weight: 700; color: var(--text); letter-spacing: -0.01em; }
  .invite-boom-sub { font-size: 14px; color: var(--muted);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; }
  @keyframes invitePop { 0% { transform: scale(0) rotate(-25deg); opacity: 0; }
    60% { transform: scale(1.18) rotate(0); opacity: 1; } 100% { transform: scale(1); } }
  @keyframes invitePulse { 0% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb),.55); }
    100% { box-shadow: none; } }
  .invite-x {
    position: absolute; top: 14px; right: 14px; width: 28px; height: 28px; border-radius: 3px;
    background: transparent; border: none; color: var(--faint); font-size: 13px; cursor: pointer;
  }
  .invite-x:hover { background: var(--hover); color: var(--text); }
  .invite-gift {
    width: 48px; height: 48px; margin: 0 auto 18px; border-radius: 3px; display: flex;
    align-items: center; justify-content: center; color: #fff;
    background: linear-gradient(135deg, var(--accent), #b5381f);
    box-shadow: none;
  }
  .invite-gift svg { width: 23px; height: 23px; }
  .invite-title { margin: 0 0 10px; font-size: 20px; line-height: 1.25; font-weight: 700; color: var(--text); }
  /* Invite pitch tracks the theme ink (John, 2026-08-26 — was hardcoded white, invisible
     on the light/white themes). */
  .invite-lede { margin: 0 auto 24px; max-width: 340px; font-size: 12.5px; line-height: 1.55; color: var(--text); }
  .invite-lede b { color: var(--text); }
  .invite-linkrow { display: flex; gap: 9px; align-items: stretch; }
  .invite-link {
    flex: 1; min-width: 0; box-sizing: border-box; padding: 11px 13px;
    background: var(--hover); border: 1px solid var(--line); border-radius: 3px;
    color: var(--text); font-size: 12px; user-select: text; overflow: hidden; text-overflow: ellipsis;
  }
  .invite-copy {
    flex: 0 0 auto; padding: 0 16px; border: none; border-radius: 3px; cursor: pointer;
    background: var(--accent); color: #fff; font-weight: 700; font-size: 12.5px; white-space: nowrap;
  }
  .invite-copy:hover { filter: brightness(1.08); }
  .invite-copy.done { background: #2e9e5b; }
  .invite-coderow { margin-top: 16px; font-size: 12px; color: var(--faint); }
  .invite-coderow .invite-code {
    color: var(--accent); letter-spacing: 1.5px; font-weight: 700; user-select: text;
    padding: 3px 9px; border-radius: 3px; background: rgba(var(--accent-rgb),.12);
  }
  .invite-stats {
    display: flex; gap: 24px; justify-content: center; margin-top: 24px; padding-top: 20px;
    border-top: 1px solid var(--line); font-size: 12px; color: var(--faint);
  }
  .invite-stats b { color: var(--accent); font-size: 15px; }
  /* Email-invite chips: field grows as you fill it; paste splits into many;
     orange = valid, red = malformed. (Fixed ✕ + flexible text → min-width:0 rule.) */
  .invite-email { margin-top: 24px; padding-top: 22px; border-top: 1px solid var(--line); text-align: left; }
  .invite-email-label { font-size: 11.5px; color: var(--faint); margin-bottom: 10px; text-align: center; }
  .invite-chips {
    display: flex; flex-wrap: wrap; gap: 7px; align-items: center;
    min-height: 44px; padding: 10px; border-radius: 3px;
    background: var(--bg, #0a0a0b); border: 1px solid var(--line, rgba(255,255,255,.1));
  }
  .invite-chips:focus-within { border-color: var(--accent, #ff6a44); }
  .invite-chip {
    display: inline-flex; align-items: center; gap: 6px; max-width: 100%; min-width: 0;
    padding: 4px 7px 4px 11px; border-radius: 3px; font-size: 12px; line-height: 1.4;
    cursor: pointer; border: 1px solid transparent;
  }
  .invite-chip .ic-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
  .invite-chip.valid { background: rgba(var(--accent-rgb),.16); color: var(--accent); border-color: rgba(var(--accent-rgb),.45); }
  /* Invalid must read as "wrong" at a glance even though the brand accent is red-orange:
     a cooler/brighter red + a DASHED border so it never relies on hue alone. */
  .invite-chip.invalid { background: rgba(255,70,70,.13); color: #ff6b6b; border: 1px dashed rgba(255,90,90,.75); }
  .invite-chip .ic-x {
    flex-shrink: 0; border: none; background: transparent; color: inherit; cursor: pointer;
    font-size: 11px; opacity: .7; padding: 0; line-height: 1;
  }
  .invite-chip .ic-x:hover { opacity: 1; }
  .invite-chip-input {
    flex: 1; min-width: 120px; background: transparent; border: none; outline: none;
    color: var(--text, #f4f4f5); font-size: 13px; padding: 5px 3px;
  }
  .invite-send {
    margin-top: 12px; width: 100%; padding: 11px 14px; border: none; border-radius: 3px;
    background: var(--accent, #ff6a44); color: #fff; font-weight: 600; font-size: 13px; cursor: pointer;
  }
  .invite-send:hover:not(:disabled) { filter: brightness(1.08); }
  .invite-send:disabled { opacity: .45; cursor: default; }
  .invite-send-msg { min-height: 16px; margin-top: 9px; font-size: 11.5px; text-align: center; color: var(--faint); }
  .invite-send-msg.ok { color: #4bd486; }
  .invite-send-msg.err { color: #ff7676; }
  .acct-refresh { color: var(--faint); font-weight: 600; }
  .acct-refresh:hover { color: var(--text); }
  .acct-refresh .check { font-size: 12px; }
  .acct-refresh.busy { pointer-events: none; opacity: .7; }
  /* Spin the ICON, not its wrapper: the .check span is 17px wide but the glyph is
     13px, so rotating the span orbited the box centre and the icon wobbled off-centre.
     transform-box: fill-box pins the origin to the SVG's own box → true centre spin. */
  .acct-refresh.busy .check { display: inline-flex; align-items: center; justify-content: center; }
  .acct-refresh.busy .check svg { animation: acctSpin .7s linear infinite; transform-origin: center; transform-box: fill-box; }
  @keyframes acctSpin { to { transform: rotate(360deg); } }
  /* compact per-account usage lines (5-hour + weekly limit) */
  /* READABILITY PASS (John, 2026-08-31: "the usage panel is too small — don't make it as
     big as Claude, but add some readability"). Everything below is a modest bump only:
     label 9→10px, numbers 10→11px, track 4→5px, row gap 2→4px, row line-height 7→10px.
     The panel keeps its compact multi-account shape; the digits and 5H/WEEK labels just
     stop being squint-small. */
  .acct-limits { display: flex; flex-direction: column; gap: 4px; padding: 2px 10px 8px 31px; cursor: pointer; border-radius: 3px; }

  /* line-height:1 (John, 2026-08-08 - the "make the rows sit together" fix): the row's
     text (.k/.v/.rst) used the browser's default line-height, which is taller than the
     7px cell squares, so each row carried invisible padding above/below its squares and
     the 5H/WEEK/FABLE lines read as floating apart even though the row gap itself is the
     same 2px as the gap BETWEEN squares. Pinning line-height to the cell height collapses
     that padding so the vertical rhythm between rows matches the horizontal rhythm
     between squares within a row. */
  .acct-limits .lim { display: flex; align-items: center; gap: 7px; font-size: 11px; line-height: 10px; color: var(--faint); }
  /* Wide enough for the longest server bucket label ("Wk Sonnet"); fixed + truncating
     so a longer/unknown bucket name can never push the bar or the % off the row. */
  .acct-limits .lim .k { flex: 0 0 auto; width: 46px; text-transform: uppercase; letter-spacing: .3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 10px; font-weight: 700; color: #fff; }
  /* USAGE STRIP (John, 2026-08-08): a row of real, evenly-spaced ROUNDED SQUARES, not a
     solid bar and not squashed rectangles. `aspect-ratio:1` forces each cell square at
     whatever width the 1fr track gives it, so they stay square on any row width; 3px gap
     + 3px radius match the designed mock. They fill left→right, the trail dims, the
     leading edge is brightest (and pulses only when that model is actively burning). */
  /* ONE FULL LINE (John, 2026-08-24: "revert this ... to one full line"). The segmented
     squares are gone; the meter is a single continuous track. The track itself is the
     100% extent — a faint fill you can always see the end of — and .lim-fill spans the
     used %. In light mode the track is a solid very-light gray so the full length is
     visible against white. */
  .acct-limits .lim .cells { flex: 1; position: relative; height: 5px; border-radius: 999px;
    background: rgba(255,255,255,.11); overflow: visible; min-width: 0; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .acct-limits .lim .cells { background: rgba(0,0,0,.08); }
  .acct-limits .lim .cells .lim-fill { position: absolute; left: 0; top: 0; bottom: 0;
    width: 0; border-radius: 999px; background: var(--accent); transition: width .2s ease; }
  .acct-limits .lim .cells .lim-fill.empty { background: transparent; }
  /* The leading edge pulses only while this model is actively generating on this account. */
  .acct-limits .lim .cells .lim-fill.live { animation: limLeadPulse 1.15s ease-in-out infinite; }
  @keyframes limLeadPulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
  /* PACE MARK: where you SHOULD be by now on an even spend. One thin vertical line marking
     a POSITION on the bar, nothing more; it never recolours with how far ahead/behind. */
  .acct-limits .lim .cells .lim-pace { position: absolute; top: -2px; bottom: -2px; left: 0;
    width: 1.5px; margin-left: -0.75px; background: #fff; border-radius: 999px; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .acct-limits .lim .cells .lim-pace { background: rgba(0,0,0,.55); }
  .acct-limits .lim .v { flex: 0 0 auto; width: 34px; text-align: right; font-variant-numeric: tabular-nums; font-size: 11px; color: #fff; }
  .acct-limits .lim .rst { flex: 0 0 auto; min-width: 28px; text-align: right; color: #fff; font-variant-numeric: tabular-nums; font-size: 11px; }
  .acct-limits .lim .rst:not(:empty)::before { content: "↺ "; opacity: .7; }
  /* A model-tinted row — colour comes from the engine/model catalog via --lim-tint, set
     in JS, so it always matches that model's chip. EVERY row is tinted now (John,
     2026-08-15: "I want that usage bar to follow the Model color"): the account's own
     engine hue, with Fable's row overriding to Fable's tone. Declared BEFORE .high so a
     >= 90% limit warning still overrides it in red. Only the squares wear the tint; the
     label stays the same faint grey as every other row (John, 2026-07-25). */
  .acct-limits .lim.tinted .cells .lim-fill { background: var(--lim-tint); }
  .acct-limits .lim.high .cells .lim-fill { background: #e5484d; }
  .acct-limits .lim.high .v { color: #e5484d; }
  .acct-limits .lim.muted .v { opacity: .55; }
  /* Why a meter isn't live. Wraps rather than truncating — a reason you can't read is
     no better than the silent stale number it replaced (screen-width discipline). */
  .acct-limits .lim-err { font-size: 11px; color: #e0704a; line-height: 1.35; padding-top: 2px; overflow-wrap: anywhere; }
  /* When the reason is a re-login, the line IS the fix — click it. */
  .acct-limits .lim-err.fixable { cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
  .acct-limits .lim-err.fixable:hover { color: #ff8a63; }
  /* A soft/transient note (meter throttled) is informational, not an error — mute it
     to the same faint grey as the rows so it doesn't read as "your account is broken". */
  .acct-limits .lim-err.soft { color: var(--faint); }
  /* drag-to-reorder accounts */
  .acct-item[draggable="true"] { cursor: grab; }
  .acct-item.dragging { opacity: .4; }
  .acct-item.drop-target { box-shadow: inset 0 2px 0 var(--accent); border-radius: 3px; }
  .acct-cloud { display: flex; align-items: center; gap: 8px; padding: 5px 8px; font-size: 11px; color: var(--faint); }
  .acct-cloud .dot { width: 7px; height: 7px; border-radius: 2px; background: var(--faint); flex: 0 0 auto; }
  .acct-cloud .dot.on { background: #45e3b0; }
  .acct-cloud .lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .acct-item .ow-sync { color: var(--faint); font-size: 13px; padding: 0 3px; border-radius: 3px; opacity: .7; }
  .acct-card:hover .ow-sync { opacity: 1; }
  .acct-item .ow-sync:hover { color: var(--accent); background: var(--active); }
  /* combined sync line: [red mark] Mobile Synced [↻]  ......  email (right) */
  .cloud-row .cloud-lbl { flex: 0 0 auto; }
  .cloud-row .cloud-email { margin-left: auto; padding-left: 12px; color: var(--faint); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; max-width: 62%; }
  .acct-item .ow-sync.spin { animation: owspin .7s linear infinite; }
  @keyframes owspin { to { transform: rotate(360deg); } }

  /* phone-chats read-only viewer */
  .pc-back { position: fixed; inset: 0; background: rgba(0,0,0,0.55); z-index: 4000; display: flex; align-items: center; justify-content: center; }
  .pc-panel { width: 460px; max-width: 92vw; max-height: 80vh; background: #141414; border: 1px solid var(--line); border-radius: 3px; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 18px 60px rgba(0,0,0,var(--sh50, 0.5)); }
  .pc-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px; border-bottom: 1px solid var(--line); font-weight: 600; color: #fff; font-size: 14px; }
  .pc-head .pc-x { cursor: pointer; color: var(--faint); font-size: 13px; padding: 2px 6px; border-radius: 3px; }
  .pc-head .pc-x:hover { color: #fff; background: var(--hover); }
  .pc-body { overflow-y: auto; padding: 6px; }
  .pc-empty { padding: 26px 18px; color: var(--faint); font-size: 12.5px; text-align: center; line-height: 1.5; }
  .pc-row { padding: 10px 12px; border-radius: 3px; cursor: pointer; }
  .pc-row:hover { background: var(--hover); }
  .pc-title { color: #eee; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .pc-meta { color: var(--faint); font-size: 10.5px; margin-top: 2px; }
  .pc-backrow { color: var(--accent); font-size: 12px; }
  .pc-thread { display: flex; flex-direction: column; gap: 8px; padding: 8px; }
  .pc-msg { padding: 8px 11px; border-radius: 3px; font-size: 12.5px; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; max-width: 88%; }
  .pc-msg.user { align-self: flex-end; background: var(--accent); color: #fff; }
  .pc-msg.assistant { align-self: flex-start; background: #222; color: #e6e6e6; }

  /* modal tabs + fields */
  .tabs { display: flex; gap: 6px; margin-bottom: 14px; }
  .tab {
    flex: 1; background: var(--panel-2); color: var(--muted);
    border: 1px solid var(--line); border-radius: 3px; padding: 7px; font-size: 12.5px; cursor: pointer;
  }
  .tab.active { color: var(--text); border-color: var(--accent); background: var(--accent-soft); }
  .fld { display: block; color: var(--faint); font-size: 11px; margin: 12px 0 5px; text-transform: uppercase; letter-spacing: .5px; }
  .save.wide { width: 100%; padding: 9px; margin-top: 12px; }
  .login-status { margin-top: 12px; padding: 9px 11px; border-radius: 3px; background: var(--panel-2); border: 1px solid var(--line); color: var(--muted); font-size: 12.5px; }
  .paste-link { margin-top: 12px; color: var(--faint); font-size: 11.5px; cursor: pointer; text-decoration: underline; }
  .paste-link:hover { color: var(--accent); }

  /* sidebar footer: account avatar (left) + settings gear (right) */
  .side-footer { flex: 0 0 auto; margin-top: auto; border-top: 1px solid var(--line); padding: 6px 10px; display: flex; align-items: center; justify-content: space-between; position: relative; }
  .side-foot-right { display: flex; align-items: center; gap: 6px; }
  .gear-btn {
    background: transparent; color: var(--muted); border: 1px solid var(--line);
    border-radius: 3px; width: 32px; height: 30px; cursor: pointer; font-size: 15px; line-height: 1;
  }
  .gear-btn:hover { color: var(--accent); background: var(--hover); }

  /* Luminair cloud identity: round avatar with the user's initial */
  .ow-avatar {
    display: flex; align-items: center; justify-content: center; position: relative;
    width: 30px; height: 30px; border-radius: 50%; cursor: pointer; padding: 0;
    background: var(--accent-soft, rgba(var(--accent-rgb),.18)); color: var(--text);   /* initial = ink, readable on any accent (John, 2026-08-24) */
    border: 1px solid var(--line); font-size: 13px; font-weight: 700; line-height: 1;
    text-transform: uppercase; user-select: none;
  }
  .ow-avatar:hover { border-color: var(--accent); }
  .ow-avatar.signed-out { background: transparent; color: var(--faint); }
  .ow-avatar .presence {
    position: absolute; right: -1px; bottom: -1px; width: 9px; height: 9px; border-radius: 50%;
    background: var(--faint); border: 2px solid var(--panel);
  }
  .ow-avatar.on .presence { background: #45e3b0; }
  /* New-user notification badge: brand-orange count pill on the account avatar. Hidden
     until a genuinely-new user appears; cleared when John opens the admin console. */
  .ow-avatar .ow-newbadge {
    position: absolute; top: -5px; right: -5px; min-width: 16px; height: 16px; padding: 0 4px;
    border-radius: 3px; background: var(--accent); color: #fff; font-size: 9px; font-weight: 800;
    line-height: 16px; text-align: center; border: 2px solid var(--panel); box-sizing: border-box;
    display: none; pointer-events: none; box-shadow: 0 0 0 1px rgba(var(--accent-rgb), .35);
  }
  .ow-avatar .ow-newbadge.show { display: block; animation: owNewPulse 2s ease-in-out infinite; }
  @keyframes owNewPulse {
    0%, 100% { box-shadow: 0 0 0 1px rgba(var(--accent-rgb), .35); }
    50% { box-shadow: none; }
  }

  /* cloud/sync popover, opens above the avatar.
     position: fixed (JS places it, same trick as .acct-menu) — the sidebar
     (aside) is `overflow: hidden` so it can collapse to the thin rail; an
     absolutely-positioned popover anchored inside it got clipped to that 56px
     box whenever the sidebar was minimized, which read as the popover sitting
     BEHIND the session pane instead of on top of it. Fixed positioning escapes
     that clip entirely and is never clipped by the sidebar's overflow. */
  .ow-menu {
    position: fixed; width: 244px;
    background: var(--panel); border: 1px solid var(--line); border-radius: 3px;
    padding: 6px; display: none; z-index: 40;
    box-shadow: 0 12px 30px rgba(0,0,0,var(--sh50, .5));
  }
  .ow-menu.show { display: block; }

  /* settings modal */
  .settings-sec-title { color: var(--faint); font-size: 10.5px; font-weight: 700; letter-spacing: .8px; text-transform: uppercase; margin: 4px 0 10px; }
  /* Tier gate: an upgrade banner + a dimmed, non-interactive section beneath it. The
     blocked feature stays visible on purpose (John, 2026-08-28: block, never remove). */
  .tier-gate { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding: 14px 16px; margin: 0 0 16px; border: 1px solid var(--accent); border-radius: 6px; background: var(--accent-soft); }
  .tier-gate-title { font-size: 13.5px; font-weight: 700; color: var(--text); }
  .tier-gate-sub { font-size: 12px; color: var(--muted); line-height: 1.5; }
  .set-page.tier-locked > :not(.tier-gate) { opacity: .4; pointer-events: none; filter: grayscale(.3); }
  .integ-row { display: flex; align-items: center; gap: 12px; background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 12px 14px; }
  .integ-info { flex: 1; min-width: 0; }
  .integ-name { font-size: 13.5px; font-weight: 600; }
  .integ-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
  .integ-sub.on { color: var(--accent); }

  /* ===== Settings modal (redesigned) ===== */
  /* A proper settings window: rectangle, side menu left, page right.
     Never taller than the window — the page scrolls inside. */
  .set-modal { width: 1120px; max-width: 94vw; height: 660px; max-height: 90vh; padding: 0; overflow: hidden; animation: setIn .2s ease-out; display: flex; flex-direction: column; }
  .set-modal .set-head { flex: 0 0 auto; }
  .set-cols { flex: 1; min-height: 0; display: flex; }
  /* Settings scaling now comes from the native page zoom (applySize), which covers
     the whole document including this modal — no per-element CSS zoom needed. */
  /* SETTINGS NAV (John, 2026-08-16 — modelled on the reference he sent): a flat list of
     10 equal labels gave no shape, so it now reads as GROUPS with an icon per row. The
     icon carries recognition, the group label carries structure, and a search box filters
     live — no page is more than one glance away. */
  .set-nav { flex: 0 0 186px; border-right: 1px solid var(--line); padding: 10px 8px 14px; display: flex; flex-direction: column; gap: 1px; background: var(--sidebar); overflow-y: auto; }
  .sn-search { position: relative; margin: 2px 3px 10px; flex: 0 0 auto; }
  .sn-search-ic { position: absolute; left: 9px; top: 50%; transform: translateY(-50%); width: 13px; height: 13px; color: var(--faint); pointer-events: none; }
  .sn-search input {
    width: 100%; box-sizing: border-box; padding: 7px 10px 7px 27px;
    background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px;
    color: var(--text); font-family: inherit; font-size: 12.5px; outline: none;
  }
  .sn-search input::placeholder { color: var(--faint); }
  .sn-search input:focus { border-color: rgba(var(--accent-rgb), .5); }
  /* Group heading: quiet, small, never clickable. */
  .sn-group {
    flex: 0 0 auto; padding: 12px 11px 5px; font-size: 10.5px; font-weight: 600;
    letter-spacing: .04em; color: var(--faint); user-select: none;
  }
  .sn-group:first-of-type { padding-top: 2px; }
  .set-nav-item {
    display: flex; align-items: center; gap: 9px;
    text-align: left; background: transparent; border: none; color: var(--muted);
    padding: 7px 11px; border-radius: 3px; font-size: 13px; font-weight: 500; cursor: pointer;
  }
  .sn-ic { flex: 0 0 auto; width: 15px; height: 15px; opacity: .85; }
  .sn-lbl { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .set-nav-item:hover { color: var(--text); background: var(--hover); }
  .set-nav-item.active { color: #fff; background: var(--active); font-weight: 600; }
  .set-nav-item.active .sn-ic { opacity: 1; color: var(--accent); }
  /* Search with no hits — says so instead of showing an empty column. */
  .sn-empty { padding: 10px 11px; font-size: 12px; color: var(--faint); }
  .sn-group[hidden], .set-nav-item[hidden], .sn-empty[hidden] { display: none; }
  .set-modal .set-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; }
  @keyframes setIn { from { opacity: 0; transform: translateY(6px) scale(.985); } to { opacity: 1; transform: none; } }
  .set-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 18px 14px; border-bottom: 1px solid var(--line); }
  .set-head h3 { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -.01em; }
  .set-x { background: transparent; border: none; color: var(--faint); font-size: 14px; width: 28px; height: 28px; border-radius: 3px; cursor: pointer; display: flex; align-items: center; justify-content: center; }
  .set-x:hover { color: var(--text); background: var(--hover); }
  .set-content { padding: 14px 18px 20px; }
  .set-content .settings-sec-title { margin: 0 0 9px; }
  .set-content .settings-sec-title.mt { margin-top: 20px; }

  /* Minimal settings — flat rows, no card boxes, no icon tiles. Adjacent rows get a
     hairline divider; a row that already has an explanatory hint below uses that for
     separation, so the page reads as a clean list instead of a stack of boxes. */
  .set-card { display: flex; align-items: center; gap: 16px; background: transparent; border: none; border-radius: 3px; padding: 11px 2px; }
  .set-card + .set-card { border-top: 1px solid var(--line); padding-top: 13px; }
  .set-ic { display: none; }
  .set-body { flex: 1; min-width: 0; }
  /* Settings look (John, 2026-08-04): the setting TITLE in our brand font (Brunea),
     the SUBTEXT in a plain regular font — clean, not the mono/global font. */
  .set-name { font-size: 14px; font-weight: 600; font-family: var(--ui-font); letter-spacing: .2px; }
  .beta-pill { font-size: 9px; font-weight: 800; letter-spacing: .6px; color: var(--accent); background: color-mix(in srgb, var(--accent) 15%, transparent); border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); border-radius: 3px; padding: 1px 5px; margin-left: 7px; vertical-align: middle; }
  .set-sub { font-size: 12px; color: var(--muted); margin-top: 3px; display: flex; align-items: center; gap: 6px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; letter-spacing: 0; }
  .set-status { display: inline-flex; align-items: center; gap: 6px; }
  .set-status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--faint); flex: 0 0 auto; }
  .set-status.on::before { background: #45e3b0; }
  .keycap { font-family: "SF Mono", ui-monospace, monospace; font-size: 11px; color: var(--text); background: var(--panel); border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 3px; padding: 1px 7px; }
  .sc-custom { color: var(--accent); font-weight: 600; }

  .set-actions { display: flex; gap: 8px; flex: 0 0 auto; }
  .btn-primary, .btn-ghost { border-radius: 3px; padding: 8px 14px; font-size: 12.5px; font-weight: 600; cursor: pointer; white-space: nowrap; }
  .btn-primary { background: var(--accent); color: var(--on-accent); border: none; }
  .btn-primary:hover { filter: brightness(1.06); }
  .btn-ghost { background: transparent; color: var(--muted); border: 1px solid var(--line); font-weight: 500; }
  .btn-ghost:hover { color: var(--text); background: var(--hover); border-color: #3a3a3a; }
  .btn-ghost.danger:hover { color: #e5484d; border-color: rgba(229,72,77,.5); background: rgba(229,72,77,.08); }
  .btn-ghost.sm { padding: 6px 11px; font-size: 12px; }
  .btn-primary.sm { padding: 6px 12px; font-size: 12px; }
  .set-modal button:focus-visible { outline: none; }

  /* Mobile Relay: 8-digit pairing code as 4 + 4 squares with a dash between. */
  .pair-code { display: flex; align-items: center; gap: 8px; margin: 14px 0 4px; flex-wrap: wrap; }
  .pair-cell { width: 40px; height: 52px; display: flex; align-items: center; justify-content: center; border: 1.5px solid var(--line); border-radius: 3px; background: var(--panel-2); font-family: "Bitcount", monospace; font-size: 30px; font-weight: 700; color: var(--accent); }
  .pair-dash { color: var(--muted); font-size: 26px; font-weight: 700; padding: 0 2px; }
  /* Pro+ gate: no code for non-entitled accounts — large light-gray asterisks instead. */
  .pair-code.pair-locked .pair-cell { color: color-mix(in srgb, var(--text) 22%, transparent); font-size: 34px; }
  .pair-code.pair-locked .pair-dash { color: color-mix(in srgb, var(--text) 22%, transparent); }
  /* Beta page "lab" empty-state — shown when no experiment is available yet (John, 2026-08-31). */
  .beta-lab { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 14px; padding: 54px 28px 46px; }
  .beta-lab-orb { position: relative; width: 82px; height: 82px; display: flex; align-items: center; justify-content: center;
    border-radius: 50%; color: var(--accent);
    background: radial-gradient(circle at 50% 45%, rgba(var(--accent-rgb), .22), rgba(var(--accent-rgb), .04) 70%);
    box-shadow: 0 0 0 1px rgba(var(--accent-rgb), .28) inset, 0 8px 30px rgba(var(--accent-rgb), .18); }
  .beta-lab-ring { position: absolute; inset: 0; border-radius: 50%; border: 1px solid rgba(var(--accent-rgb), .45);
    animation: betaPulse 2.8s ease-out infinite; }
  .beta-lab-ring.r2 { animation-delay: 1.4s; }
  @keyframes betaPulse { 0% { transform: scale(1); opacity: .55; } 100% { transform: scale(1.9); opacity: 0; } }
  .beta-lab-title { font-size: 19px; font-weight: 700; color: var(--text); letter-spacing: .2px; }
  .beta-lab-sub { max-width: 400px; font-size: 13px; line-height: 1.55; color: var(--muted); }
  @media (prefers-reduced-motion: reduce) { .beta-lab-ring { animation: none; opacity: .3; } }
  /* The fix lives in the error line itself: not-signed-in jumps straight to Account. */
  .pair-signin-link { background: none; border: 0; padding: 0; font: inherit; color: var(--accent); text-decoration: underline; cursor: pointer; }
  .pair-signin-link:hover { opacity: .82; }
  /* Armed state of New code — it retires the currently displayed capability. */
  #pairGenBtn.danger { color: #f2a08f; border-color: rgba(224,85,74,.5); }
  /* Connected devices — the phones linked to this account, by name */
  .relay-devices { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
  .rd-row { display: flex; align-items: center; gap: 11px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 3px; background: var(--panel-2); }
  .rd-dot { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; background: var(--muted); }
  .rd-dot.on { background: #4ade80; box-shadow: none; }
  .rd-body { flex: 1; min-width: 0; }
  .rd-name { font-size: 13.5px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rd-sub { font-size: 11.5px; color: var(--faint); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rd-meta { color: var(--muted); }
  .rd-remove { flex: 0 0 auto; border: 0; background: transparent; color: var(--faint); font-size: 11.5px; cursor: pointer; padding: 5px 7px; }
  .rd-remove:hover { color: #f2a08f; }
  .rd-remove:disabled { opacity: .55; cursor: default; }
  .set-hint { color: var(--faint); font-size: 11.5px; margin: 9px 2px 0; line-height: 1.5; }
  .router-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--faint); margin-right: 8px; vertical-align: 1px; }
  .router-dot.on { background: #3fb950; box-shadow: 0 0 0 3px rgba(63,185,80,.18); }
  .router-msg { color: var(--accent); margin: 0 2px 8px; }
  /* Router: direction cards + live CPU/memory charts + "who is pulling from this Mac"
     (John, 2026-09-06). Chart colours are the validated two-slot categorical pair
     (blue = CPU, orange = memory) stepped per theme; text never wears a series colour. */
  :root { --viz-cpu: #3987e5; --viz-mem: #d95926; --viz-net: #2bb5a0; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) { --viz-cpu: #2a78d6; --viz-mem: #c8501c; --viz-net: #178f7c; }
  .rt-dir { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 0 0 6px; }
  .rt-dir-card { border: 1px solid var(--line); border-radius: 6px; background: var(--panel-2); padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; transition: border-color .2s ease; }
  .rt-dir-card.on { border-color: rgba(var(--accent-rgb), .5); }
  .rt-dir-head { display: flex; align-items: center; gap: 10px; }
  .rt-dir-ic { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 6px; display: flex; align-items: center; justify-content: center; background: var(--panel); color: var(--muted); border: 1px solid var(--line); }
  .rt-dir-card.on .rt-dir-ic { color: var(--accent); background: var(--accent-soft); border-color: transparent; }
  .rt-dir-title { flex: 1; font-size: 13.5px; font-weight: 600; color: var(--text); }
  .rt-dir-card .set-sub { margin: 0; }
  .rt-dir-state { font-size: 11.5px; color: var(--faint); min-height: 14px; }
  .rt-dir-card.on .rt-dir-state { color: var(--muted); }
  .rt-dir-sub { display: flex; align-items: center; gap: 10px; padding-top: 8px; border-top: 1px solid var(--line); }
  .rt-dir-sub .set-sub { flex: 1; }
  .rt-dir-sub.dim { opacity: .5; }
  .rt-hero { border: 1px solid var(--line); border-radius: 6px; background: var(--panel-2); padding: 14px 14px 12px; margin-bottom: 8px; }
  .rt-tiles { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; margin-bottom: 12px; }
  .rt-tile { padding: 8px 10px; border-radius: 5px; background: var(--panel); border: 1px solid var(--line); min-width: 0; }
  .rt-tile-lbl { font-size: 10.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .rt-tile-val { font-size: 24px; font-weight: 700; color: var(--text); line-height: 1.15; margin-top: 2px; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .rt-tile-val small { font-size: 12px; font-weight: 500; color: var(--muted); margin-left: 3px; }
  .rt-tile-bar { height: 3px; border-radius: 2px; margin-top: 7px; background: var(--line); overflow: hidden; }
  .rt-tile-bar i { display: block; height: 100%; width: 0; transition: width .4s ease; }
  .rt-tile-bar.rt-cpu i { background: var(--viz-cpu); }
  .rt-tile-bar.rt-mem i { background: var(--viz-mem); }
  .rt-tile-bar.rt-ink i { background: var(--muted); }
  .rt-tile-bar.rt-net i { background: var(--viz-net); }
  .rt-tile-sub { font-size: 10.5px; color: var(--faint); margin-top: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
  .rt-legend { display: flex; align-items: center; gap: 14px; font-size: 11.5px; color: var(--muted); margin: 2px 0 4px; }
  .rt-legend b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
  .rt-key { display: inline-block; width: 14px; height: 3px; border-radius: 2px; vertical-align: middle; margin-right: 6px; }
  .rt-key.rt-cpu { background: var(--viz-cpu); }
  .rt-key.rt-mem { background: var(--viz-mem); }
  .rt-key.rt-net { background: var(--viz-net); }
  .rt-win { display: inline-flex; margin-left: auto; border: 1px solid var(--line); border-radius: 4px; overflow: hidden; }
  .rt-win button { appearance: none; border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 10.5px; font-weight: 600; padding: 2px 8px; cursor: pointer; }
  .rt-win button + button { border-left: 1px solid var(--line); }
  .rt-win button.on { background: var(--accent-soft); color: var(--accent); }
  .rt-win button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  .rt-legend .rt-win + .rt-live { margin-left: 10px; }
  .rt-live { margin-left: auto; color: #3fb950; font-size: 10.5px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; }
  .rt-live.off { color: var(--faint); }
  .rt-chart { position: relative; }
  .rt-svg { display: block; width: 100%; height: auto; }
  .rt-grid { stroke: var(--line); stroke-width: 1; }
  .rt-ax { fill: var(--faint); font-size: 10px; }
  .rt-empty { fill: var(--faint); font-size: 12px; }
  .rt-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
  .rt-line.rt-cpu, .rt-dot.rt-cpu { stroke: var(--viz-cpu); }
  .rt-line.rt-mem, .rt-dot.rt-mem { stroke: var(--viz-mem); }
  .rt-area.rt-cpu { fill: var(--viz-cpu); opacity: .10; }
  .rt-area.rt-mem { fill: var(--viz-mem); opacity: .10; }
  .rt-line.rt-net { stroke: var(--viz-net); stroke-width: 1.5; opacity: .9; }
  .rt-area.rt-net { fill: var(--viz-net); opacity: .14; }
  .rt-ax-net { fill: var(--viz-net); font-weight: 600; }
  .rt-dot { stroke-width: 2; fill: var(--panel-2); }
  .rt-end { fill: var(--text); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; }
  .rt-cross { stroke: var(--muted); stroke-width: 1; pointer-events: none; }
  .rt-tip { position: absolute; top: 4px; pointer-events: none; background: var(--panel); border: 1px solid var(--line); border-radius: 4px; padding: 5px 8px; font-size: 11px; color: var(--text); white-space: nowrap; box-shadow: 0 4px 14px rgba(0,0,0,.25); display: none; z-index: 2; font-variant-numeric: tabular-nums; }
  .rt-tip span { color: var(--muted); }
  .rt-pulls { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
  .rt-pulls-title { font-size: 10.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--faint); margin-bottom: 6px; display: flex; gap: 8px; align-items: center; }
  .rt-pulls-title b { color: var(--text); }
  .rt-strip-row { display: grid; grid-template-columns: 120px 1fr; gap: 8px; align-items: center; margin: 3px 0; }
  .rt-strip-name { font-size: 11.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rt-strip-name small { color: var(--faint); margin-left: 5px; }
  .rt-strip { display: block; width: 100%; height: 14px; }
  .rt-strip-bg { fill: var(--line); opacity: .45; }
  .rt-cell { fill: var(--text); }
  .rt-pull-rows { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
  .rt-pull-row { font-size: 11.5px; color: var(--muted); display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
  .rt-pull-row b { color: var(--text); font-weight: 600; }
  .rt-pull-now { display: inline-block; padding: 1px 7px; border-radius: 10px; background: var(--accent-soft); color: var(--accent); font-size: 10.5px; font-weight: 700; }
  .rt-items { display: flex; flex-direction: column; gap: 2px; margin: 4px 0 4px 12px; }
  .rt-item { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; align-items: center; font-size: 11px; color: var(--muted); }
  .rt-item.live .rt-item-meta { color: var(--accent); font-weight: 600; }
  .rt-kind { font-size: 9.5px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; padding: 1px 5px; border-radius: 3px; border: 1px solid var(--line); color: var(--faint); white-space: nowrap; }
  .rt-kind.run { color: var(--viz-mem); border-color: color-mix(in srgb, var(--viz-mem) 45%, transparent); }
  .rt-kind.model { color: var(--viz-cpu); border-color: color-mix(in srgb, var(--viz-cpu) 45%, transparent); }
  .rt-item-lbl { font-family: 'SF Mono', ui-monospace, monospace; font-size: 10.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rt-item-meta { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--faint); }
  .rt-sent { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); font-size: 11.5px; color: var(--muted); }
  .rt-sent-title { font-size: 10.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--faint); margin-right: 8px; }
  .rt-node { border: 1px solid var(--line); border-radius: 6px; background: var(--panel-2); padding: 12px 14px; margin-bottom: 10px; }
  .rt-node.off { opacity: .72; }
  .rt-node-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
  .rt-node-name { font-size: 13.5px; font-weight: 600; color: var(--text); white-space: nowrap; }
  .rt-node-meta { flex: 1; min-width: 0; font-size: 11.5px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rt-badge { font-size: 10.5px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; padding: 2px 7px; border-radius: 3px; border: 1px solid var(--line); color: var(--muted); white-space: nowrap; }
  .rt-badge.warn { color: #e0a53a; border-color: rgba(224,165,58,.45); }
  .rt-badge.ok { color: #3fb950; border-color: rgba(63,185,80,.4); }
  @media (max-width: 760px) { .rt-dir { grid-template-columns: 1fr; } .rt-tiles { grid-template-columns: repeat(3, 1fr); } }
  @media (prefers-reduced-motion: reduce) { .rt-tile-bar i, .rt-dir-card { transition: none; } }
  .set-hint code { background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 1px 5px; font-size: 11px; color: var(--text); }
  /* Account tab: label + input row that never runs past the panel edge (min-width:0 on the input). */
  .acct-row { display: flex; gap: 8px; align-items: center; margin-top: 9px; }
  .acct-row input { flex: 1; min-width: 0; background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; color: var(--text); padding: 8px 11px; font-size: 13px; }
  .acct-row input:focus { outline: none; border-color: var(--accent); }
  .acct-row .btn-primary, .acct-row .btn-ghost { flex: 0 0 auto; }
  .acct-email-now { color: var(--text); font-size: 13px; font-weight: 600; }
  .acct-status { font-size: 11.5px; line-height: 1.4; margin-top: 7px; min-height: 14px; overflow-wrap: anywhere; }
  .acct-status.ok { color: #4a9e6f; }
  .acct-status.err { color: #e5484d; }
  .set-link { color: var(--accent); cursor: pointer; text-decoration: none; }
  .set-link:hover { text-decoration: underline; }
  .set-field { display: flex; flex-direction: column; gap: 5px; }
  .set-field-lbl { font-size: 11.5px; font-weight: 600; color: var(--text); letter-spacing: 0.01em; }
  .set-field-req, .set-field-opt { font-weight: 500; color: var(--faint); }
  .set-field-desc { color: var(--faint); font-size: 11px; line-height: 1.5; }
  .set-field-desc code { background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 1px 5px; font-size: 10.5px; color: var(--text); }
  /* Integrations: key + command input rows */
  .set-keyrow { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
  .set-key-input { flex: 1; min-width: 0; background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 9px 11px; color: var(--text); font-family: inherit; font-size: 12.5px; }
  .set-key-input:focus { outline: none; border-color: var(--accent); }
  .set-key-input::placeholder { color: var(--faint); }
  .set-slash { color: var(--accent); font-weight: 700; font-size: 14px; padding: 0 2px; }
  .set-sec-label { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; margin: 20px 2px 4px; }
  .set-cmd { display: flex; align-items: center; gap: 10px; background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 9px 11px; margin-top: 8px; }
  .set-cmd .cmd-trig { color: var(--accent); font-weight: 600; }
  .set-cmd .cmd-meta { color: var(--faint); font-size: 11.5px; margin-left: auto; }
  .set-cmd .cmd-edit { flex: 1; min-width: 0; background: transparent; border: none; color: var(--accent); font-weight: 600; font-family: inherit; font-size: inherit; padding: 2px 0; cursor: text; }
  .set-cmd .cmd-edit:focus { outline: none; }
  .set-cmd .cmd-edit::placeholder { color: var(--faint); font-weight: 500; }
  .set-cmd.is-new { border-style: dashed; opacity: 0.85; }
  .set-cmd .cmd-model { flex-shrink: 0; margin-left: 4px; }
  /* Integrations: category-grouped connector CARDS. The page opens as a grid of
     tappable cards split by category (Marketing / Research); clicking a card opens
     that connector's full setup panel below it. Icon-free by design (matches the
     rest of the minimal settings). */
  /* Models / Augments tab bar (reuses .seg, just bigger + spaced). */
  .integ-tabs { margin: 2px 0 20px; }
  .integ-tabs button { font-size: 12.5px; padding: 6px 16px; }
  /* The Models tab is already labelled "Models", so drop the redundant subheading
     inside its panel — but keep the node in the DOM (applyModelsUI anchors on it). */
  .integ-tabpanel[data-tab="models"] > #integCatModels { display: none; }
  .integ-cat { color: var(--muted); font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; font-weight: 700; margin: 20px 2px 11px; }
  .integ-cat:first-of-type { margin-top: 2px; }
  .integ-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 12px; }
  .integ-card { text-align: left; background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 15px 16px; cursor: pointer; display: flex; flex-direction: column; gap: 8px; transition: border-color .12s, background .12s, transform .07s; font-family: inherit; }
  .integ-card:hover { border-color: rgba(var(--accent-rgb), .5); background: var(--hover); }
  .integ-card:active { transform: scale(.99); }
  .integ-card.active { border-color: var(--accent); background: rgba(var(--accent-rgb), .09); }
  .integ-card-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
  .integ-card-id { display: flex; align-items: center; gap: 9px; min-width: 0; }
  .integ-logo { width: 26px; height: 26px; border-radius: 3px; flex-shrink: 0; object-fit: cover; background: #fff; box-shadow: inset 0 0 0 1px rgba(255,255,255,.08); }
  .integ-card-name { font-size: 14px; font-weight: 650; color: var(--text); letter-spacing: -.01em; min-width: 0; }
  /* MCP / API / AUTH / LOCAL — what kind of connector this is, at a glance (John, 2026-08-20).
     MCP = exposed to the session directly as MCP tools. API = a `//command` the app runs
     server-side with a pasted key/token. AUTH = an interactive browser sign-in, no key pasted.
     LOCAL = a one-time local package install, no account at all. */
  .integ-tag { font-size: 9px; font-weight: 700; letter-spacing: .04em; padding: 2px 6px; border-radius: 3px; flex: 0 0 auto; text-transform: uppercase; }
  .integ-tag-mcp { color: #4aa3ff; background: rgba(74,163,255,.13); }
  .integ-tag-api { color: #45e3b0; background: rgba(69,227,176,.13); }
  .integ-tag-auth { color: #f2a08f; background: rgba(242,160,143,.13); }
  .integ-tag-local { color: var(--muted); background: rgba(255,255,255,.07); }
  .integ-tag-skill { color: #c99bff; background: rgba(201,155,255,.14); }
  .integ-card-sub { font-size: 11.5px; color: var(--muted); line-height: 1.45; }
  /* Sign-in status as a footer row, divided off from the blurb (John, 2026-08-17).
     margin-top:auto pins it to the bottom so every card's status line sits on the same
     baseline even when the blurbs are different lengths. */
  .integ-card-foot { margin-top: auto; padding-top: 9px; border-top: 1px solid var(--line); }
  .integ-card .set-status { font-size: 10.5px; color: var(--faint); font-weight: 600; flex: 0 0 auto; }
  .integ-card .set-status.on { color: #45e3b0; }
  /* Cloud-mode badge. Blue = this connector is connected server-side and runs with the
     Mac off; grey = it supports cloud mode but isn't connected yet. State is driven purely
     off the existing .set-status.on class via :has(), so no JS wiring can desync it.
     Connectors that are Mac-only (Higgsfield) carry no .integ-cloud badge at all. */
  .integ-cloud { display: inline-flex; align-items: center; color: var(--faint); opacity: .4; flex: 0 0 auto; transition: color .12s, opacity .12s; }
  .integ-cloud svg { display: block; }
  .integ-card-top .integ-cloud { margin-right: 5px; }
  /* Gated on body.cloud-on (set by applyAnthUI when Claude Cloud holds a key). Cloud
     mode is one master switch: with no key there is no server-side path at all, so a
     connected connector still can't run with the Mac off and its badge must stay grey.
     A lit badge therefore means "this really does work right now with the Mac off." */
  body.cloud-on .integ-card:has(.set-status.on) .integ-cloud { color: #4aa3ff; opacity: 1; }
  /* Legend row at the top of the connectors page. */
  .integ-legend { display: flex; align-items: center; gap: 8px; margin: 12px 2px 16px; font-size: 11.5px; color: var(--muted); line-height: 1.4; }
  body.cloud-on .integ-legend .integ-cloud { color: #4aa3ff; opacity: 1; }
  .integ-legend-txt { flex: 1; min-width: 0; }
  .integ-docs-link { color: var(--accent); text-decoration: none; font-weight: 600; white-space: nowrap; flex: 0 0 auto; }
  .integ-docs-link:hover { text-decoration: underline; }
  /* Detail panel: the chosen connector's full setup. It now lives inside the
     right-side drawer (see below), so it fills the drawer with no card chrome. */
  .integ-detail { border: 1px solid var(--line); border-radius: 3px; padding: 4px 16px 18px; margin-top: 14px; background: var(--panel); }
  .integ-drawer-body .integ-detail { border: none; border-radius: 3px; margin-top: 0; padding: 0 20px 20px; background: transparent; }

  /* Right-side detail drawer. A card click slides this in from the right EDGE of
     the settings content, so the detail lands next to what you clicked instead of
     stacking at the bottom. This is the default expand pattern for the modal. */
  .set-cols { position: relative; }
  .integ-scrim { position: absolute; inset: 0; background: rgba(0,0,0,.34); opacity: 0; pointer-events: none; transition: opacity .2s ease; z-index: 5; }
  .integ-scrim.open { opacity: 1; pointer-events: auto; }
  .integ-drawer { position: absolute; top: 0; right: 0; bottom: 0; width: 460px; max-width: 82%; background: var(--panel); border-left: 1px solid var(--line); box-shadow: -18px 0 40px rgba(0,0,0,var(--sh28, .28)); transform: translateX(100%); transition: transform .22s cubic-bezier(.22,.61,.36,1); z-index: 6; display: flex; flex-direction: column; }
  .integ-drawer.open { transform: none; }
  .integ-drawer-body { flex: 1; min-height: 0; overflow-y: auto; padding-top: 4px; }
  .integ-detail-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 13px 0 4px; }
  .integ-detail-title { font-size: 14.5px; font-weight: 650; letter-spacing: -.01em; }
  .integ-back { background: transparent; border: none; color: var(--muted); font-size: 12px; font-weight: 500; cursor: pointer; padding: 5px 9px; border-radius: 3px; font-family: inherit; }
  .integ-back:hover { color: var(--text); background: var(--hover); }
  /* Inside a detail panel the connect row sits flush under the head (no extra top gap). */
  .integ-detail .set-keyrow:first-of-type { margin-top: 6px; }
  /* Connected accounts inside an engine's detail panel: one row each, with the
     per-account actions John asked to see on the model side (John, 2026-08-15). */
  .integ-accts { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
  .integ-acct {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 11px; border: 1px solid var(--line); border-radius: 3px; background: var(--panel-2);
  }
  .integ-acct .ia-dot { width: 7px; height: 7px; border-radius: 50%; background: #3fb950; flex: none; }
  .integ-acct .ia-meta { display: flex; flex-direction: column; min-width: 0; margin-right: auto; }
  .integ-acct .ia-name { font-size: 13px; font-weight: 600; color: var(--text); }
  .integ-acct .ia-sub { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .integ-acct .ia-btn {
    flex: none; font-size: 12px; padding: 5px 10px; border-radius: 3px; cursor: pointer;
    border: 1px solid var(--line); background: var(--panel); color: var(--text);
  }
  .integ-acct .ia-btn:hover { border-color: var(--muted); }
  .integ-acct .ia-remove { color: #e5484d; border-color: color-mix(in srgb, #e5484d 40%, transparent); }
  .integ-acct .ia-remove:hover { background: color-mix(in srgb, #e5484d 12%, transparent); border-color: #e5484d; }
  /* Perplexity research sources block (rendered into a pane) */
  .pplx-sources { border-top: 1px solid var(--line); margin-top: 6px; padding-top: 10px; }
  .pplx-src-label { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; margin-bottom: 6px; }
  .pplx-src { font-size: 12.5px; line-height: 1.7; color: var(--muted); }
  /* Tap-to-run chip for a //command Claude emitted that SENDS or SPENDS (option C,
     John 2026-07-30). Read-only commands auto-run instead and never render a chip.
     Row mixes a flexible button + a fixed note, so both get the min-width:0 /
     flex-shrink:0 treatment — a long command truncates, it never busts the pane. */
  .runcmd-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
  .runcmd {
    flex: 1; min-width: 0; text-align: left;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-family: inherit; font-size: 12.5px; color: var(--accent);
    background: rgba(var(--accent-rgb), .10); border: 1px solid rgba(var(--accent-rgb), .38);
    border-radius: 3px; padding: 7px 11px; cursor: pointer;
    transition: background .12s ease, border-color .12s ease;
  }
  .runcmd:hover:not(:disabled) { background: rgba(var(--accent-rgb), .18); border-color: var(--accent); }
  .runcmd.ran, .runcmd:disabled {
    color: var(--muted); background: transparent; border-color: var(--line);
    cursor: default; opacity: .7;
  }
  .runcmd-note { flex-shrink: 0; font-size: 11px; color: var(--muted); }
  .runcmd.ran + .runcmd-note { visibility: hidden; }
  /* OpenAI generated image */
  .gen-img { max-width: min(440px, 100%); height: auto; border-radius: 3px; border: 1px solid var(--line); display: block; }
  /* Luminair commands learning pop-up (also reused by the header shortcuts palette) */
  .cmd-help-modal { width: 540px; display: flex; flex-direction: column; max-height: 82vh; }
  .cmd-help-list { margin: 14px 0 6px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
  .cmd-help-row { background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 11px 13px; }
  .cmd-help-top { display: flex; align-items: center; gap: 8px; }
  .cmd-help-name { font-family: var(--ui-font); font-size: 13px; font-weight: 700; color: var(--accent); letter-spacing: .2px; }
  .cmd-help-name.cloud { color: #ffaf2b; }   /* Claude / and skill commands = Opus yellow, matches composer highlight */
  /* No gray in these palettes (John): descriptions read in full body text; gray is
     reserved for the folder tree / sidebar. */
  .cmd-help-desc { color: var(--text); font-size: 12px; line-height: 1.55; margin-top: 5px; }
  /* Shortcuts palette: three tabs (Claude / Luminair / Custom) + section labels. */
  .shortcuts-modal .shortcuts-sub { color: var(--text); }
  .shortcuts-models { display: flex; flex-wrap: wrap; gap: 6px 10px; margin: 12px 0 2px; }
  .sc-model {
    display: inline-flex; align-items: center; gap: 6px;
    font-family: var(--ui-font); font-size: 11.5px; font-weight: 600; letter-spacing: .2px;
    color: var(--text-dim); opacity: .55;
  }
  .sc-model.on { color: var(--text); opacity: 1; }
  .sc-dot {
    width: 8px; height: 8px; border-radius: 50%;
    border: 1.5px solid var(--line); background: transparent; box-sizing: border-box;
  }
  .shortcuts-tabs { display: flex; gap: 6px; margin: 12px 0 2px; }
  .shortcuts-tab {
    flex: 1; padding: 7px 10px; border-radius: 3px; cursor: pointer;
    background: var(--panel-2); border: 1px solid var(--line); color: var(--text);
    font-family: var(--ui-font); font-size: 12px; font-weight: 600; letter-spacing: .2px;
    transition: background .12s, border-color .12s, color .12s;
  }
  .shortcuts-tab:hover { border-color: rgba(var(--accent-rgb), .4); }
  .shortcuts-tab.active { background: rgba(var(--accent-rgb), .16); border-color: var(--accent); color: var(--accent); }
  .shortcuts-sec {
    font-family: var(--ui-font); font-size: 10.5px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .6px; color: var(--text); margin: 4px 2px -2px;
  }
  /* Shortcuts palette: filter box above the (Luminair + Claude) command list */
  .shortcuts-modal .cmd-help-list { min-height: 120px; }
  .shortcuts-search {
    width: 100%; box-sizing: border-box; margin-top: 10px; padding: 9px 11px;
    background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px;
    color: var(--text); font-size: 13px; font-family: var(--ui-font);
  }
  .shortcuts-search:focus { outline: none; border-color: var(--accent); }
  .shortcuts-empty { color: var(--text); font-size: 12.5px; padding: 6px 2px; line-height: 1.5; grid-column: 1 / -1; }
  /* ---- Skills / Directives panel = the same settings-sized modal as Master Controller
     (John, 2026-07-26): a wide horizontal rectangle whose card list is a 2-column grid
     that scrolls vertically, instead of the old narrow single-column popup. ---- */
  .shortcuts-modal { width: 900px; max-width: 94vw; height: 680px; max-height: 88vh; }
  .shortcuts-modal .cmd-help-list {
    flex: 1; min-height: 0; margin-top: 12px;
    display: grid; grid-template-columns: 1fr 1fr; gap: 9px; align-content: start;
  }
  .shortcuts-modal .cmd-help-row { height: 100%; box-sizing: border-box; }
  /* Section labels ("Commands" / "Skills") span the full width so the grid resets under them. */
  .shortcuts-modal .shortcuts-sec { grid-column: 1 / -1; margin: 6px 2px -1px; }
  .shortcuts-modal .shortcuts-sec:first-child { margin-top: 0; }
  @media (max-width: 560px) { .shortcuts-modal .cmd-help-list { grid-template-columns: 1fr; } }
  /* "New automation" create form */
  .auto-modal { width: 480px; display: flex; flex-direction: column; }
  .auto-lbl { display: flex; align-items: center; gap: 8px; font-size: 11px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; color: var(--muted); margin: 13px 0 5px; }
  .auto-in, .auto-ta {
    width: 100%; box-sizing: border-box; background: var(--panel-2); border: 1px solid var(--line);
    border-radius: 3px; padding: 9px 11px; color: var(--text); font-family: inherit; font-size: 13px; resize: vertical;
  }
  .auto-in:focus, .auto-ta:focus { border-color: var(--accent); }
  .auto-sum-ta { color: var(--text); }
  .auto-sum-gen {
    margin-left: auto; background: var(--accent-soft); color: var(--accent); border: none; cursor: pointer;
    border-radius: 3px; padding: 3px 8px; font-size: 10px; font-weight: 700; letter-spacing: .2px; text-transform: none;
  }
  .auto-sum-gen:hover { filter: brightness(1.08); }
  .auto-sum-gen:disabled { opacity: .6; cursor: default; }
  .auto-err { color: #e0736a; font-size: 12px; min-height: 16px; margin: 8px 0 0; }
  .set-perm { color: #e0a04a; font-size: 11.5px; margin: 9px 2px 0; line-height: 1.55; }
  .set-perm-act { display: block; margin-top: 8px; }
  /* permissions checklist */
  .perm-list { display: flex; flex-direction: column; gap: 6px; }
  .perm-row { display: flex; align-items: center; gap: 9px; background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; padding: 9px 12px; }
  .perm-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--faint); flex: 0 0 auto; }
  .perm-row.on .perm-dot { background: #45e3b0; }
  .perm-row.off .perm-dot { background: #e5484d; }
  .perm-name { font-size: 12.5px; font-weight: 600; flex: 0 0 auto; }
  .perm-why { flex: 1; min-width: 0; font-size: 11px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* granted (green): no action needed — hide BOTH the "Open" and "Allow" buttons, show a "Granted" tag instead */
  .perm-row.on .perm-open, .perm-row.on .perm-req { display: none; }
  .perm-row.on::after { content: "Granted"; flex: 0 0 auto; font-size: 11px; font-weight: 600; color: #45e3b0; }
  /* segmented control (session sort) */
  .seg { display: inline-flex; background: var(--panel); border: 1px solid var(--line); border-radius: 3px; padding: 2px; gap: 2px; flex: 0 0 auto; }
  .seg button { background: transparent; border: none; color: var(--muted); font-size: 11.5px; padding: 4px 9px; border-radius: 3px; cursor: pointer; font-weight: 500; }
  .seg button:hover { color: var(--text); }
  .seg button.active { background: var(--accent); color: var(--on-accent); font-weight: 600; }
  .seg.seg-wrap { flex-wrap: wrap; justify-content: flex-end; max-width: 300px; }
  /* Settings dropdown (Interface font): native select styled to match .seg; each option
     renders in its own typeface via inline font-family. */
  .set-select { background: var(--panel); border: 1px solid var(--line); border-radius: 3px;
    color: var(--text); font-size: 12px; padding: 5px 26px 5px 9px; cursor: pointer;
    font-weight: 500; flex: 0 0 auto; min-width: 150px; -webkit-appearance: none; appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' stroke='%238a8a8a' stroke-width='1.5' fill='none' stroke-linecap='round'/></svg>");
    background-repeat: no-repeat; background-position: right 9px center; }
  .set-select:hover { border-color: var(--accent); }
  .set-select:focus { outline: none; border-color: var(--accent); }
  /* Accent-color picker: round colour swatches; the active one gets a white ring. */
  .accent-seg { gap: 8px; padding: 3px; background: transparent; border: none; flex-wrap: wrap; }
  .accent-seg .accent-break { flex-basis: 100%; height: 0; margin: 0; padding: 0; }
  .accent-seg button { width: 20px; height: 20px; padding: 0; border-radius: 50%; background: var(--sw); border: 2px solid transparent; box-shadow: inset 0 0 0 1px rgba(0,0,0,var(--shEdge, .35)); transition: transform .1s ease; }
  .accent-seg button:hover { transform: scale(1.12); background: var(--sw); }
  .accent-seg button.active { border-color: #fff; }
  /* Theme-preset chips: rounded pill split diagonally — bg tint on one half, accent on the other. */
  .preset-seg { gap: 8px; padding: 3px; background: transparent; border: none; flex-wrap: wrap; }
  .preset-seg button { width: 34px; height: 22px; padding: 0; border-radius: 6px; border: 2px solid transparent; box-shadow: inset 0 0 0 1px rgba(0,0,0,var(--shEdge, .35)); transition: transform .1s ease; background: linear-gradient(115deg, var(--pbg) 0 55%, var(--pac) 55% 100%); }
  .preset-seg button:hover { transform: scale(1.08); }
  .preset-seg button.active { border-color: #fff; }
  .preset-seg button.preset-none { width: auto; padding: 0 10px; background: var(--panel-2); border-color: var(--line); color: var(--muted); font-size: 12px; font-weight: 600; box-shadow: none; }
  .preset-seg button.preset-none.active { border-color: var(--accent); color: var(--text); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .preset-seg button.active { border-color: var(--text); }
  /* session drag-reorder insertion line */
  .row.session.drop-before-s::before, .row.session.drop-after-s::after {
    content: ''; position: absolute; left: 0; right: 0; height: 2px; background: var(--accent); border-radius: 3px;
  }
  .row.session.drop-before-s::before { top: -1px; }
  .row.session.drop-after-s::after { bottom: -1px; }

  /* composer mic button (minimal) */
  .composer .pmic {
    background: transparent; color: var(--muted); border: none; padding: 0;
    width: 28px; height: 36px; cursor: pointer; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .composer .pmic:hover { color: var(--text); }
  .composer .pmic.recording { color: var(--accent); animation: micpulse 1.1s ease-in-out infinite; }
  .composer .pmic.busy { opacity: .45; }
  @keyframes micpulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

  /* Stop button: only visible while the pane is running. Tiny square. Wears the session's
     custom colour when one is set, matching the queue badge (John, 2026-08-24: "make sure
     the square also does"); falls back to the neutral muted/line when the pane is untinted. */
  .composer .pstop {
    display: none; background: transparent; color: var(--pane-tint-solid, var(--muted));
    border: 1px solid var(--pane-tint-solid, var(--line)); border-radius: 3px; padding: 0;
    width: 28px; height: 28px; align-self: flex-end; cursor: pointer; flex: 0 0 auto;
    align-items: center; justify-content: center;
  }
  .pane.running .composer .pstop { display: inline-flex; }
  .composer .pstop:hover { color: var(--pane-tint-solid, var(--accent)); border-color: var(--pane-tint-solid, var(--accent)); background: var(--hover); }
  .composer .pstop.stopping { opacity: .4; pointer-events: none; }
  /* BETA Live conversation entry button — only when the beta toggle is on, hidden while a reply runs */
  .composer .pvoice {
    display: none; background: transparent; color: var(--muted);
    border: 1px solid var(--line); border-radius: 3px; padding: 0;
    width: 28px; height: 28px; align-self: flex-end; cursor: pointer; flex: 0 0 auto;
    align-items: center; justify-content: center;
  }
  /* Conversational (Live voice) hidden for now, John 2026-08-15 — was: display: inline-flex */
  body.live-voice-on .pane:not(.running) .composer .pvoice { display: none; }
  .composer .pvoice:hover { color: var(--accent); border-color: var(--accent); background: var(--hover); }

  /* Text selection uses the brand color, not the OS blue. Translucent accent fill so
     the highlighted text stays readable; --accent-rgb follows the accent picker. */
  ::selection { background: rgba(var(--accent-rgb), .32); color: #fff; }
  ::-moz-selection { background: rgba(var(--accent-rgb), .32); color: #fff; }
  ::-webkit-scrollbar { width: 9px; }
  ::-webkit-scrollbar-thumb { background: #2f2f2f; border-radius: 3px; border: 2px solid transparent; background-clip: padding-box; }

  /* terminal drawer */
  .term-toggle { font-family: 'SF Mono', ui-monospace, monospace; font-size: 12px; font-weight: 700; letter-spacing: 1px; }
  .term-toggle.active { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
  /* Terminal is a CENTERED POP-UP (was a right-side drawer that widened the whole
     window). A dim, softly-blurred scrim sits behind it; click the scrim or hit ESC
     to close. It floats over the app — it never pushes or resizes anything. */
  #termBackdrop {
    position: fixed; inset: 0;
    background: rgba(0,0,0,.55);
    -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
    opacity: 0; pointer-events: none;
    transition: opacity .14s ease-out;
    z-index: 59;
  }
  body.term-open #termBackdrop { opacity: 1; pointer-events: auto; }
  #termDrawer {
    position: fixed; top: 50%; left: 50%;
    width: min(880px, 92vw); height: min(70vh, 560px);
    background: #0a0a0a;
    border: 1px solid var(--line); border-radius: 3px;
    box-shadow: 0 26px 90px rgba(0,0,0,var(--sh62, .62)), 0 0 0 1px rgba(255,255,255,.03);
    overflow: hidden;
    display: flex; flex-direction: column;
    opacity: 0; pointer-events: none;
    transform: translate(-50%, -50%) scale(.96);
    transition: opacity .14s ease-out, transform .14s ease-out;
    z-index: 60;
  }
  body.term-open #termDrawer { opacity: 1; pointer-events: auto; transform: translate(-50%, -50%) scale(1); }
  .term-head {
    -webkit-app-region: no-drag;
    flex: 0 0 auto; height: 46px;
    display: flex; align-items: center; gap: 8px;
    padding: 0 10px 0 16px;
    border-bottom: 1px solid var(--line);
    background: var(--panel);
  }
  .term-title { font-family: 'Bitcount', monospace; font-size: 12px; letter-spacing: 2px; color: var(--muted); flex: 1; user-select: none; }
  .term-x {
    -webkit-app-region: no-drag;
    background: transparent; color: var(--faint);
    border: none; cursor: pointer; font-size: 14px;
    width: 26px; height: 26px; border-radius: 3px;
    display: flex; align-items: center; justify-content: center;
  }
  .term-x:hover { color: var(--text); background: var(--hover); }
  #termBody { flex: 1 1 auto; min-height: 0; padding: 8px 6px 8px 12px; background: #0a0a0a; overflow: hidden; }
  #termBody .xterm { height: 100%; }
  /* Terminal cursor = the SAME retro CRT block as the app's "thinking" caret
     (.term-cursor): orange, fine horizontal scanlines cut through it, soft bloom.
     Replaces xterm's flat block fill. The #termBody prefix boosts specificity so it
     beats xterm's own injected cursor color (which it sets with !important on the
     non-blink variant). We keep the blink via OPACITY (term-blink) because the
     scanline background is force-locked with !important. */
  #termBody .xterm .xterm-cursor-block,
  #termBody .xterm .xterm-cursor-block:not(.xterm-cursor-blink) {
    background:
      repeating-linear-gradient(to bottom, transparent 0 2px, rgba(0,0,0,.30) 2px 3px),
      var(--accent) !important;
    color: #0a0a0a !important;          /* glyph under the block stays legible on orange */
    box-shadow: none;
    border-radius: 3px;
  }
  #termBody .xterm .xterm-cursor-block.xterm-cursor-blink {
    animation: term-blink 1.06s steps(1, end) infinite !important;
  }
  .xterm .xterm-viewport::-webkit-scrollbar { width: 9px; }

  /* ===== Active Sessions (top of sidebar) ===== */
  #activeWrap { border-bottom: 1px solid var(--line); }
  /* Divider between Open branches and Active Sessions — same 1px line as elsewhere.
     Only when Open branches is actually showing (they're adjacent siblings); when it's
     hidden, activeWrap sits under .side-top whose own border-bottom is the line, so we
     don't double it up. */
  #sideBranches:not([hidden]) + #activeWrap { border-top: 1px solid var(--line); }
  .active-list { padding: 0 0 6px; }
  .active-row { display: flex; align-items: center; gap: 7px; margin: 0 8px 0; padding: 2px 2px 2px 7px; border-radius: 0; cursor: pointer; box-shadow: inset 0 1px 0 color-mix(in srgb, var(--text) 8%, transparent); }   /* 2px right (was 7): trim the gap after the status word (John, 2026-09-08); tiny top highlight 2026-09-15; rows tightened 7px to 4px vertical, 2px to 1px gap (John, 2026-09-22), then 4px to 2px with no gap between rows (John, 2026-09-22) */
  .active-row:hover { background: var(--hover); }
  .active-row.active { background: var(--active); }
  /* when a session is selected, the OTHER active sessions read at ~70% intensity */
  .active-row:not(.active) .meta, .active-row:not(.active) .astatus { opacity: .7; }
  /* window-closed sessions we still track: same row, but the name reads dimmer so
     it's clear they're active-in-the-background, not open in view. */
  .active-row.bg .sname { color: rgba(255,255,255,.62); font-style: italic; }
  .active-row .meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0; }
  .active-row .sname { font-size: 13px; font-weight: 400; color: rgba(255,255,255,.8); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }   /* match the regular session rows */
  .active-row .asub { font-size: 8.5px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .active-row .astatus { font-size: 8.5px; }
  /* device glyph — laptop = this Mac, phone = mobile. Muted so it reads as metadata. */
  .active-row .adevice { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 13px; height: 13px; color: var(--faint); opacity: .8; }
  .active-row .adevice svg { width: 13px; height: 13px; display: block; }
  .active-row.foreign .adevice { color: var(--accent); opacity: 1; }   /* on another device → accent, so it stands out */
  body.collapsed .active-row .adevice { display: none; }

  /* ---- Relay connection LED (John, 2026-09-14) ------------------------------
     Shown ONLY on a relay/connected row — a session (or, later, a folder) that
     lives on another computer or your phone. A local row has no .aconn at all.
     While the relay is actively transferring it flickers fast and irregularly,
     like an old modem's activity light. Reused by the folder tree's relay rows. */
  .aconn { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 9px; height: 14px; margin-right: 4px; color: var(--relay-led, #35c46a); opacity: .92; }
  .aconn svg { width: 9px; height: 14px; display: block; }
  .aconn.xfer { animation: aconn-xfer .82s steps(1, end) infinite; }
  .active-list .active-row:nth-child(3n) .aconn.xfer { animation-duration: .66s; }
  .active-list .active-row:nth-child(3n+1) .aconn.xfer { animation-duration: .95s; }
  @keyframes aconn-xfer {
    0%{opacity:1} 7%{opacity:.15} 13%{opacity:1} 21%{opacity:.2} 29%{opacity:.9}
    37%{opacity:.15} 46%{opacity:1} 54%{opacity:.25} 62%{opacity:.85} 70%{opacity:.1}
    78%{opacity:1} 85%{opacity:.3} 92%{opacity:1} 100%{opacity:.45}
  }
  @media (prefers-reduced-motion: reduce) { .aconn.xfer { animation: none; opacity: 1; } }
  body.collapsed .active-row .aconn { display: none; }

  /* Active Sessions subsections: "This computer" and "Relay", each collapsible. */
  .active-subhead { display: flex; align-items: center; gap: 5px; padding: 6px 10px 3px 12px; cursor: pointer; user-select: none; }
  .active-subhead .sec-caret { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 12px; height: 12px; margin: 0 1px 0 -2px; padding: 0; border: 0; background: none; color: var(--faint); transform: rotate(90deg); transition: transform .12s ease, color .12s; cursor: pointer; }
  .active-subhead .sec-caret svg { display: block; }
  .active-subhead:hover .sec-caret { color: var(--accent); }
  .active-subsec.collapsed .active-subhead .sec-caret { transform: rotate(0deg); }
  .active-sublabel { flex: 1 1 auto; min-width: 0; font-size: 9px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .active-subcount { flex: 0 0 auto; font-size: 9px; color: var(--faint); opacity: .7; }

  /* Folder tree subsections: "This computer" and "Relay", each collapsible (relay
     grouping, 2026-09-14). Same look as the Active Sessions subheads, indented to the
     folder rows. */
  .folder-subhead { display: flex; align-items: center; gap: 5px; padding: 8px 10px 3px 14px; cursor: pointer; user-select: none; }
  .folder-subhead .sec-caret { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 12px; height: 12px; margin: 0 1px 0 -2px; padding: 0; border: 0; background: none; color: var(--faint); transform: rotate(90deg); transition: transform .12s ease, color .12s; cursor: pointer; }
  .folder-subhead .sec-caret svg { display: block; }
  .folder-subhead:hover .sec-caret { color: var(--accent); }
  .folder-subhead.collapsed .sec-caret { transform: rotate(0deg); }
  .folder-sublabel { flex: 1 1 auto; min-width: 0; font-size: 9px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .folder-subcount { flex: 0 0 auto; font-size: 9px; color: var(--faint); opacity: .7; }
  /* Relay LED on a folder row: reuses .aconn, sized to sit beside the folder icon. Jitter
     the flicker per row so a column of relay folders reads like independent modem lights. */
  .row.folder .fconn { width: 8px; height: 13px; margin-right: 4px; }
  .row.folder .fconn svg { width: 8px; height: 13px; }
  .folder-item:nth-child(3n) .fconn.xfer { animation-duration: .7s; }
  .folder-item:nth-child(3n+1) .fconn.xfer { animation-duration: .95s; }
  body.collapsed .row.folder .aconn { display: none; }
  /* Computer-to-computer relay: the Runs-on chip in a pane head names the session's home
     computer (grey while that computer is asleep); the asleep card offers Wake. */
  .pane-head .prelay { display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto; max-width: 150px; height: 18px; padding: 0 7px 0 5px; margin-right: 4px; border: 1px solid var(--accent); border-radius: 9px; color: var(--accent); font-size: 10.5px; font-weight: 600; letter-spacing: .1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; opacity: .95; }
  .pane-head .prelay svg { width: 11px; height: 11px; flex: 0 0 auto; }
  .pane-head .prelay span { overflow: hidden; text-overflow: ellipsis; }
  .pane-head .prelay.off { border-color: var(--line); color: var(--faint); }
  .pane.minimized .pane-head .prelay span, .pane-head.tight .prelay span { display: none; }
  .msg.relay-wake { display: flex; align-items: center; gap: 9px; margin: 10px 14px; padding: 9px 12px; border: 1px solid var(--line); border-radius: 10px; background: #0002; color: var(--muted); font-size: 12.5px; }
  .msg.relay-wake .rw-ico { display: inline-flex; color: var(--faint); }
  .msg.relay-wake .rw-ico svg { width: 14px; height: 14px; }
  .msg.relay-wake .rw-text { flex: 1 1 auto; }
  .msg.relay-wake .rw-wake { flex: 0 0 auto; padding: 4px 11px; border: 1px solid var(--accent); border-radius: 8px; background: transparent; color: var(--accent); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; }
  .msg.relay-wake .rw-wake:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
  .msg.relay-wake .rw-wake:disabled { opacity: .6; cursor: default; }
  .row.session.cloud-session.relay-session { opacity: 1; }
  .row.session.cloud-session.relay-session .cloud-badge { display: none; }
  /* ---- branch-out agents nested under their session, joined by a tree line ---- */
  /* CAP AT 8 ROWS, THEN SCROLL (John, 2026-09-04): a single session can stack dozens of
     "Agent · …" sub-rows (a 40-agent translation run filled the whole sidebar and pushed
     the folder tree off the bottom with no way to reach it). --asub-row-h is one sub-row's
     real height (4+4 padding + the 13px status line); eight is an exact stop and the 9th
     peeks so you can tell there's more to scroll. Overflow scrolls WITHIN the agent list,
     so the folders below always keep their room. */
  .active-subs { position: relative; margin: -2px 8px 2px 8px; --asub-row-h: 21px; max-height: calc(var(--asub-row-h) * 8); overflow-y: auto; overflow-x: hidden; scrollbar-width: auto; }   /* tail gap = the same 2px as every row */
  .active-subs::-webkit-scrollbar { width: 8px; }
  .active-subs::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
  .active-subs::-webkit-scrollbar-thumb:hover { background: var(--muted); }
  .active-subs::-webkit-scrollbar-track { background: transparent; }
  .active-row.sub { margin: 0; padding: 2px 9px 2px 28px; border-radius: 3px; }
  /* Hover X on a session row (John, 2026-07-30) — close a session from the sidebar.
     The slot is RESERVED PERMANENTLY (padding-right) and the button is absolutely
     positioned in it, instead of being a third flex child that only exists on hover.
     Why: .astatus is display:none unconditionally (name-only side panel, John
     2026-07-28), so there is no label for the X to replace — a hover-only flex child
     would steal 17px from the title and visibly re-ellipsis it under the cursor
     (measured: 208px -> 187px). Reserving the space costs those pixels once and the
     row never moves. Scoped to :not(.sub): agent/job sub-rows share .active-row but
     aren't sessions and get no X. */
  .active-row:not(.sub) { position: relative; padding-right: 12px; }   /* was 26: the status word (THINKING) sat far off the right edge with tons of empty space; move it right (John, 2026-09-14). The hover-X is absolute so it can overlap the status on hover without shifting the title. */
  .active-row:not(.sub) .arow-x { display: none; position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
    align-items: center; justify-content: center; width: 17px; height: 17px; padding: 0; border: 0; border-radius: 3px;
    background: transparent; color: var(--faint); cursor: pointer; }
  .active-row:not(.sub):hover .arow-x { display: flex; }
  .active-row:not(.sub) .arow-x:hover { background: rgba(255,255,255,.1); color: var(--text); }
  body.collapsed .active-row .arow-x { display: none !important; }   /* rail is dot-only — no room, and no row to aim at */
  .active-row.sub .sname { font-size: 11px; color: rgba(255,255,255,.66); }
  .active-row.sub .adot { width: 6px; height: 6px; }
  .active-row.sub .astatus { font-size: 8px; opacity: .85; }
  /* the trunk: a vertical line running through each agent row (x aligns under the parent dot) */
  .active-row.sub::before { content: ''; position: absolute; left: 12px; top: 0; bottom: 0; width: 1px; background: var(--line); }
  .active-row.sub.last::before { bottom: 50%; }   /* last agent: trunk ends at its elbow */
  body.collapsed .active-subs { display: none; }   /* no room for the tree when rail is collapsed */
  /* Collapse toggle for a session's nested agent/job rows (open by default). */
  .active-row .asub-caret { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 13px; height: 13px; margin: 0 1px 0 -3px; padding: 0; border: 0; background: none; color: var(--faint); cursor: pointer; border-radius: 3px; transform: rotate(90deg); transition: transform .12s ease, color .12s; }   /* open = caret points down */
  .active-row .asub-caret:hover { color: var(--accent); background: #0003; }
  .active-row.subs-collapsed .asub-caret { transform: rotate(0deg); }   /* collapsed = points right */
  .active-row.subs-collapsed + .active-subs { display: none; }
  /* ---- tab-group: sessions tabbed together are strung on ONE vertical line ----
     No box, no horizontal fence — the tabbed sessions read as one group joined by a
     vertical spine running through their status dots (same trunk as the branch-out
     tree). Order already mirrors the tab strip. (John, 2026-07-27) */
  .active-row.grouped { position: relative; }   /* keep the uniform 4px gap; spine bridges it below */
  /* the spine: a 1px vertical line at the dot's x, linking every tab in the group.
     top/bottom stretch past the row's own margin so the line stays UNBROKEN across the gap. */
  /* Sits on the STATUS DOT, not under the device glyph, and is 2px like the folder rail
     (John, 2026-09-10). The dot's x shifts right when the Pro+ device icon is present, so
     :has(.adevice) re-anchors the spine to the dot in that layout. */
  .active-row.grouped::before { content: ''; position: absolute; left: 10px; top: -2px; bottom: -2px; width: 2px; border-radius: 3px; background: var(--line); z-index: 0; }
  .active-row.grouped:has(.adevice)::before { left: 30px; }   /* device glyph pushes the dot right — follow it */
  .active-row.grouped.group-first::before { top: 50%; }    /* first tab: line starts at its dot */
  .active-row.grouped.group-last::before { bottom: 50%; }  /* last tab: line ends at its dot */
  .active-row.grouped .adot { position: relative; z-index: 1; }   /* dots sit ON the spine */
  body.collapsed .active-row.grouped::before { display: none; }   /* no room for the spine when the rail is collapsed */
  /* No own margin — the row's flex `gap:7px` already spaces the dot from the name; the
     extra 3px doubled it into an uneven gap (John, 2026-08-27). */
  /* The dot ALWAYS wears its session's MODEL colour, in every state (John, 2026-08-29:
     "show the colour of the model ALL THE TIME"). tintDotToModel() sets --dot-c per row;
     it falls back to the status colour only when the model is unknown. Error stays red. */
  .adot { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; background: var(--dot-c, var(--faint)); }
  .aspec { display: inline-flex; align-items: center; flex: 0 0 auto; color: var(--accent); margin-right: 6px; }
  .steam { display: inline-flex; align-items: center; flex: 0 0 auto; color: var(--accent); margin-right: 5px; opacity: .9; }
  .steam svg { width: 11px; height: 11px; }
  .row.session .steam { margin-right: 4px; }
  .pane-head .steam { margin: 0 5px 0 1px; }
  body.collapsed .steam { margin-right: 0; }
  .aspec svg { width: 12px; height: 12px; }
  body.collapsed .aspec { margin-right: 0; }
  /* The blinking dot wears the SESSION'S MODEL colour (John, 2026-07-30) — Fable 5
     purple, Sonnet blue, Haiku mint, Opus orange. renderer.js tintDotToModel() sets
     --dot-c per row; --dot-work is the fallback, and Opus 4.8's colour IS --dot-work,
     so Opus sessions look identical to before. Only THIS state is model-tinted —
     waiting/idle/error below keep their fixed status colours on purpose. */
  /* Working session dot = the custom ACCENT (John, 2026-08-24: "Working sessions also"),
     not the model tint / fixed orange it used before. Job rows still override to gold below. */
  .adot.thinking { background: var(--dot-c, var(--accent)); animation: micpulse 1.1s ease-in-out infinite; }
  /* Background jobs blink GOLD, not the model colour (John, 2026-07-30) — same gold as the
     "N jobs" chip (--bo-lt), so a job reads as a job everywhere it appears. Outranks the
     model-tinted rule above on specificity (4 classes vs 2). */
  .active-row.job-sub .adot.thinking { background: var(--bo-lt); }
  .adot.waiting { background: var(--dot-c, #45e3b0); }
  .adot.error { background: #ff2d20; }   /* error ALWAYS red — an alert must never read as a model colour */
  /* IDLE IS ALWAYS GREEN (John, 2026-09-03: "when idle, they need to be green dots on the
     left panel"). tintDotToModel sets --dot-c on every row, so the old var(--dot-c, green)
     fallback never fired and idle wore the model colour (orange). The model colour is
     for a session that's WORKING; a resting session reads green, full stop. */
  .adot.idle { background: #45e3b0; }
  /* SAME SIZE, orange == green (John, asked repeatedly): the working/orange indicator used the
     global micpulse (opacity → .35), so a fading orange read SMALLER than the solid full-opacity
     green "done" dot/square even though both are the exact same pixel box. Inside the branch-out
     card the working state now uses bo-work — a gentle pulse whose floor is .72, so orange keeps
     the same visual weight/size as the solid green at every frame. Scoped to branch-out only;
     the app-wide micpulse is untouched. */
  @keyframes bo-work { 0%, 100% { opacity: 1; } 50% { opacity: .72; } }
  .bo-subs .adot.thinking, .bo-sub .adot.thinking { animation: bo-work 1.2s ease-in-out infinite; }
  .ag-sq.running { animation: bo-work 1.2s ease-in-out infinite; }
  .astatus { font-size: 9.5px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; flex: 0 0 auto; }
  .astatus.thinking { color: var(--accent); }
  .astatus.waiting { color: #45e3b0; }
  .astatus.error { color: #e0736a; }
  .astatus.idle { color: var(--faint); }   /* done & idle: listed, but dim and dot-less */

  /* ===== resizable panes + sidebar ===== */
  .gutter { flex: 0 0 auto; background: transparent; position: relative; z-index: 5; }
  .gutter-row { width: 6px; margin: 0 -3px; cursor: col-resize; }
  .gutter-col { height: 6px; margin: -3px 0; cursor: row-resize; }
  /* A thin GRAY divider line centered in the resize hit-area — always visible so
     panes read as separated. It turns ORANGE (the active accent) while you hover
     or drag it. */
  .gutter::before { content: ''; position: absolute; background: var(--line); transition: background .12s; pointer-events: none; }
  .gutter-row::before { top: 0; bottom: 0; left: 50%; width: 1px; transform: translateX(-50%); }
  .gutter-col::before { left: 0; right: 0; top: 50%; height: 1px; transform: translateY(-50%); }
  .gutter:hover::before, body.resizing .gutter-row:hover::before, body.resizing .gutter-col:hover::before { background: var(--accent); }
  body.resizing { user-select: none; }
  .side-gutter { position: absolute; top: 0; right: -3px; width: 6px; height: 100%; cursor: col-resize; z-index: 20; transition: background .1s; }
  .side-gutter:hover { background: rgba(var(--accent-rgb),.4); }
  body.collapsed .side-gutter { display: none; }

  /* ===== jump-to-latest pill =====
     Floats ABOVE THE WHOLE INPUT BLOCK, not just the composer — that block's
     height changes (branch-out/queued chip row, reply-chip, voice status, image
     attachments, multi-line textarea all add rows above the send button), so the
     pill can't use a fixed offset or it ends up buried in/behind that stack. JS
     (ResizeObserver on .pane-composer) keeps --composer-h current; the pill just
     rides on top of it with a fixed gap. */
  .jump-latest {
    position: absolute; left: 50%; transform: translateX(-50%);
    bottom: calc(var(--composer-h, 64px) + 14px);
    /* VISIBLE ENOUGH TO FIND (John, 2026-08-16: "isn't super visible"). It was panel-grey
       on a dark transcript with a grey hairline — it read as background. Now it wears the
       accent: tinted fill, accent border and accent text, so it announces itself without
       shouting. Padding is symmetric: `display: flex` + centring makes the arrow and the
       word one centred row, so the 6px/12px inset is identical top-to-bottom and
       left-to-right instead of the text sitting off-centre inside a block button. */
    display: none; z-index: 15;
    align-items: center; justify-content: center; gap: 5px;
    /* MATCHES THE CONTEXT CARD EXACTLY (John, 2026-08-18): same fill, same border, same
       type. It was a heavier accent-filled pill with its own bolder 11.5px face, so the
       two floating surfaces read as different components. Now: .015 accent wash, .30
       accent hairline, #fff text at the card's 13px * --chat-scale with its line-height
       and letter-spacing. Only the layout (centred row, padding) stays button-specific. */
    background: var(--panel-2);   /* opaque, same surface as the Context Card */
    color: #fff;
    border: 1px solid rgba(var(--accent-rgb), .30); border-radius: 3px;
    padding: 8px 12px; line-height: 1.5; letter-spacing: .3px;
    font-size: 13px; font-weight: 400; cursor: pointer;
    /* Same black drop shadow as the Context Card (John, 2026-08-17) so both floating
       surfaces read as one layer above the transcript. */
    box-shadow: 0 4px 10px rgba(0,0,0,var(--sh55, .28)), 0 1px 3px rgba(0,0,0,var(--sh40, .2));
    transition: bottom .12s ease, background .12s ease, border-color .12s ease;
  }
  .jump-latest.show { display: inline-flex; }   /* flex so the arrow + word centre as one row */
  .jump-latest:hover { border-color: rgba(var(--accent-rgb), .5); }   /* same hover as .ctx-pop */

  /* branch-out: a bordered button, same treatment as the intensity button */
  .pane-head .pfork {
    -webkit-app-region: no-drag;
    flex: 0 0 auto; background: transparent; cursor: pointer;
    color: var(--faint); display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--line); border-radius: 3px; padding: 3px 6px; margin-left: 4px;
  }
  .pane-head .pfork svg { width: 14px; height: 14px; }
  .pane-head .pfork:hover { color: var(--accent); background: var(--hover); border-color: #3a3a3a; }

  /* The // Directives affordance next to a session's title (shown when it carries Directives) */
  .pane-head .pdirectives {
    -webkit-app-region: no-drag;
    flex: 0 0 auto; cursor: pointer; margin-left: 6px;
    display: inline-flex; align-items: center; justify-content: center;
    font-family: "SF Mono", ui-monospace, monospace; font-size: 11px; font-weight: 700; line-height: 1;
    letter-spacing: -0.5px; color: var(--accent);
    background: color-mix(in srgb, var(--accent) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
    border-radius: 3px; padding: 3px 6px;
  }
  .pane-head .pdirectives[hidden] { display: none; }
  .pane-head .pdirectives:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); border-color: var(--accent); }
  .pane-head.compact .pdirectives { display: none; }

  /* Journal affordance next to the title — matches the fork button's weight */
  .pane-head .pscrap {
    -webkit-app-region: no-drag;
    flex: 0 0 auto; background: transparent; cursor: pointer;
    color: var(--faint); display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--line); border-radius: 3px; padding: 3px 6px; margin-left: 4px;
  }
  .pane-head .pscrap svg { width: 15px; height: 15px; }
  .pane-head .pscrap:hover { color: var(--accent); background: var(--hover); border-color: #3a3a3a; }
  /* PERMANENT, like the ⋯ menu (John, 2026-08-15): "the button should always be
     visible". It never folds away on a narrow pane and never folds into the ⋯ menu —
     the session's journal doc is one click from every title bar, at every width.
     flex:0 0 auto (above) keeps it from being squeezed out; the title shrinks instead. */
  .pane-head .pscrap, .pane-head.compact .pscrap { display: inline-flex; }

  /* Pinned-messages affordance — same weight/placement as .pscrap, right next to it */
  .pane-head .ppins {
    -webkit-app-region: no-drag;
    flex: 0 0 auto; background: transparent; cursor: pointer;
    color: var(--faint); display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--line); border-radius: 3px; padding: 3px 6px; margin-left: 4px;
  }
  .pane-head .ppins svg { width: 14px; height: 14px; }
  .pane-head .ppins:hover { color: var(--accent); background: var(--hover); border-color: #3a3a3a; }
  .pane-head .ppins, .pane-head.compact .ppins { display: inline-flex; }   /* permanent, like .pscrap */
  .pins-pop {
    position: fixed; z-index: 500; width: 280px; max-height: 320px; overflow-y: auto;
    background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
    box-shadow: 0 10px 28px rgba(0,0,0,.35); padding: 6px;
  }
  .pins-empty { padding: 10px 8px; font-size: 12px; color: var(--muted); }
  .pins-row {
    display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-radius: 5px; cursor: default;
  }
  .pins-row:hover { background: var(--hover); }
  .pins-snip { flex: 1 1 auto; font-size: 12px; color: var(--text); cursor: pointer; line-height: 1.35; }
  .pins-x {
    flex: 0 0 auto; width: 18px; height: 18px; padding: 0; line-height: 1;
    border: 1px solid var(--line); border-radius: 3px; background: transparent;
    color: var(--muted); font-size: 11px; cursor: pointer;
  }
  .pins-x:hover { color: #ff6b57; border-color: #ff6b57; }
  @keyframes pinFlash { 0%, 100% { background: transparent; } 30% { background: rgba(255,180,84,.22); } }
  .pin-jump-flash { animation: pinFlash 1.1s ease; }

  /* ⌄ fork switcher: sits just left of the session title, only shown when a pane has forks */
  .pane-head .pvariants, .tab-actions .pvariants {
    -webkit-app-region: no-drag;
    flex: 0 0 auto; background: transparent; cursor: pointer;
    color: var(--muted); display: none; align-items: center; justify-content: center;
    border: 1px solid var(--line); border-radius: 3px; padding: 3px 4px; margin-right: 2px;
  }
  .tab-actions .pvariants { display: inline-flex; margin-right: 6px; }
  .pane-head .pvariants svg, .tab-actions .pvariants svg { width: 13px; height: 13px; }
  .pane-head .pvariants:hover, .tab-actions .pvariants:hover { color: var(--accent); background: var(--hover); border-color: #3a3a3a; }

  /* ===== slash-command / skill autocomplete ===== */
  .slash-menu {
    position: fixed; z-index: 70; max-height: 320px; overflow-y: auto;
    background: var(--panel); border: 1px solid var(--line); border-radius: 3px;
    padding: 5px; box-shadow: 0 14px 34px rgba(0,0,0,var(--sh55, .55));
  }
  .slash-item {
    display: flex; align-items: center; gap: 9px;
    padding: 7px 9px; border-radius: 3px; cursor: pointer; white-space: nowrap;
  }
  .slash-item.active, .slash-item:hover { background: var(--hover); }
  .slash-name {
    font-family: "SF Mono", ui-monospace, monospace; font-size: 12.5px;
    color: #ffaf2b; flex: 0 0 auto; font-weight: 600;   /* Claude command = Opus yellow */
  }
  .slash-kind {
    flex: 0 0 auto; font-size: 9px; font-weight: 700; letter-spacing: .4px;
    text-transform: uppercase; padding: 2px 5px; border-radius: 3px;
    color: var(--text); border: 1px solid var(--line);   /* no gray text (John) */
  }
  .slash-kind.skill { color: #ffaf2b; border-color: rgba(255,175,43,.35); }   /* Claude skill = Opus yellow */
  .slash-kind.cmd { color: #ffaf2b; border-color: rgba(255,175,43,.35); }   /* Claude / command = Opus yellow */
  .slash-kind.owm { color: var(--accent); border-color: rgba(var(--accent-rgb),.45); }   /* Luminair app = orange */
  .slash-kind.custom { color: var(--accent); border-color: rgba(var(--accent-rgb),.45); }   /* user // shortcut = orange */
  .slash-kind.macro { color: #5b8def; border-color: rgba(91,141,239,.45); }   /* /// directive = Sonnet blue (John, 2026-07-31) */
  .slash-name.owm { color: var(--accent); }
  .slash-name.macro { color: #5b8def; }   /* /// directive = Sonnet blue */
  .slash-name.sbdoc { color: #a78bfa; }   /* [[Journal doc]] = purple, matches the doc-link render color */
  .slash-kind.sbdoc { color: #a78bfa; border-color: rgba(167,139,250,.4); }   /* Journal DOC badge = purple */
  .slash-desc {
    flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
    font-size: 12px; color: var(--muted);
  }

  /* ===== tabbed pane block (drag a session onto the title bar) ===== */
  .block {
    flex: 1 1 0; display: flex; flex-direction: column; min-width: 0; min-height: 0;
    position: relative; border-right: 2px solid var(--line); border-bottom: 2px solid var(--line);
  }
  .block .pane.in-tabblock { flex: 1 1 0; border: none; }
  /* In a tab, the pane KEEPS its header as a control toolbar directly under the tab
     strip, so queue-flow, model, intensity and size-cap stay reachable (John, 2026-07-27).
     The header ALSO shows the active session's full title + status dot + status WORD
     here (tabs stay compact so all of them stay clickable — John, 2026-07-28). Hidden:
     the pane-close ✕ (the chip has its own ✕ → closeTab) and fork/variants (they live
     in .tab-actions on the strip). The control cluster on the right stays and acts on
     this pane. */
  .block .pane.in-tabblock .pane-head .pvariants,
  .block .pane.in-tabblock .pane-head .pfork,
  .block .pane.in-tabblock .pane-head .pclose { display: none; }
  /* The status word lives in the title bar and only appears when tabbed (a single
     pane's head already reads its title fine, so it stays hidden there). */
  /* Tabs show the session NAME ONLY (John, 2026-07-28) — the status is the dot + the
     hover tooltip now, never a word. (Reverses the earlier in-tab status word.) */
  .pane-head .phstatus { display: none; }
  .tab-strip {
    flex: 0 0 auto; display: flex; align-items: stretch; height: 30px;
    background: var(--panel); border-bottom: 1px solid var(--line); padding: 0 6px 0 4px; gap: 4px;
    cursor: grab;   /* the empty strip background is a handle to drag the whole group */
  }
  .tab-strip.group-drag { cursor: grabbing; }
  /* Edge fades hint at more tabs to scroll to. Drop the fade on whichever edge is
     already at the end — a first/last tab shows in full, no gradient (John, 2026-09-07).
     JS toggles .at-start / .at-end by scrollLeft; each var carries that edge's two stops. */
  .tab-list { flex: 1 1 auto; display: flex; align-items: flex-end; gap: 3px; overflow-x: auto; min-width: 0; scrollbar-width: none; -ms-overflow-style: none; --tl-l: transparent 0, #000 14px; --tl-r: #000 calc(100% - 14px), transparent 100%; -webkit-mask-image: linear-gradient(to right, var(--tl-l), var(--tl-r)); mask-image: linear-gradient(to right, var(--tl-l), var(--tl-r)); }
  .tab-list.at-start { --tl-l: #000 0, #000 0; }
  .tab-list.at-end { --tl-r: #000 100%, #000 100%; }
  .tab-list::-webkit-scrollbar { height: 0; width: 0; display: none; }
  .tab-chip {
    flex: 0 0 auto; display: flex; align-items: center; gap: 6px;   /* size to full name; tab-list scrolls (John, 2026-09-05) */
    padding: 5px 8px; margin-top: 2px; border-radius: 3px; cursor: pointer;
    color: var(--muted); font-size: 12px; border: 1px solid transparent; border-bottom: none;
  }
  .tab-chip:hover { background: var(--hover); }
  .tab-chip.active { background: var(--panel-2); color: #fff; border-color: var(--line); }
  /* Per-session tint carried onto the tab chip (applyChipTint sets --chip-tint).
     ONLY the ACTIVE tab wears its colour (John, 2026-09-01: "non-active tabs should
     not have a color"). An inactive tinted chip stays neutral like any other tab; on
     hover it just gets the standard --hover, not its model tint. The active chip's
     tint matches the pane head (same --chip-tint / left→right fade). */
  .tab-chip.tinted:not(.active) { background: var(--pane-tint-bg, transparent); }
  .tab-chip.tinted:not(.active):hover { background: var(--hover); }
  .tab-chip.tinted.active {
    background: linear-gradient(90deg, transparent 0%, var(--head-fade) 100%), var(--chip-tint);
    color: #fff; border-color: var(--line);
  }
  .tab-chip .tc-name { flex: 0 0 auto; white-space: nowrap; }   /* full name, tab-list scrolls horizontally (John, 2026-09-05) */
  /* Option B — Dot + clipped name (John, 2026-07-29): the ACTIVE tab keeps its REAL
     name instead of collapsing to a bare dot (or a monogram) — just clipped short and
     ALWAYS visible, so it carries more context while staying compact. Double-click the
     name still renames. ✕ shows on hover only (rule below). */
  .tab-chip.active .tc-name { display: block; }
  /* Tab dot wears the session's MODEL colour — the same --dot-c tintDotToModel() sets on the
     sidebar rows — so a tab matches its model status colour idle AND running (John, 2026-08-31:
     "the tab still doesn't get the right model status color"). Falls back to faint when the
     model is unknown, accent while running. */
  .tab-chip .tc-dot { width: 6px; height: 6px; border-radius: 2px; flex: 0 0 auto; background: var(--dot-c, var(--faint)); }
  .tab-chip.running .tc-dot { background: var(--dot-c, var(--accent)); animation: micpulse 1.1s ease-in-out infinite; }
  .tab-chip .tc-dot.error { background: #e0554a; }   /* stopped / broke / errored → red, model colour aside */
  .tab-chip .tc-x { flex: 0 0 auto; opacity: 0; color: var(--faint); font-size: 11px; padding: 1px 4px; border-radius: 3px; }
  .tab-chip:hover .tc-x { opacity: 1; }   /* ✕ on hover only — active tab now shows its name, not a permanent ✕ */
  .tab-chip .tc-x:hover { color: var(--accent); background: var(--active); }
  .tab-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 2px; }
  .tab-actions .pfork {
    -webkit-app-region: no-drag; flex: 0 0 auto; background: transparent; border: none; cursor: pointer;
    color: var(--muted); display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 24px; padding: 0; border-radius: 3px;
  }
  .tab-actions .pfork svg { width: 17px; height: 17px; }
  .tab-actions .pfork:hover { color: var(--accent); background: var(--hover); }
  .tab-actions .pfolder { color: var(--faint); font-size: 11.5px; cursor: pointer; padding: 3px 6px; border-radius: 3px; white-space: nowrap; }
  .tab-actions .pfolder:hover { color: var(--accent); background: var(--hover); }
  .tab-strip.drop-tab { box-shadow: none; background: var(--accent-soft); }
  /* dragging a tab left/right to REORDER it within its own strip */
  .tab-chip.tab-drag { opacity: .4; }
  .tab-chip.drop-before { box-shadow: inset 2px 0 0 0 var(--accent); }   /* insert to this tab's LEFT */
  .tab-chip.drop-after  { box-shadow: inset -2px 0 0 0 var(--accent); }  /* insert to this tab's RIGHT */

  /* ===== pasted-image attachments (composer) ===== */
  .pane-attach { display: none; flex-wrap: wrap; gap: 6px; padding: 0 2px 8px; }
  .attach-thumb { position: relative; width: 52px; height: 52px; border-radius: 3px; overflow: hidden; border: 1px solid var(--line); }
  .attach-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .attach-thumb .at-x {
    position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%;
    background: rgba(0,0,0,.62); color: #fff; font-size: 10px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
  }
  .attach-thumb .at-x:hover { background: var(--accent); }

  /* ===== queue image viewer: click the picture glyph on a queued request ===== */
  .img-viewer {
    display: none; position: fixed; inset: 0; z-index: 9999; background: rgba(0,0,0,.85);
    align-items: center; justify-content: center; padding: 48px;
  }
  .img-viewer.open { display: flex; }
  .img-viewer .iv-body { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; justify-content: center; max-width: 92vw; max-height: 88vh; overflow: auto; }
  .img-viewer .iv-body img { max-width: min(78vw, 680px); max-height: 82vh; object-fit: contain; border-radius: 3px; border: 1px solid var(--line); }
  .img-viewer .iv-close {
    position: absolute; top: 16px; right: 20px; background: transparent; border: none; color: #fff;
    font-size: 20px; line-height: 1; cursor: pointer; opacity: .75; width: 32px; height: 32px; border-radius: 3px;
  }
  .img-viewer .iv-close:hover { opacity: 1; background: rgba(255,255,255,.1); }
  .msg.user .msg-imgs { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 6px; justify-content: flex-start; }
  /* An attached image shows as a clear, obvious thumbnail (same language as the
     composer attach chips + the mobile app) so you can always SEE there's an image.
     Click the message to expand each thumbnail to full size, and back. */
  .msg.user .msg-img {
    display: block; width: 64px; height: 64px; object-fit: cover; object-position: top;
    border-radius: 3px; border: 1px solid var(--line); cursor: pointer;
    box-shadow: 0 1px 5px rgba(0,0,0,var(--sh30, .3));
  }
  .msg.user.expanded .msg-img {
    width: auto; height: auto; max-width: min(320px, 100%); max-height: 340px;
    object-fit: contain;
  }

  /* ===== Luminair Pro paywall ===== */
  .pw-overlay {
    position: fixed; inset: 0; z-index: 9999; overflow: hidden;
    background: radial-gradient(1100px 760px at 50% 38%, #170d0a 0%, #0a0a0a 62%);
    display: flex; align-items: center; justify-content: center;
    -webkit-app-region: drag;   /* let the user still move the window */
    /* The paywall is INTENTIONALLY dark (brand splash) in every app theme. In light
       mode --text/--muted/--line resolve to dark values, so every var(--text) label,
       price and feature went dark-on-dark and vanished (John, 2026-08-29). Pin the
       dark-theme token values inside the overlay so the paywall reads in both modes. */
    --text: #f2f2f2;
    --muted: #9a9a9a;
    --line: #2a2a2a;
    --accent-soft: rgba(var(--accent-rgb), .16);
  }
  /* Static orange glow — animation removed (John, 2026-07-25). The breathing pulse
     and the rotating sweep are gone; a still, centered glow remains. */
  .pw-overlay::before {
    content: ''; position: absolute; left: 50%; top: 40%; width: 820px; height: 820px;
    transform: translate(-50%,-50%); pointer-events: none; filter: blur(14px);
    background: radial-gradient(circle, rgba(var(--accent-rgb),.34) 0%, rgba(var(--accent-rgb),.07) 42%, transparent 70%);
  }
  /* rotating sweep removed entirely */
  .pw-overlay::after { display: none; }
  @keyframes pwBreathe { 0%,100% { opacity: .75; transform: translate(-50%,-50%) scale(1); } 50% { opacity: 1; transform: translate(-50%,-50%) scale(1.13); } }
  @keyframes pwSweep { to { transform: translate(-50%,-50%) rotate(360deg); } }
  @media (prefers-reduced-motion: reduce) { .pw-overlay::before, .pw-overlay::after { animation: none; } }
  /* Brand login (mobile parity): the phone's sign-in screen, exactly — flat
     near-black with the LIVE canvas grain+glow backdrop. .brand suppresses the
     old breathing-glow/sweep pseudos; the canvas IS the effect. */
  .pw-overlay.brand { background: #0a0a0a; }
  .pw-overlay.brand::before, .pw-overlay.brand::after { display: none; }
  .pw-brand-bg { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
  /* ---- desktop login gate (#cc-overlay): video background + bigger logo + orange
     glowing CTA (John, 2026-07-24). All scoped to #cc-overlay so the mobile-parity
     paywall screen is untouched. ---- */
  #cc-overlay .cc-video-bg {
    position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
    z-index: 0; pointer-events: none;
  }
  /* scrim: darken the video enough that white text and the card stay readable,
     with a stronger pool behind the card centre. */
  #cc-overlay .cc-video-scrim {
    position: absolute; inset: 0; z-index: 1; pointer-events: none;
    /* Let the footage read while keeping the card legible: a light overall veil +
       vignette, and a soft central pool behind the text. Not a blackout. */
    background:
      radial-gradient(680px 520px at 50% 45%, rgba(8,7,6,.55) 0%, rgba(8,7,6,.24) 58%, transparent 100%),
      linear-gradient(180deg, rgba(8,7,6,.34) 0%, rgba(8,7,6,.16) 42%, rgba(8,7,6,.5) 100%);
  }
  #cc-overlay .pw-card { position: relative; z-index: 2; }
  /* logo 3x (was 19px) */
  /* one line, never break — nowrap + tighter tracking so "/Luminair" stays whole.
     The overlay is full-screen, so the logo can extend past the 360px card. */
  /* wordmark 20% smaller (John, 2026-07-25): 52 → 42px. margin-bottom:0 so the tagline
     sits close under the logo. */
  #cc-overlay .pw-wordmark.pw-brand-logo { font-size: 42px; letter-spacing: 1.5px; white-space: nowrap; text-shadow: none; margin-bottom: 0; }
  /* headline bigger + one line (John, 2026-07-25): 25 → 33px, never wrap. Pulled up
     close to the logo (margin-top negative vs the card gap). */
  #cc-overlay .pw-brand-head { font-size: 33px; white-space: nowrap; margin-top: -6px; }
  /* CTA pushed down, away from the tagline (John, 2026-07-25) */
  #cc-overlay .pw-brand-cta.cc-cta { margin-top: 30px; }
  /* CTA: orange with the glow (override the neutral .google slab entirely) */
  #cc-overlay .pw-brand-cta.cc-cta {
    background: var(--accent); color: #fff; border: none; font-weight: 600;
    box-shadow: none;
  }
  #cc-overlay .pw-brand-cta.cc-cta:hover { filter: brightness(1.06); background: var(--accent); box-shadow: none; }
  /* Resend-style login: small logo, tight title, one compact neutral button —
     clean and restrained, not a big glowing hero. (John, 2026-07-24) */
  .pw-overlay.brand .pw-card { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 14px; max-width: 360px; }
  .pw-wordmark.pw-brand-logo { font-size: 19px; letter-spacing: 2px; text-shadow: none; margin-bottom: 10px; }
  .pw-brand-head { margin: 0; font-size: 25px; font-weight: 600; line-height: 1.2; letter-spacing: -0.02em; color: #fff; }
  .pw-brand-head .o { color: var(--accent); }
  .pw-brand-head b { color: #fff; font-weight: 700; }
  /* John's mobile rule: on the sign-in screen the small paragraphs go WHITE */
  .pw-brand-lede { margin: -2px 0 6px; font-size: 13.5px; line-height: 1.5; color: #fff; max-width: 300px; }
  .pw-brand-cta {
    display: flex; align-items: center; justify-content: center; gap: 10px;
    width: 100%; max-width: 320px; min-height: 48px; background: var(--accent); color: #fff;
    border: none; border-radius: 3px; font-size: 15px; font-weight: 600; cursor: pointer;
    box-shadow: none; -webkit-app-region: no-drag;
    transition: filter .12s, transform .12s, background .12s, border-color .12s;
  }
  .pw-brand-cta:hover { filter: brightness(1.05); }
  .pw-brand-cta:active { transform: translateY(1px) scale(.99); filter: brightness(.96); }
  .pw-brand-cta:disabled { opacity: .6; box-shadow: none; }
  /* Google button, Resend-style: neutral dark surface with a hairline border — the
     restraint John liked. The colored G carries the brand cue, not an orange slab. */
  .pw-brand-cta.google { background: #161616; color: #fff; border: 1px solid rgba(255,255,255,.14); box-shadow: none; font-weight: 600; }
  .pw-brand-cta.google:hover { background: #1e1e1e; border-color: rgba(255,255,255,.24); filter: none; }
  /* quiet secondary line for new users — a text link, never a second slab */
  .pw-brand-altlink { margin: 2px 0 0; font-size: 13px; color: var(--muted); }
  .pw-brand-altlink a { color: var(--accent); cursor: pointer; text-decoration: none; font-weight: 600; -webkit-app-region: no-drag; }
  .pw-brand-altlink a:hover { text-decoration: underline; }
  /* secondary CTA: the "restore your Luminair account" button, quieter than the primary */
  .pw-brand-cta.ghost { background: transparent; color: var(--accent); border: 1px solid rgba(var(--accent-rgb),.5); box-shadow: none; font-weight: 600; min-height: 46px; }
  .pw-brand-cta.ghost:hover { background: rgba(var(--accent-rgb),.1); filter: none; }
  .pw-brand-cta .gg { width: 18px; height: 18px; flex: 0 0 auto; }
  .pw-brand-note { margin: 10px 0 0; font-size: 12.5px; line-height: 1.5; color: #fff; max-width: 300px; opacity: .8; }
  .pw-brand-input {
    width: 100%; max-width: 340px; min-height: 50px; box-sizing: border-box;
    background: #111; border: 1px solid var(--line); border-radius: 3px;
    color: var(--text); font: inherit; font-size: 14px; padding: 0 14px;
    outline: none; -webkit-app-region: no-drag;
  }
  .pw-brand-input:focus { border-color: var(--accent); }
  .pw-brand-input::placeholder { color: var(--faint); }
  /* "Use your email" — the non-Google door in, for anyone invited without Gmail
     (John, 2026-07-25). Quiet link that expands into an inline sign-in/register
     form; matches the brand card's centered column. */
  .cc-email-block { width: 100%; display: flex; flex-direction: column; align-items: center; margin-top: 14px; }
  .cc-email-form { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 10px; }
  .cc-email-form .pw-brand-input { margin: 0; }
  .cc-email-form .pw-brand-cta.ghost { margin: 2px 0 0; }
  .cc-email-form .pw-brand-altlink { margin-top: 0; }
  .pw-card {
    -webkit-app-region: no-drag; position: relative; z-index: 1;
    width: 100%; max-width: 440px; padding: 40px 28px; box-sizing: border-box; text-align: center;
  }
  .pw-wordmark {
    font-family: 'Brunea', 'Bitcount', monospace; font-size: 24px; letter-spacing: 2px;   /* wordmark = logo, stays Brunea */
    text-transform: uppercase; font-weight: 700; color: var(--text);
    text-shadow: none; margin-bottom: 26px;
  }
  /* big value headline: one orange word carries the brand */
  .pw-hero { font-size: 40px; line-height: 1.04; font-weight: 800; letter-spacing: -0.03em; color: #fff; margin-bottom: 14px; }
  .pw-hero em { font-style: normal; color: var(--accent); text-shadow: none; }
  .pw-lede { font-size: 15.5px; color: var(--muted); line-height: 1.5; margin: 0 auto 30px; max-width: 360px; }
  .pw-title { font-size: 26px; font-weight: 700; letter-spacing: -0.02em; color: var(--text); margin-bottom: 6px; }
  .pw-sub { font-size: 14px; color: var(--muted); margin-bottom: 24px; }
  .pw-note { font-size: 14px; color: var(--muted); line-height: 1.5; margin-bottom: 22px; }
  /* benefits list ~20% bigger + white subtext (John, 2026-07-25) */
  .pw-feats { list-style: none; text-align: left; max-width: 400px; margin: 0 auto 30px; display: flex; flex-direction: column; gap: 14px; }
  .pw-feats li { position: relative; padding-left: 28px; font-size: 17px; color: var(--text); line-height: 1.35; }
  .pw-feats li::before { content: ''; position: absolute; left: 2px; top: 8px; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
  .pw-feat-h { font-weight: 600; color: var(--text); }
  /* Marketing subtext (John, 2026-07-25): system font, 80% white — set on every
     descriptive subline (.pw-feat-d / .pw-plan-sub / .pw-legal). Headings + prices
     stay in the brand monospace. */
  .pw-feat-d { font-size: 16px; color: rgba(255,255,255,.8); margin-top: 2px; line-height: 1.35;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; }
  /* Invited-friend free-month banner (John, 2026-07-25) — announces "your first month
     is free" at the top of the paywall for accounts a friend invited. Fixed star +
     flexible text: star flex-shrink:0, text min-width:0 (screen-width discipline). */
  /* more prominent (John, 2026-07-25): centered, larger, stronger glow — with a
     gentle pulse so it draws the eye without being obnoxious. */
  .pw-free {
    display: flex; align-items: center; justify-content: center; gap: 9px; text-align: center;
    max-width: 320px; margin: 4px auto 20px; padding: 9px 14px;
    background: rgba(var(--accent-rgb),.14); border: 1.5px solid var(--accent); border-radius: 3px;
    animation: pwFreePulse 2.4s ease-in-out infinite;
  }
  @keyframes pwFreePulse {
    0%, 100% { box-shadow: none; }
    50%      { box-shadow: none; }
  }
  @media (prefers-reduced-motion: reduce) { .pw-free { animation: none; } }
  .pw-free-star { color: var(--accent); font-size: 17px; line-height: 1.35; flex-shrink: 0; }
  .pw-free-txt { min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 2px;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; overflow-wrap: anywhere; }
  /* line 1: same size as the Yearly plan name (16px) */
  .pw-free-h { font-size: 16px; font-weight: 700; color: #fff; line-height: 1.3; }
  /* line 2: small, like the plan price details (.pw-plan-sub) */
  .pw-free-sub { font-size: 12px; line-height: 1.3; color: rgba(255,255,255,.8); }
  .pw-plans { display: flex; flex-direction: column; gap: 10px; text-align: left; }
  /* Pricing v2 (Cursor-style): Individual|Teams segment, tier tabs, price + checklist */
  .pw-plans-v2 { gap: 12px; }
  .pw-seg { display: flex; gap: 6px; }
  .pw-seg-btn { flex: 1; padding: 8px 0; border-radius: 5px; border: 1px solid var(--line); background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--muted); font-size: 13px; font-weight: 700; cursor: pointer; transition: background .12s, color .12s; }
  .pw-seg-btn:hover { background: color-mix(in srgb, var(--text) 13%, transparent); color: var(--text); }
  .pw-seg-btn.on { border-color: var(--accent); color: var(--text); background: var(--accent-soft); }
  .pw-tier-tabs { display: flex; gap: 6px; }
  .pw-tab { padding: 5px 14px; border-radius: 999px; border: 1px solid var(--line); background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--muted); font-size: 12.5px; font-weight: 600; cursor: pointer; transition: background .12s, color .12s; }
  .pw-tab:not(.on):not(.pw-tab-free):hover { background: color-mix(in srgb, var(--text) 13%, transparent); color: var(--text); }
  .pw-tab.on { border-color: var(--accent); color: var(--text); background: var(--accent-soft); }
  .pw-tab-free { opacity: .55; cursor: default; }
  .pw-tier-price .pw-plan-price { font-size: 26px; font-weight: 800; color: var(--text); }
  .pw-tier-price .pw-per { font-size: 13px; color: var(--muted); font-weight: 600; margin-left: 2px; }
  .pw-seat-row { display: flex; align-items: center; gap: 8px; margin: 4px 0 2px; }
  .pw-seat-lbl { font-size: 12px; font-weight: 700; color: var(--text); }
  .pw-seat-btn {
    width: 22px; height: 22px; padding: 0; line-height: 1; border-radius: 5px;
    border: 1px solid var(--line); background: var(--panel); color: var(--text);
    font-size: 15px; cursor: pointer; display: flex; align-items: center; justify-content: center;
  }
  .pw-seat-btn:hover { border-color: var(--accent); }
  .pw-seat-val { min-width: 26px; text-align: center; font-weight: 800; font-size: 14px; color: var(--text); font-variant-numeric: tabular-nums; }
  .pw-seat-note { font-size: 11px; color: var(--muted); margin-left: 4px; }
  .pw-tier-feats { display: flex; flex-direction: column; gap: 5px; min-height: 172px; }
  .pw-feat-lead { color: var(--muted); font-size: 12px; margin-bottom: 2px; }
  .pw-feat-li { color: var(--text); font-size: 13px; }
  .pw-plan {
    position: relative; background: var(--panel); border: 1.5px solid var(--line); border-radius: 3px;
    padding: 13px 15px; cursor: pointer; color: var(--text); transition: border-color .12s, background .12s;
  }
  .pw-plan.on { border-color: var(--accent); background: var(--accent-soft); }
  .pw-badge {
    position: absolute; top: -9px; right: 12px; background: var(--accent); color: #fff; font-size: 10px;
    font-weight: 700; letter-spacing: .02em; text-transform: uppercase; padding: 2px 8px; border-radius: 3px;
  }
  .pw-plan-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
  .pw-plan-name { font-size: 16px; font-weight: 600; }
  .pw-plan-price { font-size: 16px; font-weight: 700; }
  .pw-per { font-size: 12px; font-weight: 500; color: var(--muted); }
  .pw-plan-sub { margin-top: 3px; font-size: 12px; color: rgba(255,255,255,.8); text-align: left;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; }
  .pw-err { margin-top: 12px; font-size: 13px; color: #f2a08f; }
  .pw-cta {
    margin-top: 16px; width: 100%; background: var(--accent); color: #fff; border: none; border-radius: 3px;
    padding: 14px; font-size: 15px; font-weight: 700; cursor: pointer;
    box-shadow: none; transition: transform .12s ease, box-shadow .12s ease, filter .12s ease;
  }
  .pw-cta:hover { transform: translateY(-1px); box-shadow: none; filter: brightness(1.05); }
  .pw-cta:active { transform: translateY(0); }
  .pw-cta:disabled { opacity: .55; box-shadow: none; }
  .pw-refresh { margin-top: 8px; text-align: center; }
  .pw-link { background: none; border: none; color: var(--muted); font-size: 13px; cursor: pointer; padding: 6px; }
  .pw-legal { margin-top: 16px; font-size: 11px; line-height: 1.5; color: rgba(255,255,255,.8);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; }
  /* "Logged in as … — Log out" under the legal, a little space below it (John, 2026-07-25) */
  .pw-whoami { margin-top: 18px; font-size: 12px; color: rgba(255,255,255,.55);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; }
  .pw-whoami a { color: var(--accent); cursor: pointer; font-weight: 600; text-decoration: none; }
  .pw-whoami a:hover { text-decoration: underline; }
  /* Top-right X on the paywall → back to the login screen */
  .pw-close { position: absolute; top: 16px; right: 18px; z-index: 3; width: 30px; height: 30px;
    display: flex; align-items: center; justify-content: center; border-radius: 3px;
    background: rgba(0,0,0,.35); border: 1px solid rgba(255,255,255,.14); color: #d8d2cf;
    font-size: 14px; cursor: pointer; -webkit-app-region: no-drag; transition: background .12s, color .12s; }
  .pw-close:hover { background: rgba(0,0,0,.6); color: #fff; }
  .pw-legal a { color: var(--muted); text-decoration: underline; cursor: pointer; }

  /* =====================================================================
     LIGHT-MODE AUDIT PASS (2026-07-25) — consolidated overrides for
     hardcoded dark-tuned colors that had no light treatment and rendered
     as near-invisible / muddy text on white. Every rule is scoped to
     body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) so dark mode is completely untouched.
     Grouped by area; colors chosen for AA contrast on white.
     ===================================================================== */

  /* — Stranded-work / stash warning UI + stash diff viewer (pale amber /
       green / coral / blue on dark → invisible on white) — */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-stash-head,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-stash-ic,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-st-btn,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-stash .sb-name { color: var(--bo-txt); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-stash .sb-sess { color: #7a6635; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-st-msg.ok,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .stash-modal .stash-diff .add { color: #127a57; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .stash-modal .stash-diff .hunk { color: #2b6fa0; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .stash-modal .stash-diff .del,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-st-btn.danger,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-st-msg.err,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-sess.err { color: #b6402c; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .side-branches .sb-meta { color: #6a6a6a; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .row-menu-item.danger { color: #c23b2e; }

  /* — Assistant message body: links, tool chips, errors, quotes, tables — */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .a-link,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .tool { color: #3a3a3a; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .a-copy:hover { color: #2a2a2a; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .err { color: #b23c1f; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .msg.assistant .md-quote { background: rgba(0,0,0,.03); border-color: rgba(0,0,0,.08); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .msg.assistant .md-table tbody tr:nth-child(even) td { background: rgba(0,0,0,.02); }

  /* — Branch-out sub-agent list + recap card — */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .bo-sub-name { color: var(--text); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .bo-recap-k,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .bo-recap-foot code { color: var(--bo-lt); }

  /* — Query bar: reply-chip hover ×, auto-track toggle thumb — */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .reply-chip .rc-x:hover { color: #16233d; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .q-auto-track::after { background: #ffffff; box-shadow: 0 0 0 1px rgba(0,0,0,var(--sh18, .18)); }

  /* — Voice mode is an intentional immersive DARK moment: keep the overlay
       fully dark in light mode too (was fading from dark → white) — */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .voice-overlay { background: radial-gradient(120% 90% at 50% 16%, #17110c 0%, #0a0a0a 62%); }

  /* — Global text selection: white-on-tint was invisible on white — */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) ::selection { color: var(--text); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) ::-moz-selection { color: var(--text); }

  /* — Phone-chats viewer title — */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .pc-title { color: var(--text); }

  /* — Slash / command autocomplete + command-help (yellow on white) — */
  /* NO BROWN-YELLOW ON LIGHT (John, 2026-09-06: "that brown yellow has to change on light and
     white mode"). The old #8a5a00 was forced onto EVERY slash name, beating .slash-name.owm's
     accent, so //maddox read brown next to a lime accent. Light: plain names in ink, app (//)
     names + the app tag in the accent, directives stay blue, skill/cmd tags in muted ink. */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .slash-name { color: var(--text); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .slash-name.owm,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .cmd-help-name.cloud,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .slash-kind.owm,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .slash-kind.custom { color: var(--accent); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .slash-name.macro { color: #2f5bc0; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .slash-name.sbdoc,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .slash-kind.sbdoc { color: #7c3aed; }   /* Journal doc = readable purple on white */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .slash-kind.skill,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .slash-kind.cmd { color: var(--muted); border-color: var(--line); }

  /* — Sidebar status labels — */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .astatus.waiting { color: #127a57; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .astatus.error { color: #e5484d; }

  /* — Settings: permissions, accent picker, automations, invites — */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .perm-row.on::after,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .invite-send-msg.ok { color: #127a57; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .accent-seg button.active { border-color: var(--text); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .set-perm { color: var(--bo-lt); }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .auto-err,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .invite-send-msg.err,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .invite-chip.invalid { color: #e5484d; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .invite-chip.valid { color: var(--accent); }

  /* — Connector-card error hints (inline style="color:#f2a08f" → needs
       !important to beat the inline color; salmon was ~2:1 on white) — */
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) #oaiErr,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) #hfErr,
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) #pplxErr { color: #b23c1f !important; }
  /* Boot splash — the DEFINED brand wordmark (.pw-wordmark: Brunea, brand orange,
     self-glitch) over a real progress bar that shows what's loading + %. Never a
     typed stand-in font. (John, 2026-07-27) */
  #boot-cover { transition: opacity .32s ease; }
  #boot-cover.boot-done { opacity: 0; pointer-events: none; }
  .boot-stack { display: flex; flex-direction: column; align-items: center; gap: 26px; }
  /* Legible over the live footage: brand glow + a dark drop so the orange never muddies. */
  .boot-wordmark { margin-bottom: 0 !important; font-size: 30px;
    text-shadow: none; }
  .boot-progress { width: 240px; display: flex; flex-direction: column; gap: 9px; }
  .boot-bar { height: 3px; width: 100%; background: rgba(255,255,255,.10); border-radius: 3px; overflow: hidden; }
  .boot-bar-fill { height: 100%; width: 0%; background: var(--accent, #ff6a44);
    box-shadow: none; border-radius: 3px; transition: width .35s cubic-bezier(.4,0,.2,1); }
  .boot-meta { display: flex; justify-content: space-between; align-items: center; gap: 10px;
    font-family: 'SF Mono', ui-monospace, monospace; font-size: 11px; letter-spacing: .3px;
    color: rgba(255,255,255,.62); text-shadow: none; }
  /* the rebel line grows/shrinks, the % never moves (screen-width rule: min-width:0 + ellipsis) */
  #boot-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #boot-pct { flex-shrink: 0; color: var(--accent, #ff6a44); font-variant-numeric: tabular-nums; }

/* ==== Claude's own connector lookups — INVISIBLE ============================
   John, 2026-07-31: "I never want to see the meta get searched code, I don't
   care. Just let it happen in the background." A lookup CLAUDE fired for its own
   research gets zero pixels. The node stays in the DOM (hidden) only so the
   payload still reaches Claude; it is never shown, never clickable, never
   printed. A lookup John types himself is unaffected and renders in full. */
.meta-auto-silent { display: none !important; }

/* ---- Journal · the operating document -----------------------------------
   Not a card database with a schema on show — the briefing itself, rendered, so
   that reading it top to bottom tells you exactly how the session behaves.

   The evidence this layout is built on (graded, //maddox):
   · Sections are bounded REGIONS, because common region (Palmer 1992, ROBUST)
     overrides both proximity and similarity for "these belong together" — and
     only ONE region layer per level, so the lines inside use a spine + hairline
     rather than nested cards that would compete with the section's own edge.
   · Body text is capped at ~68ch (Dyson & Haselgrove 2001 — ~55cpl beat 100cpl
     on comprehension; 45–75 is the craft range). The panel is wider than the
     text on purpose.
   · Type is never carried by COLOUR ALONE (WCAG 1.4.1; ~8% of men have red-green
     CVD). Every colour here restates something the heading already says in words.
   · Row actions are always present and low-contrast, never hover-only: hiding a
     frequent action is burying, not progressive disclosure — and hover-only is
     not keyboard-operable. Stripping the signifier also costs ~22% more time to
     work out what is clickable (NN/g 2017).
   · Body type does not go small. Dark-on-light beats light-on-dark for reading
     (Piepenbrock/Buchner) and the penalty is worst at small sizes, so a dark
     document has to buy the legibility back with size and spacing. */
.sx { width: 900px; display: flex; flex-direction: column; max-height: 90vh; padding-bottom: 0; }

/* Masthead — a document opens with a masthead, not a dialog title. */
.sx-mast { padding-bottom: 14px; }
.sx-kicker { font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--accent); font-weight: 700; }
.sx-title { margin: 7px 0 0; font-size: 23px; line-height: 1.2; font-weight: 650; letter-spacing: -.015em; color: var(--text); }
.sx-lede { margin: 8px 0 0; max-width: 68ch; font-size: 13.5px; line-height: 1.55; color: var(--muted); }
.sx-lede strong { color: var(--text); font-weight: 600; }

.sx-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin-bottom: 2px; }
.sx-tab { background: none; border: 0; border-bottom: 2px solid transparent; margin-bottom: -1px; padding: 9px 13px; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; }
.sx-tab:hover { color: var(--text); }
.sx-tab.on { color: var(--accent); border-bottom-color: var(--accent); }

.sx-pane { display: flex; flex-direction: column; min-height: 0; }
/* `hidden` must win over the display rules above — a flex/inline-flex declaration
   silently beats the UA [hidden] default, which is how a 'hidden' pane keeps
   painting. Every element toggled via .hidden in this panel is guarded here. */
.sx-pane[hidden], .sx-addbtn[hidden], .sx-drawer[hidden], .sx-form[hidden] { display: none !important; }
.sx-pane[data-pane="doc"] { flex: 1; overflow-y: auto; padding-top: 14px; }

/* The standing-truth strip: how many lines are actually in force, and which
   layer you're looking through. The lens FILTERS one document — it never swaps
   in a different one, because "1 source of truth" has to be literal on screen. */
.sx-lensrow { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
.sx-force { font-size: 12.5px; color: var(--muted); margin-right: auto; }
.sx-force-n { font-size: 15px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.sx-lens { display: flex; gap: 2px; background: color-mix(in srgb, var(--text) 5%, transparent); border: 1px solid var(--line); border-radius: 3px; padding: 3px; flex-shrink: 0; }
.sx-lensbtn { background: none; border: 0; border-radius: 3px; padding: 5px 11px; font-size: 12px; font-weight: 600; color: var(--muted); cursor: pointer; white-space: nowrap; }
.sx-lensbtn:hover { color: var(--text); }
.sx-lensbtn.on { background: var(--panel); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,var(--sh28, .28)); }

/* ---- Sections -------------------------------------------------------------
   Each behaviour gets one bounded region and one accent. The accent is
   reinforcement for a heading that already says the same thing in words. */
.sx-sec { --sx-c: var(--muted); border: 1px solid var(--line); border-radius: 3px; background: color-mix(in srgb, var(--text) 2.5%, transparent); padding: 15px 17px 5px; margin-bottom: 13px; }
.sx-sec[data-kind="ruledout"] { --sx-c: var(--accent); }
.sx-sec[data-kind="pin"]      { --sx-c: #4a8cff; }
.sx-sec[data-kind="ask"]      { --sx-c: #d9a441; }
.sx-sec[data-kind="note"]     { --sx-c: #8a8a8a; }
.sx-sec[data-kind="directive"] { --sx-c: #5b8def; }   /* /// directive = Sonnet blue (matches the /// list badge) */
.sx-sec--dead { background: color-mix(in srgb, var(--accent) 5%, transparent); border-color: color-mix(in srgb, var(--accent) 22%, var(--line)); }
/* Custom directives — read-only, blue. The tag reads like the // panel (///deploy); the
   directive text itself is Sonnet blue so the whole section is unmistakably "directives". */
.sx-sec--dir { background: color-mix(in srgb, #5b8def 6%, transparent); border-color: color-mix(in srgb, #5b8def 26%, var(--line)); }
.sx-line--dir .sx-line-text { color: #5b8def; }
.sx-dir-nm { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 700; font-size: 12.5px; color: #5b8def; }
body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .sx-line--dir .sx-line-text,
body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .sx-dir-nm { color: #2f5bc0; }   /* deeper blue stays readable on white */
body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .sx-sec[data-kind="directive"] { --sx-c: #2f5bc0; }

.sx-sec-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 9px; margin-bottom: 12px; }
.sx-sec-idx { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; font-weight: 600; color: var(--sx-c); opacity: .8; letter-spacing: .04em; }
.sx-sec-title { margin: 0; font-size: 15.5px; font-weight: 650; color: var(--text); letter-spacing: -.01em; }
.sx-sec-count { font-size: 11px; font-weight: 700; color: var(--sx-c); background: color-mix(in srgb, var(--sx-c) 15%, transparent); border-radius: 3px; padding: 2px 8px; font-variant-numeric: tabular-nums; }
.sx-sec-desc { flex: 1 0 100%; margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); max-width: 68ch; }

/* ---- Lines ----------------------------------------------------------------
   A line, not a card: a coloured spine in the margin the way a manuscript
   rubricates, then the text. No second border — the section already owns the
   region, and a nested one would fight it. */
.sx-lines { display: flex; flex-direction: column; }
.sx-line { position: relative; padding: 11px 4px 11px 15px; border-top: 1px solid color-mix(in srgb, var(--line) 65%, transparent); cursor: text; }
.sx-lines > .sx-line:first-child { border-top: 0; }
.sx-line::before { content: ""; position: absolute; left: 0; top: 12px; bottom: 12px; width: 3px; border-radius: 3px; background: var(--sx-c); opacity: .55; }
.sx-line:hover { background: color-mix(in srgb, var(--text) 3%, transparent); border-radius: 3px; }
.sx-line:hover::before { opacity: 1; }
.sx-line:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
.sx-line.done { opacity: .55; }
.sx-line.done .sx-line-text { text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--muted) 60%, transparent); }
.sx-line.superseded .sx-line-text { opacity: .7; }

.sx-line-name { font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 3px; letter-spacing: -.005em; }
/* 68ch measure, and long unbroken strings (paths, urls) wrap instead of
   pushing the panel wide — the recurring bug class in this codebase. */
.sx-line-text { font-size: 14.5px; line-height: 1.58; color: var(--text); max-width: 68ch; overflow-wrap: anywhere; white-space: pre-wrap; }
.sx-line-text.clamp { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; font-size: 13px; color: var(--muted); white-space: normal; }

.sx-line-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-top: 7px; }
.sx-tag { font-size: 10.5px; font-weight: 650; letter-spacing: .02em; color: var(--muted); background: color-mix(in srgb, var(--text) 8%, transparent); border-radius: 3px; padding: 2px 7px; }
.sx-tag--project { color: #4a8cff; background: color-mix(in srgb, #4a8cff 14%, transparent); }
/* Master = the top tier, so it carries the brand orange: highest authority, and
   visibly distinct from the blue project rules sitting under it. */
.sx-tag--master { color: var(--accent); background: color-mix(in srgb, var(--accent) 15%, transparent); }
.sx-line.master { border-left: 2px solid color-mix(in srgb, var(--accent) 55%, transparent); padding-left: 10px; }
.sx-tag--done { color: #d9a441; background: color-mix(in srgb, #d9a441 15%, transparent); }
.sx-when { font-size: 11px; color: var(--muted); opacity: .8; }

/* Always present, never hover-only — hiding a frequent action is burying, and a
   hover-only control cannot be reached from the keyboard at all. They sit quiet
   until the pointer or focus lands on the line, then come up to full contrast. */
.sx-acts { display: flex; gap: 2px; margin-left: auto; }
.sx-act { background: none; border: 1px solid transparent; border-radius: 3px; padding: 3px 9px; min-height: 24px; font-size: 11.5px; font-weight: 600; color: var(--muted); opacity: .8; cursor: pointer; transition: opacity .12s ease, color .12s ease; }
.sx-line:hover .sx-act, .sx-line:focus-within .sx-act { opacity: 1; }
.sx-act:hover { color: var(--text); background: var(--hover); border-color: var(--line); opacity: 1; }
.sx-act:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; opacity: 1; }
.sx-act--del:hover { color: #ff5f56; border-color: color-mix(in srgb, #ff5f56 40%, transparent); background: color-mix(in srgb, #ff5f56 12%, transparent); }

/* ---- Empty document ------------------------------------------------------- */
.sx-blank { text-align: center; padding: 46px 24px 52px; }
.sx-blank-rule { width: 34px; height: 2px; background: var(--accent); border-radius: 3px; margin: 0 auto 16px; opacity: .8; }
.sx-blank-title { font-size: 15.5px; font-weight: 650; color: var(--text); }
.sx-blank-sub { margin: 8px auto 0; max-width: 56ch; font-size: 13px; line-height: 1.6; color: var(--muted); }
.sx-loading { padding: 40px; text-align: center; color: var(--muted); font-size: 13px; }

/* ---- Paste archive --------------------------------------------------------
   Deliberately demoted: pastes are not part of the briefing, so they must not
   sit as a peer of the four sections that are. */
.sx-drawer { border: 1px dashed var(--line); border-radius: 3px; margin-bottom: 13px; }
.sx-drawer > summary { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; padding: 11px 15px; cursor: pointer; list-style: none; font-size: 13px; color: var(--muted); }
.sx-drawer > summary::-webkit-details-marker { display: none; }
.sx-drawer > summary::before { content: "›"; font-size: 15px; color: var(--muted); transition: transform .15s ease; }
.sx-drawer[open] > summary::before { transform: rotate(90deg); }
.sx-drawer-t { font-weight: 650; color: var(--text); }
.sx-drawer-d { flex: 1 0 100%; font-size: 12px; color: var(--muted); padding-left: 17px; }
.sx-drawer-body { padding: 0 15px 6px; --sx-c: var(--muted); }

/* ---- The dock: composer + carry, pinned so "where do I add this?" is never a
   question you have to scroll to answer. ----------------------------------- */
.sx-dock { position: sticky; bottom: 0; background: var(--panel); padding-top: 10px; margin-top: 2px; }
.sx-dock::before { content: ""; position: absolute; left: 0; right: 0; top: -22px; height: 22px; background: linear-gradient(to bottom, transparent, var(--panel)); pointer-events: none; }

.sx-addbtn { width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px; background: none; border: 1px dashed color-mix(in srgb, var(--accent) 40%, var(--line)); border-radius: 3px; padding: 13px; font-size: 13.5px; font-weight: 600; color: var(--muted); cursor: pointer; transition: color .12s ease, border-color .12s ease, background .12s ease; }
.sx-addbtn:hover { color: var(--accent); border-color: var(--accent); background: color-mix(in srgb, var(--accent) 7%, transparent); }
.sx-plus { font-size: 16px; font-weight: 700; line-height: 1; }

.sx-form { border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line)); border-radius: 3px; padding: 14px; background: color-mix(in srgb, var(--text) 3%, transparent); }
.sx-name, .sx-body { width: 100%; box-sizing: border-box; background: var(--bg); border: 1px solid var(--line); border-radius: 3px; color: var(--text); padding: 9px 11px; font-family: inherit; }
.sx-name { font-size: 13px; font-weight: 600; margin-bottom: 8px; }
.sx-body { font-size: 14px; line-height: 1.55; resize: vertical; }
.sx-name:focus, .sx-body:focus { outline: none; border-color: var(--accent); }
.sx-name::placeholder, .sx-body::placeholder { color: var(--muted); opacity: .75; }

/* Two plain-word choices, all options visible — recognition, never a schema
   question. The words are the SAME words as the section headings, so the
   mapping needs no explaining. */
.sx-choice { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; margin-top: 11px; }
.sx-choice-lbl { font-size: 11.5px; font-weight: 650; color: var(--muted); letter-spacing: .02em; min-width: 62px; }
.sx-opts { display: flex; gap: 5px; flex-wrap: wrap; }
.sx-opt { display: inline-flex; align-items: center; gap: 6px; background: none; border: 1px solid var(--line); border-radius: 3px; padding: 5px 12px; min-height: 26px; font-size: 12px; font-weight: 600; color: var(--muted); cursor: pointer; transition: all .12s ease; }
.sx-opt:hover { color: var(--text); border-color: color-mix(in srgb, var(--text) 30%, var(--line)); }
.sx-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sx-opt-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; opacity: .5; }
.sx-opts--kind .sx-opt[data-kind="ruledout"] .sx-opt-dot { background: var(--accent); opacity: 1; }
.sx-opts--kind .sx-opt[data-kind="pin"] .sx-opt-dot { background: #4a8cff; opacity: 1; }
.sx-opts--kind .sx-opt[data-kind="ask"] .sx-opt-dot { background: #d9a441; opacity: 1; }
.sx-opts--kind .sx-opt[data-kind="note"] .sx-opt-dot { background: #8a8a8a; opacity: 1; }
.sx-opt.on { color: var(--text); border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }

.sx-formrow { display: flex; align-items: center; gap: 8px; margin-top: 13px; }
.sx-tighten, .sx-cancel { background: none; border: 1px solid var(--line); border-radius: 3px; padding: 7px 13px; min-height: 28px; font-size: 12.5px; font-weight: 600; color: var(--muted); cursor: pointer; }
.sx-tighten:hover, .sx-cancel:hover { color: var(--text); background: var(--hover); }
.sx-tighten.busy { opacity: .6; cursor: default; }
.sx-kbd { margin-left: auto; font-size: 11px; color: var(--muted); opacity: .7; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

.sx-foot { padding: 10px 0 2px; }
.scrap-carrybtn { background: none; border: 0; padding: 2px; font-size: 12.5px; color: var(--muted); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: color-mix(in srgb, var(--muted) 45%, transparent); }
.scrap-carrybtn:hover { color: var(--accent); text-decoration-color: var(--accent); }

/* ---- Edit in place -------------------------------------------------------- */
.sx-line.editing { background: color-mix(in srgb, var(--accent) 6%, transparent); border-radius: 3px; }
.sx-line.editing .sx-line-main, .sx-line.editing .sx-line-foot { display: none; }
.sx-inline { cursor: auto; }

/* ---- Undo toast ----------------------------------------------------------- */
.sx-toast { display: flex; align-items: center; gap: 12px; margin-bottom: 9px; background: color-mix(in srgb, var(--text) 10%, var(--panel)); border: 1px solid var(--line); border-radius: 3px; padding: 9px 13px; font-size: 12.5px; color: var(--text); box-shadow: 0 4px 14px rgba(0,0,0,var(--sh22, .22)); }
.sx-toast span { margin-right: auto; }
.sx-toast-undo { background: none; border: 0; color: var(--accent); font-weight: 700; font-size: 12.5px; cursor: pointer; padding: 2px 4px; }
.sx-toast-undo:hover { text-decoration: underline; }

/* ---- Search + carry picker (unchanged surfaces, restyled to match) --------- */
.scrap-add { display: flex; gap: 8px; margin: 14px 0 12px; }
.scrap-q { flex: 1; min-width: 0; background: var(--bg); border: 1px solid var(--line); border-radius: 3px; color: var(--text); padding: 9px 11px; font-size: 13px; }
.scrap-q:focus { outline: none; border-color: var(--accent); }
.scrap-hits { overflow-y: auto; }
.scrap-count { font-size: 11.5px; color: var(--muted); margin-bottom: 9px; }
.scrap-hit { border-left: 2px solid var(--line); padding: 3px 0 3px 12px; margin-bottom: 13px; }
.scrap-hitmeta { font-size: 11px; color: var(--muted); margin-bottom: 4px; }
.scrap-hittext { font-size: 13px; line-height: 1.55; color: var(--text); max-width: 68ch; overflow-wrap: anywhere; white-space: pre-wrap; }
.scrap-chip { font-size: 10px; font-weight: 650; color: var(--muted); background: color-mix(in srgb, var(--text) 8%, transparent); border-radius: 3px; padding: 1px 6px; }
/* a hit that came from the journal, not the transcript — worth telling apart at a glance */
.scrap-chip.store-journal { color: var(--accent); background: color-mix(in srgb, var(--accent) 15%, transparent); }
.scrap-hit:has(.store-journal) { border-left-color: var(--accent); }
.scrap-empty { padding: 22px 6px; text-align: center; font-size: 12.5px; color: var(--muted); }
/* ── Move-notes picker, rebuilt (John, 2026-08-18: "drastically improve this pop up") ──
   Was a stack of tall borderless rows with the raw session title spilling to three
   lines. Now: a titled header with an icon, a live search, and compact single-line rows
   each with an initial badge, a truncated title + folder, and a chevron. */
.scrap-picker { width: 460px; padding: 20px; }
.scrap-pick-head { display: flex; gap: 12px; align-items: flex-start; margin-bottom: 14px; }
.scrap-pick-icon {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.scrap-pick-htext h3 { margin: 0 0 3px; font-size: 15px; }
.scrap-pick-htext p { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.scrap-pick-search { margin-bottom: 10px; }
.scrap-pick-filter {
  width: 100%; box-sizing: border-box; padding: 9px 12px;
  background: var(--panel-2, rgba(255,255,255,.03)); color: var(--text);
  border: 1px solid var(--line); border-radius: 7px; font-size: 13px; outline: none;
}
.scrap-pick-filter:focus { border-color: var(--accent); }
.scrap-pick-filter::placeholder { color: var(--faint); }
.scrap-srclist { max-height: 42vh; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; margin: 0 0 16px; }
.scrap-src {
  display: flex; align-items: center; gap: 11px; text-align: left; width: 100%;
  background: none; border: 1px solid transparent; border-radius: 7px;
  padding: 8px 10px; cursor: pointer; transition: background .1s, border-color .1s;
}
.scrap-src:hover, .scrap-src:focus-visible {
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: color-mix(in srgb, var(--accent) 8%, transparent); outline: none;
}
.scrap-src.done { opacity: .6; cursor: default; }
.scrap-src-badge {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; color: var(--muted);
  background: color-mix(in srgb, var(--text) 8%, transparent);
}
.scrap-src:hover .scrap-src-badge { color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, transparent); }
.scrap-src-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.scrap-src-title { font-size: 13px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.scrap-src-meta { font-size: 11px; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.scrap-src-go { flex: 0 0 auto; color: var(--faint); opacity: 0; transition: opacity .1s; }
.scrap-src:hover .scrap-src-go { opacity: 1; color: var(--accent); }

  /* ── D2: "Other devices" — cloud-only sessions authored on another Mac ────── */
  .otherdev-head { cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 6px; }
  .otherdev-head:hover { color: var(--accent); }
  .otherdev-head .od-count { color: var(--faint); font-size: 10px; font-weight: 600; letter-spacing: 0; }
  .otherdev-head.collapsed .od-count { opacity: .8; }
  .otherdev-head .od-sync { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); opacity: .9; animation: odpulse 1.1s ease-in-out infinite; }
  @keyframes odpulse { 0%,100% { opacity: .25; } 50% { opacity: .95; } }
  .otherdev-list.collapsed { display: none; }
  .row.session.cloud-session { opacity: .92; }
  .row.session.cloud-session .cloud-badge {
    flex-shrink: 0; width: 15px; height: 15px; margin-right: 2px; display: inline-block;
    background: var(--faint);
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M17.5 19a4.5 4.5 0 0 0 .5-8.97A6 6 0 0 0 6.34 9 4.5 4.5 0 0 0 6.5 19Z'/></svg>") center/15px no-repeat;
            mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M17.5 19a4.5 4.5 0 0 0 .5-8.97A6 6 0 0 0 6.34 9 4.5 4.5 0 0 0 6.5 19Z'/></svg>") center/15px no-repeat;
  }
  .row.session.cloud-session:hover .cloud-badge { background: var(--accent); }
  /* relink candidates: each unlinked remote folder + its sessions + a Link/Locate action */
  .od-group { margin: 2px 0 6px; }
  .od-folder { display: flex; align-items: center; gap: 6px; padding: 3px 6px 3px 8px; min-width: 0; }
  .od-folder .od-fname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; font-weight: 600; color: var(--faint); letter-spacing: .02em; }
  .od-folder .od-fcount { flex: 0 0 auto; color: var(--faint); font-size: 10px; font-weight: 600; opacity: .8; }
  .od-folder .od-link {
    flex: 0 0 auto; cursor: pointer; font: inherit; font-size: 10px; font-weight: 700; letter-spacing: .03em;
    padding: 2px 8px; border-radius: 3px; border: 1px solid var(--accent); color: var(--accent);
    background: transparent; transition: background .12s, color .12s;
  }
  .od-folder .od-link:hover:not(:disabled) { background: var(--accent); color: var(--on-accent); }
  .od-folder .od-link:disabled { opacity: .5; cursor: default; }
  .od-group .row.session.cloud-session { padding-left: 20px; }

  /* read-only viewer for a session pulled from the cloud */
  .cloudview-overlay { position: fixed; inset: 0; z-index: 4300; background: rgba(0,0,0,.5); display: flex; align-items: center; justify-content: center; padding: 32px; -webkit-app-region: no-drag; }
  .cloudview { width: min(760px, 100%); max-height: 86vh; display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--line); border-radius: 3px; box-shadow: 0 20px 60px rgba(0,0,0,var(--sh55, .55)); overflow: hidden; }
  .cloudview-head { position: relative; padding: 16px 18px 12px; border-bottom: 1px solid var(--line); }
  .cloudview-head .cv-title { font-size: 14px; font-weight: 650; color: var(--text); padding-right: 34px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cloudview-head .cv-sub { font-size: 11px; color: var(--faint); margin-top: 3px; letter-spacing: .3px; }
  .cloudview-head .cv-close { position: absolute; top: 12px; right: 12px; width: 28px; height: 28px; border: none; background: transparent; color: var(--muted); font-size: 15px; cursor: pointer; border-radius: 3px; }
  .cloudview-head .cv-close:hover { background: var(--hover); color: var(--accent); }
  .cv-actions { margin-top: 10px; display: flex; align-items: center; gap: 10px; min-width: 0; }
  .cv-continue { background: var(--accent); color: var(--on-accent); border: none; font-size: 11.5px; font-weight: 700; padding: 6px 14px; border-radius: 3px; cursor: pointer; letter-spacing: .2px; flex-shrink: 0; }
  .cv-continue:hover { filter: brightness(1.12); }
  .cv-continue:disabled { opacity: .55; cursor: default; filter: none; }
  .cv-err { font-size: 11px; color: #ff6b6b; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cv-earlier { padding: 8px; text-align: center; border-bottom: 1px solid var(--line); }
  .cv-earlier-btn { background: transparent; border: 1px solid var(--line); color: var(--muted); font-size: 11.5px; padding: 5px 12px; border-radius: 3px; cursor: pointer; }
  .cv-earlier-btn:hover { border-color: var(--accent); color: var(--accent); }
  .cv-body { flex: 1; overflow-y: auto; padding: 16px 18px; display: flex; flex-direction: column; gap: 14px; }
  .cv-loading { color: var(--faint); font-size: 12.5px; text-align: center; padding: 24px 0; }
  .cv-turn { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
  .cv-who { font-size: 10.5px; font-weight: 600; letter-spacing: .5px; text-transform: uppercase; color: var(--faint); }
  .cv-user .cv-who { color: var(--accent); }
  .cv-text { font-size: 13px; line-height: 1.55; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
  .cv-img-note { font-size: 11px; color: var(--faint); font-style: italic; }

  /* EVERYWHERE, not just the account menu (John, 2026-08-16: "I only see the glow here.
     But nowhere else"). The rules above were a hand-picked list of ~10 selectors, so the
     effect only showed where I happened to name it. This inherits one soft phosphor

  /* Delete a note, permanently (John, 2026-08-16) — quiet ×, only on hover. */
  .note-card .nc-del {
    flex: 0 0 auto; width: 20px; height: 20px; padding: 0;
    background: transparent; border: 0; border-radius: 3px;
    color: var(--faint); font-size: 15px; line-height: 1; cursor: pointer;
    opacity: 0; transition: opacity .12s ease, color .12s ease, background .12s ease;
  }
  .note-card:hover .nc-del { opacity: 1; }
  .note-card .nc-del:hover { color: #e5484d; background: rgba(229,72,77,.12); }

  /* First-run look picker (John, 2026-08-25). Sits above everything except the boot
     cover so it is the first real surface a new user touches. Theme + accent only. */
  .look-gate {
    position: fixed; inset: 0; z-index: 99000;
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--bg) 86%, transparent);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    -webkit-app-region: drag;
  }
  .look-gate.show { display: flex; }
  .look-card {
    -webkit-app-region: no-drag;
    width: min(460px, calc(100vw - 48px));
    display: flex; flex-direction: column; gap: 16px;
    padding: 26px 26px 22px; border-radius: 14px;
    background: var(--panel); border: 1px solid var(--line);
    box-shadow: 0 18px 44px rgba(0,0,0,.45);
  }
  .look-title { font-family: var(--ui-font); font-size: 19px; font-weight: 700; color: var(--text); }
  .look-sub { font-size: 12.5px; color: var(--muted); margin-top: -10px; }
  .look-row { display: flex; flex-direction: column; gap: 8px; }
  .look-lab { font-size: 11px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--faint); }
  .look-go {
    align-self: stretch; margin-top: 4px; padding: 10px 0;
    border: 0; border-radius: 9px; cursor: pointer;
    background: var(--accent); color: var(--on-accent);
    font-family: var(--ui-font); font-size: 13.5px; font-weight: 700;
    transition: filter .12s ease;
  }
  .look-go:hover { filter: brightness(1.08); }

  /* Free-trial chip (John, 2026-08-26): discrete accent pill in the sidebar footer that
     counts down the 7-day trial; click opens the upgrade paywall. */
  .side-foot-left { display: flex; align-items: center; gap: 7px; }
  .trial-chip {
    flex: 0 0 auto; cursor: pointer;
    padding: 2px 7px; border-radius: 999px; line-height: 1.4;
    font-size: 9.5px; font-weight: 700; letter-spacing: .4px; white-space: nowrap;
    color: var(--accent);
    background: rgba(var(--accent-rgb), .12);
    border: 1px solid rgba(var(--accent-rgb), .35);
    transition: background .12s ease, border-color .12s ease;
  }
  .trial-chip:hover { background: rgba(var(--accent-rgb), .2); border-color: rgba(var(--accent-rgb), .55); }
  .trial-chip[hidden] { display: none; }

  /* Account-chip status badge (John, 2026-08-26): the WHY of this account's access —
     Free (whitelisted), Pro (paid), or the local "Nd Trial" countdown — sits inside the
     account button, before the caret. Retires the standalone footer trial chip. */
  .acct-btn .acct-status {
    flex: 0 0 auto; margin-left: 6px;
    padding: 1px 6px; border-radius: 999px; line-height: 1.4;
    font-size: 9px; font-weight: 700; letter-spacing: .3px; white-space: nowrap;
  }
  .acct-btn .acct-status.wl    { color: #3ecf8e; background: rgba(62,207,142,.16); }
  .acct-btn .acct-status.pro   { color: var(--accent); background: rgba(var(--accent-rgb),.18); }
  .acct-btn .acct-status.trial { color: #ffaf2b; background: rgba(255,175,43,.16); }

  /* Per-engine "Visible models" toggles (John, 2026-08-26): hide models you never use
     from every picker. Lives at the bottom of each connector detail panel. */
  .mdl-visible { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 12px; }
  .mdl-visible-head { font-size: 10.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--faint); margin-bottom: 8px; }
  .mdl-vis-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 5px 0; cursor: pointer; }
  .mdl-vis-name { font-size: 12.5px; color: var(--text); cursor: text; border-radius: 3px; padding: 2px 5px; margin-left: -5px; transition: background .12s, color .12s; user-select: none; }
  .mdl-vis-name:hover { background: var(--hover); color: var(--accent); }
  .mdl-vis-tog { flex: 0 0 auto; width: 30px; height: 17px; border-radius: 999px; background: var(--hover); border: 1px solid var(--line); position: relative; transition: background .12s ease, border-color .12s ease; cursor: pointer; }
  .mdl-vis-tog::after { content: ''; position: absolute; top: 1px; left: 1px; width: 13px; height: 13px; border-radius: 50%; background: var(--muted); transition: transform .12s ease, background .12s ease; }
  .mdl-vis-tog.on { background: rgba(var(--accent-rgb), .3); border-color: rgba(var(--accent-rgb), .5); }
  .mdl-vis-tog.on::after { transform: translateX(13px); background: var(--accent); }

  /* Inline connector-suggestion card (John, 2026-08-26): shown when a session offers an
     installable capability, with a live Install/Connect action. */
  .connector-card {
    align-self: stretch; margin: 14px 0; padding: 14px 16px; border-radius: 3px;
    background: var(--panel-2); border: 1px solid rgba(var(--accent-rgb), .30);
    display: flex; align-items: center; gap: 14px;
  }
  .connector-card .cc-body { flex: 1; min-width: 0; }
  .connector-card .cc-name { font-size: 13.5px; font-weight: 700; color: var(--text); }
  .connector-card .cc-blurb { font-size: 12px; line-height: 1.5; color: var(--muted); margin-top: 3px; }
  .connector-card .cc-btn {
    flex: 0 0 auto; padding: 8px 14px; border: 0; border-radius: 8px; cursor: pointer;
    background: var(--accent); color: var(--on-accent); font-weight: 700; font-size: 12.5px; white-space: nowrap;
    transition: filter .12s ease;
  }
  .connector-card .cc-btn:hover { filter: brightness(1.08); }
  .connector-card .cc-btn.done { background: rgba(62,207,142,.16); color: #3ecf8e; cursor: default; }
  .connector-card .cc-err { flex-basis: 100%; margin-top: 8px; font-size: 11.5px; color: #ff6b6b; }

  /* Quick Ask — an isolated floating burner chat (John, 2026-08-27, rebuilt). */
  .quick-ask-overlay { position: fixed; inset: 0; z-index: 900; display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--bg) 55%, transparent); backdrop-filter: blur(3px); }
  .quick-ask-overlay[hidden] { display: none; }
  .quick-ask-panel { width: min(760px, 92vw); height: min(72vh, 720px); display: flex; flex-direction: column;
    background: var(--panel); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; box-shadow: 0 24px 70px rgba(0,0,0,.5); }
  .quick-ask-head { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line); }
  .quick-ask-head .qa-title { font-family: var(--ui-font); font-weight: 700; font-size: 14px; color: var(--text); }
  .quick-ask-head .qa-sub { font-size: 11px; color: var(--faint); }
  .quick-ask-head .spacer { flex: 1; }
  .quick-ask-head .qa-convert { padding: 4px 11px; border-radius: 6px; border: 1px solid rgba(var(--accent-rgb),.4); background: rgba(var(--accent-rgb),.14);
    color: var(--accent); font-size: 12px; font-weight: 700; cursor: pointer; }
  .quick-ask-head .qa-convert:hover { background: rgba(var(--accent-rgb),.24); }
  .quick-ask-head .qa-erase { padding: 4px 10px; border-radius: 6px; border: 1px solid var(--line); background: var(--hover); color: var(--muted); font-size: 12px; font-weight: 600; cursor: pointer; }
  .quick-ask-head .qa-erase:hover { color: #ff6b6b; border-color: rgba(255,90,90,.4); background: rgba(255,90,90,.1); }
  .quick-ask-head .qa-close { width: 26px; height: 26px; border: 0; background: transparent; color: var(--faint); font-size: 13px; cursor: pointer; border-radius: 6px; }
  .quick-ask-head .qa-close:hover { background: var(--hover); color: var(--text); }
  .quick-ask-mount { flex: 1 1 auto; min-height: 0; display: flex; }
  .quick-ask-mount .pane { flex: 1; min-width: 0; }
  .quick-ask-mount .pane .pane-head { display: none; }
  /* Header status dot */
  .quick-ask-btn { position: relative; }
  .quick-ask-btn .qa-status-dot { position: absolute; top: 3px; right: 3px; width: 6px; height: 6px; border-radius: 50%; background: transparent; }
  .quick-ask-btn .qa-status-dot.thinking { background: var(--accent); animation: micpulse 1.1s ease-in-out infinite; }
  .quick-ask-btn .qa-status-dot.error { background: #ff2d20; }
  .quick-ask-btn .qa-status-dot.done, .quick-ask-btn .qa-status-dot.idle { background: #45e3b0; }
  .quick-ask-btn .qa-status-dot.none { background: transparent; }
  /* Working in the background (overlay closed while a turn runs): the BOLT itself pulses in
     the running model's colour (--dot-c set by tintDotToModel), so a hidden Quick Ask still
     shows it is thinking. The tiny corner dot is redundant then, so hide it. */
  .quick-ask-btn.qa-working svg { stroke: var(--dot-c, var(--accent)); animation: qaBoltPulse 1.1s ease-in-out infinite; }
  .quick-ask-btn.qa-working .qa-status-dot { display: none; }
  @keyframes qaBoltPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
  /* ---- Team panel (Team/Team+ plans): right drawer with Chat + Seats ---- */
  .team-btn { position: relative; }
  .team-dot { position: absolute; top: -4px; right: -4px; min-width: 15px; height: 15px; padding: 0 4px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border-radius: 8px; background: var(--accent); color: #fff; font-size: 9px; font-weight: 700; line-height: 1; letter-spacing: -0.02em; }
  .team-dot[hidden] { display: none; }
  /* Team Usage dashboard (John, 2026-09-06). Roles, not raw hex, in the body; dark
     defaults, light overrides. Series colors = validated reference palette slots 1-2. */
  .tu-root { --tu-s1: #3987e5; --tu-s2: #d95926; --tu-grid: rgba(255,255,255,.07); --tu-axis: rgba(255,255,255,.18); --tu-track: rgba(255,255,255,.06); position: relative; }
  body:is([data-theme="light"],[data-theme="white"]):not([data-preset]) .tu-root { --tu-s1: #2a78d6; --tu-s2: #eb6834; --tu-grid: rgba(0,0,0,.07); --tu-axis: rgba(0,0,0,.22); --tu-track: rgba(0,0,0,.06); }
  .tu-filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 0 0 14px; }
  .tu-seg { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
  .tu-seg button { background: transparent; border: 0; color: var(--muted); font: inherit; font-size: 12px; padding: 6px 12px; cursor: pointer; }
  .tu-seg button.on { background: var(--accent); color: var(--on-accent, #111); font-weight: 600; }
  .tu-refresh { margin-left: auto; background: transparent; border: 1px solid var(--line); color: var(--muted); border-radius: 999px; padding: 6px 12px; font: inherit; font-size: 12px; cursor: pointer; }
  .tu-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 12px; }
  .tu-tile { border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; background: rgba(255,255,255,.02); }
  .tu-tile-l { font-size: 12px; color: var(--muted); }
  .tu-tile-v { font-size: 28px; font-weight: 600; line-height: 1.15; margin: 4px 0 2px; letter-spacing: -.01em; }
  .tu-tile-d { font-size: 11px; color: var(--muted); }
  .tu-tile-d[data-dir="up"] { color: #7ed957; } .tu-tile-d[data-dir="down"] { color: var(--muted); }
  .tu-card { border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px 10px; margin-bottom: 12px; background: rgba(255,255,255,.02); }
  .tu-card-h { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
  .tu-card-t { font-size: 13px; font-weight: 600; } .tu-card-s { font-size: 12px; color: var(--muted); }
  .tu-svg { display: block; overflow: visible; }
  .tu-grid { stroke: var(--tu-grid); stroke-width: 1; } .tu-axis { stroke: var(--tu-axis); stroke-width: 1; }
  .tu-ax { font-size: 10px; fill: var(--muted); } .tu-lab { font-size: 11px; fill: var(--text); font-weight: 600; }
  .tu-bar.plan { fill: var(--tu-s1); } .tu-bar.charged { fill: var(--tu-s2); }
  .tu-hit { fill: transparent; cursor: pointer; }
  .tu-col.hov .tu-bar { filter: brightness(1.15); }
  .tu-legend { display: flex; gap: 14px; font-size: 12px; color: var(--muted); margin-top: 6px; align-items: center; }
  .tu-legend span { display: inline-flex; align-items: center; gap: 6px; } .tu-legend i { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
  .tu-legend-h { margin-left: auto; opacity: .8; }
  .tu-hb { display: flex; flex-direction: column; gap: 6px; }
  .tu-hb-r { display: grid; grid-template-columns: minmax(120px, 28%) 1fr 64px; align-items: center; gap: 10px; font-size: 12px; border-radius: 6px; padding: 2px 4px; outline: none; }
  .tu-hb-r:hover, .tu-hb-r:focus { background: rgba(255,255,255,.04); }
  .tu-hb-l { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tu-hb-track { height: 12px; background: var(--tu-track); border-radius: 4px; overflow: hidden; }
  .tu-hb-track i { display: block; height: 100%; background: var(--tu-s1); border-radius: 0 4px 4px 0; }
  .tu-hb-v { text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }
  .tu-empty { font-size: 12px; color: var(--muted); padding: 6px 0; }
  .tu-table { width: 100%; border-collapse: collapse; font-size: 12px; }
  .tu-table th { text-align: left; font-weight: 600; color: var(--muted); padding: 6px 8px; border-bottom: 1px solid var(--line); }
  .tu-table td { padding: 6px 8px; border-bottom: 1px solid var(--tu-grid); }
  .tu-table .n { text-align: right; font-variant-numeric: tabular-nums; }
  .tu-table.tu-sub { margin: 6px 0 4px; } .tu-table.tu-sub th, .tu-table.tu-sub td { padding: 4px 8px; }
  .tu-detail td { background: rgba(255,255,255,.02); }
  .tu-link { background: none; border: 0; color: var(--accent); font: inherit; font-size: 12px; cursor: pointer; padding: 0; }
  .tu-tip { position: absolute; z-index: 5; pointer-events: none; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; font-size: 12px; box-shadow: 0 6px 20px rgba(0,0,0,.25); min-width: 150px; }
  .tu-tip-r { display: flex; align-items: center; gap: 8px; margin: 2px 0; } .tu-tip-r i { width: 12px; height: 2px; border-radius: 1px; display: inline-block; } .tu-tip-r b { font-weight: 600; } .tu-tip-r span { color: var(--muted); }
  /* Team Board (John, 2026-09-06): person cards + clickable session chips */
  .tb-legend { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; font-size: 12px; color: var(--muted, #9a9a9a); margin: 2px 0 12px; }
  .tb-legend span { display: inline-flex; align-items: center; gap: 6px; }
  .tb-legend-hint { margin-left: auto; opacity: .8; }
  .tb-dot { width: 8px; height: 8px; border-radius: 50%; background: #666; display: inline-block; flex: none; }
  .tb-dot.run { background: #7ed957; box-shadow: 0 0 0 0 rgba(126,217,87,.6); animation: tbPulse 1.6s ease-out infinite; }
  .tb-dot.wait { background: #f5b942; } .tb-dot.err { background: #ff6b6b; } .tb-dot.idle { background: #666; }
  @keyframes tbPulse { 0% { box-shadow: 0 0 0 0 rgba(126,217,87,.55); } 100% { box-shadow: 0 0 0 8px rgba(126,217,87,0); } }
  .tb-card { border: 1px solid var(--line, #2a2a2a); border-radius: 10px; padding: 12px 14px; margin: 0 0 10px; background: rgba(255,255,255,.02); }
  .tb-card.off { opacity: .62; }
  .tb-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
  .tb-av { width: 30px; height: 30px; border-radius: 50%; background: rgba(200,255,0,.14); color: var(--accent, #c8ff00); font-weight: 700; display: inline-flex; align-items: center; justify-content: center; flex: none; }
  .tb-who { flex: 1; min-width: 0; } .tb-name { font-size: 14px; font-weight: 600; } .tb-sub { font-size: 12px; color: var(--muted, #9a9a9a); display: flex; align-items: center; gap: 6px; }
  .tb-pres { width: 7px; height: 7px; border-radius: 50%; display: inline-block; background: #666; } .tb-pres.on { background: #7ed957; }
  .tb-role { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted, #9a9a9a); border: 1px solid var(--line, #2a2a2a); border-radius: 999px; padding: 2px 8px; }
  .tb-sessions { display: flex; flex-wrap: wrap; gap: 6px; }
  .tb-empty { font-size: 12px; color: var(--muted, #9a9a9a); }
  .tb-chip { display: inline-flex; align-items: center; gap: 7px; max-width: 100%; border: 1px solid var(--line, #2a2a2a); background: rgba(255,255,255,.03); color: inherit; border-radius: 999px; padding: 5px 10px 5px 8px; font: inherit; font-size: 12px; cursor: pointer; }
  .tb-chip:hover:not(:disabled) { border-color: var(--accent, #c8ff00); background: rgba(200,255,0,.06); }
  .tb-chip:disabled { cursor: default; opacity: .6; }
  .tb-chip-t { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tb-chip-s { color: var(--muted, #9a9a9a); }
  .tb-chip.run .tb-chip-s { color: #7ed957; } .tb-chip.wait .tb-chip-s { color: #f5b942; } .tb-chip.err .tb-chip-s { color: #ff6b6b; }
  .tm-role2.saving { opacity: .6; }
  .tsh-teamdocs { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; background: color-mix(in srgb, var(--text) 2%, transparent); }
  .tsh-hint { font-size: 12px; color: var(--muted); }
  .tsh-sec { margin: 18px 0 8px; display: flex; flex-direction: column; gap: 2px; }
  .tsh-sec:first-child { margin-top: 4px; }
  .tsh-sec-t { font-size: 13px; font-weight: 600; letter-spacing: .01em; }
  .tsh-sec-h { font-size: 12px; color: var(--muted, #9a9a9a); }
  .tsh-sharebtn { align-self: flex-start; margin-top: 8px; }
  .tsh-row { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border: 1px solid var(--line, #2a2a2a); border-radius: 9px; margin: 6px 0; background: rgba(255,255,255,.02); }
  .tsh-row:hover { background: rgba(255,255,255,.04); }
  .tsh-ic { width: 18px; display: inline-flex; opacity: .8; }
  .tsh-main { flex: 1; min-width: 0; }
  .tsh-title { font-size: 13px; }
  .tsh-meta { font-size: 12px; color: var(--muted, #9a9a9a); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .tsh-actions { display: flex; gap: 6px; flex-shrink: 0; }
  .tsh-empty { padding: 6px 2px; }
  .tsh-search { width: 100%; box-sizing: border-box; margin: 8px 0; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--line, #2a2a2a); background: rgba(255,255,255,.04); color: inherit; }
  .tsh-pick { max-height: 46vh; overflow: auto; display: flex; flex-direction: column; gap: 4px; }
  .tsh-pick-row { display: flex; justify-content: space-between; gap: 10px; text-align: left; padding: 8px 10px; border-radius: 8px; border: 1px solid transparent; background: transparent; color: inherit; cursor: pointer; }
  .tsh-pick-row:hover { background: rgba(255,255,255,.05); border-color: var(--line, #2a2a2a); }
  .tsh-pick-d { font-size: 12px; color: var(--muted, #9a9a9a); }
  .tsh-editor { width: 100%; min-height: 60%; box-sizing: border-box; font: inherit; font-size: 13px; line-height: 1.45; padding: 10px; border-radius: 8px; border: 1px solid var(--line, #2a2a2a); background: rgba(255,255,255,.03); color: inherit; resize: vertical; }
  .tsh-viewer-foot { display: flex; gap: 8px; align-items: center; margin-top: 10px; }
  .tsh-status { font-size: 12px; color: var(--muted, #9a9a9a); margin-left: auto; margin-right: 10px; }
  .tsh-ws .btn-primary { margin-top: 4px; }
  .shp-status { font-size: 12px; color: var(--muted, #9a9a9a); margin-right: 10px; max-width: 46%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .shp-status[data-kind="busy"] { color: var(--fg, #ddd); }
  .shp-status[data-kind="ok"] { color: #7ed957; }
  .shp-status[data-kind="error"] { color: #ff6b6b; }
  /* Docked like a session pane: a static right column inside .main-body, pushing the
     pane grid over instead of sliding above it. Stays open until closed. */
  .team-panel { flex: 0 0 340px; width: 340px; min-height: 0; background: var(--panel); border-left: 1px solid var(--line); display: flex; flex-direction: column; }
  .team-panel[hidden] { display: none; }
  /* Manage-team modal — Settings-style: scrim + centered card, own tab rail. */
  /* Manage team — Maddox redesign (2026-09-01): Settings-style shell with an icon
     sidebar (persistent navigation > pill soup), a per-tab header that says what
     the surface is for, and card-based content. */
  .tmgr-overlay { position: fixed; inset: 0; z-index: 9600; background: rgba(0,0,0,.45); backdrop-filter: blur(3px); display: flex; align-items: center; justify-content: center; padding: 40px; }
  .tmgr-card { width: min(860px, 94vw); height: min(620px, 88vh); background: var(--panel); border: 1px solid var(--line); border-radius: 16px; box-shadow: 0 28px 80px rgba(0,0,0,.55); display: flex; overflow: hidden; }
  .tmgr-nav { width: 192px; flex: none; display: flex; flex-direction: column; gap: 2px; padding: 14px 10px; border-right: 1px solid var(--line); background: color-mix(in srgb, var(--text) 2.5%, transparent); }
  .tmgr-nav-title { font-size: 14px; font-weight: 800; color: var(--text); padding: 4px 10px 12px; letter-spacing: -.2px; }
  .tmgr-tab { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; padding: 7px 10px; border-radius: 8px; border: none; background: none; color: var(--muted); font-size: 12.5px; font-weight: 600; cursor: pointer; transition: background .12s, color .12s; }
  .tmgr-tab svg { flex: none; opacity: .8; }
  .tmgr-tab:hover { color: var(--text); background: color-mix(in srgb, var(--text) 6%, transparent); }
  .tmgr-tab.on { color: var(--text); background: var(--accent-soft); }
  .tmgr-tab.on svg { color: var(--accent); opacity: 1; }
  .tmgr-nav-foot { margin-top: auto; padding: 8px 10px 2px; font-size: 10.5px; color: var(--faint); line-height: 1.5; }
  .tmgr-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
  .tmgr-head { display: flex; align-items: flex-start; gap: 10px; padding: 18px 22px 14px; border-bottom: 1px solid var(--line); }
  .tmgr-head-txt { flex: 1; min-width: 0; }
  .tmgr-title { font-weight: 800; font-size: 16px; letter-spacing: -.2px; }
  .tmgr-sub { font-size: 12px; color: var(--faint); margin-top: 3px; line-height: 1.5; }
  .tmgr-x { flex: none; background: none; border: none; color: var(--muted); font-size: 15px; cursor: pointer; -webkit-app-region: no-drag; padding: 2px 6px; border-radius: 6px; }
  .tmgr-x:hover { color: var(--text); background: color-mix(in srgb, var(--text) 8%, transparent); }
  .tmgr-body { flex: 1; overflow-y: auto; padding: 20px 22px; }
  /* Generic content primitives shared by every tab */
  .tmgr-body .tm-seat { border-bottom: none; border: 1px solid var(--line); border-radius: 10px; padding: 10px 13px; margin-bottom: 8px; background: color-mix(in srgb, var(--text) 2%, transparent); }
  .tmgr-body .tm-seat:hover { background: color-mix(in srgb, var(--text) 4.5%, transparent); }
  .tmgr-body .tm-loading { padding: 26px 0; text-align: center; font-size: 12.5px; }
  /* [[doc]] typeahead in Team Chat + shared-doc viewer */
  .tm-doc-menu { position: absolute; bottom: calc(100% + 6px); left: 8px; right: 8px; max-height: 260px; overflow-y: auto; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 12px 34px rgba(0,0,0,.45); z-index: 20; display: flex; flex-direction: column; padding: 4px; }
  .tm-doc-menu button { text-align: left; background: none; border: none; color: var(--text); font-size: 12.5px; padding: 7px 10px; border-radius: 6px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tm-doc-menu button:hover { background: color-mix(in srgb, var(--text) 10%, transparent); }
  .tmdoc-read-body { white-space: pre-wrap; word-break: break-word; font-size: 13px; line-height: 1.5; color: var(--text); background: color-mix(in srgb, var(--text) 5%, transparent); border: 1px solid var(--line); border-radius: 8px; padding: 12px; margin: 0 0 12px; max-height: 100%; overflow-y: auto; }
  .tm-head { display: flex; align-items: center; gap: 6px; padding: 10px 12px; border-bottom: 1px solid var(--line); }
  .tm-title { font-weight: 800; font-size: 13px; margin-right: 6px; }
  .tm-tab { padding: 4px 12px; border-radius: 999px; border: 1px solid var(--line); background: none; color: var(--muted); font-size: 12px; cursor: pointer; }
  .tm-tab.on { border-color: var(--accent); color: var(--text); background: var(--accent-soft); }
  .tm-x { margin-left: auto; background: none; border: none; color: var(--muted); font-size: 14px; cursor: pointer; }
  .tm-body { flex: 1; min-height: 0; display: flex; }
  .tm-chat { flex: 1; display: flex; flex-direction: column; min-height: 0; }
  .tm-feed { flex: 1; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 10px; }
  .tm-msg { max-width: 92%; background: color-mix(in srgb, var(--text) 6%, transparent); border-radius: 6px; padding: 7px 10px; align-self: flex-start; }
  .tm-msg.me { align-self: flex-end; background: var(--accent-soft); }
  .tm-who { font-size: 10px; color: var(--faint); margin-bottom: 2px; }
  .tm-acts { margin-left: 6px; opacity: 0; }
  .tm-msg:hover .tm-acts { opacity: 1; }
  .tm-act { background: none; border: none; cursor: pointer; font-size: 11px; color: var(--faint); padding: 0 2px; }
  .tm-act:hover { color: var(--text); }
  .tm-quote { font-size: 11px; color: var(--faint); border-left: 2px solid var(--line); padding: 2px 6px; margin: 2px 0 4px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }
  .tm-quote:hover { color: var(--text); }
  .tm-flash { outline: 1px solid var(--accent); }
  .tm-reacts { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 4px; }
  .tm-react { background: var(--bg); border: 1px solid var(--line); border-radius: 999px; font-size: 11px; padding: 1px 7px; cursor: pointer; color: var(--text); }
  .tm-react.mine { border-color: var(--accent); background: var(--accent-soft); }
  .tm-livebar { display: flex; gap: 6px; flex-wrap: wrap; padding: 6px 8px; border-bottom: 1px solid var(--line); }
  /* display:flex overrides the UA [hidden] rule, so an empty livebar/replybar stayed
     visible as a stray second border line (John, 2026-09-03 "double line at top and
     bottom of the team chat"). Re-hide them explicitly when the attribute is set. */
  .tm-livebar[hidden], .tm-replybar[hidden], .tm-mentionbar[hidden] { display: none; }
  .tm-mentionbar { display: flex; align-items: center; gap: 7px; font-size: 11.5px; color: var(--accent); background: var(--accent-soft); padding: 5px 10px; border-top: 1px solid var(--accent); }
  .tm-mentionbar .tm-mb-ico { display: grid; place-items: center; width: 16px; height: 16px; border-radius: 50%; background: var(--accent); color: #000; font-weight: 700; font-size: 10px; }
  .tm-mentionbar .tm-mb-txt { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tm-mentionbar .tm-mb-x { background: none; border: none; cursor: pointer; color: var(--accent); font-size: 12px; }
  .tm-dm { display: inline-flex; align-items: center; margin: 1px 0 4px; font-size: 10.5px; color: var(--accent); opacity: .9; }
  .tm-live { background: var(--accent-soft); border: 1px solid var(--accent); border-radius: 999px; color: var(--text); font-size: 11px; padding: 3px 10px; cursor: pointer; }
  .tm-replybar { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--faint); padding: 4px 8px; border-top: 1px solid var(--line); }
  .tm-replybar .tm-reply-txt { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tm-reply-x { background: none; border: none; cursor: pointer; color: var(--faint); font-size: 11px; }
  .tm-text { font-size: 13px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
  .tm-refchip { display: inline-flex; margin-top: 5px; padding: 3px 9px; border-radius: 999px; border: 1px solid var(--accent); background: none; color: var(--accent); font-size: 11.5px; cursor: pointer; }
  .tm-queue { display: block; margin-top: 5px; background: none; border: none; color: var(--muted); font-size: 10.5px; cursor: pointer; padding: 0; opacity: 0; }
  .tm-msg:hover .tm-queue { opacity: .85; }
  .tm-compose { display: flex; gap: 6px; padding: 10px 12px; border-top: 1px solid var(--line); }
  .tm-compose input { flex: 1; background: var(--bg); border: 1px solid var(--line); border-radius: 5px; color: var(--text); font-size: 13px; padding: 7px 9px; }
  .tm-attach { width: 32px; height: 32px; border: 1px solid var(--line); border-radius: 5px; background: var(--bg); color: var(--muted); display: grid; place-items: center; }
  .tm-attach:hover { color: var(--text); border-color: var(--accent); }
  .tm-attach svg { width: 16px; height: 16px; }
  .tm-image-strip { position: relative; width: 74px; margin: 8px 12px 0; }
  .tm-image-strip img { display: block; width: 72px; height: 54px; object-fit: cover; border: 1px solid var(--line); border-radius: 6px; }
  .tm-image-strip button { position: absolute; right: -6px; top: -7px; width: 20px; height: 20px; border: 0; border-radius: 50%; background: var(--text); color: var(--bg); font-size: 11px; }
  .tm-image { display: block; border: 0; padding: 0; margin-top: 7px; background: transparent; cursor: zoom-in; }
  .tm-image img { display: block; max-width: 260px; max-height: 240px; object-fit: contain; border-radius: 5px; }
  .tm-seats { flex: 1; padding: 12px; overflow-y: auto; }
  .tm-seat-head { font-size: 11px; color: var(--faint); font-weight: 700; letter-spacing: .5px; text-transform: uppercase; margin-bottom: 8px; }
  .tm-seat { display: flex; align-items: center; gap: 8px; padding: 7px 4px; border-bottom: 1px solid var(--line); }
  .tm-seat-mail { flex: 1; font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; }
  .tm-seat-st { font-size: 10.5px; color: var(--faint); }
  .tm-seat-x { background: none; border: none; color: var(--faint); cursor: pointer; opacity: 0; }
  .tm-seat:hover .tm-seat-x { opacity: .8; }
  .tm-seat-add { display: flex; gap: 6px; margin-top: 12px; }
  .tm-scim { margin-top: 14px; }
  .tm-scim-out { margin-top: 8px; padding: 8px 10px; background: var(--bg); border: 1px solid var(--line); border-radius: 6px; font-size: 12px; }
  .tm-scim-out .sel { user-select: text; word-break: break-all; margin-top: 4px; }
  .tm-seat-add input { flex: 1; background: var(--bg); border: 1px solid var(--line); border-radius: 5px; color: var(--text); font-size: 13px; padding: 7px 9px; }
  .tm-loading { color: var(--faint); font-size: 12px; padding: 8px 0; }
  /* Manage-team Seats — Maddox design pass (2026-09-01): usage meter, roster with
     identity + status hierarchy, a clear invite section, SCIM as its own card. */
  .tm-seatwrap { display: flex; flex-direction: column; gap: 20px; }
  .tm-usage { display: flex; flex-direction: column; gap: 11px; padding: 15px 16px; border: 1px solid var(--line); border-radius: 12px; background: color-mix(in srgb, var(--text) 3%, transparent); }
  .tm-usage-top { display: flex; align-items: baseline; gap: 8px; }
  .tm-usage-count { font-size: 21px; font-weight: 800; color: var(--text); letter-spacing: -.3px; }
  .tm-usage-of { font-size: 13px; color: var(--muted); }
  .tm-plan { margin-left: auto; align-self: center; font-size: 10.5px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--accent); border: 1px solid var(--accent); border-radius: 999px; padding: 2px 10px; }
  .tm-meter { height: 6px; border-radius: 999px; background: color-mix(in srgb, var(--text) 12%, transparent); overflow: hidden; }
  .tm-meter > i { display: block; height: 100%; border-radius: 999px; background: var(--accent); transition: width .35s ease; }
  .tm-usage-foot { display: flex; align-items: center; font-size: 11.5px; color: var(--faint); }
  .tm-seats-btn { margin-left: auto; background: none; border: none; color: var(--accent); font-size: 12px; font-weight: 600; cursor: pointer; padding: 0; }
  .tm-seats-btn:hover { text-decoration: underline; }
  .tm-sec-h { font-size: 11px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--faint); margin-bottom: 9px; }
  .tm-roster { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; }
  .tm-row { display: flex; align-items: center; gap: 12px; padding: 11px 14px; }
  .tm-row + .tm-row { border-top: 1px solid var(--line); }
  .tm-av { width: 30px; height: 30px; border-radius: 50%; flex: none; display: grid; place-items: center; font-size: 12px; font-weight: 700; color: var(--accent); background: var(--accent-soft); text-transform: uppercase; }
  .tm-id { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
  .tm-email { font-size: 13px; color: var(--text); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tm-badge { align-self: flex-start; display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 600; letter-spacing: .2px; }
  .tm-badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
  .tm-badge.joined { color: #35c07a; }
  .tm-badge.invited { color: var(--muted); }
  .tm-badge.expired { color: #e0603f; }
  .tm-role2 { background: var(--bg); border: 1px solid var(--line); border-radius: 7px; color: var(--text); font-size: 12px; padding: 5px 8px; cursor: pointer; }
  .tm-role2:focus { outline: none; border-color: var(--accent); }
  .tm-resend { background: none; border: 1px solid var(--line); border-radius: 7px; color: var(--muted); font-size: 11px; font-weight: 600; padding: 4px 9px; cursor: pointer; }
  .tm-resend:hover { color: var(--text); border-color: var(--accent); }
  .tm-rm { background: none; border: none; color: var(--faint); cursor: pointer; font-size: 13px; padding: 4px 7px; border-radius: 6px; opacity: 0; transition: opacity .12s, color .12s, background .12s; }
  .tm-row:hover .tm-rm { opacity: 1; }
  .tm-rm:hover { color: #e0603f; background: color-mix(in srgb, #e0603f 15%, transparent); }
  .tmdoc-l { display: block; margin: 12px 0 0; font-size: 12px; color: var(--dim); }
  .tmdoc-l select, .tmdoc-l input, .tmdoc-l textarea {
    display: block; width: 100%; box-sizing: border-box; margin-top: 5px;
    background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px;
    color: var(--text); padding: 9px 12px; font-size: 13px; font-family: inherit;
  }
  .tmdoc-l textarea { resize: vertical; min-height: 120px; }
  .tmdoc-l select:focus, .tmdoc-l input:focus, .tmdoc-l textarea:focus { outline: none; border-color: var(--accent); }
  .tm-invite { display: flex; gap: 8px; align-items: flex-start; }
  .tm-invite input:not(.invite-chip-input) { flex: 1; background: var(--bg); border: 1px solid var(--line); border-radius: 9px; color: var(--text); font-size: 13px; padding: 9px 12px; }
  .tm-invite input:not(.invite-chip-input):focus { outline: none; border-color: var(--accent); }
  /* Chip field inside Seats reuses the referral invite chips, but stays inline with the
     Send button (the global .invite-send is a full-width stacked button). */
  .tm-invite .invite-chips { flex: 1; min-height: 42px; border-radius: 9px; }
  .tm-invite .invite-send { margin-top: 0; width: auto; align-self: stretch; white-space: nowrap; border-radius: 9px; }
  .tm-hint { font-size: 11.5px; color: var(--faint); margin-top: 8px; line-height: 1.5; }
  .tm-scim2 { display: flex; align-items: flex-start; gap: 12px; padding: 13px 14px; border: 1px dashed var(--line); border-radius: 12px; }
  .tm-scim2-txt { flex: 1; }
  .tm-scim2-t { font-size: 12.5px; font-weight: 600; color: var(--text); margin-bottom: 3px; }
  .tm-scim2-d { font-size: 11.5px; color: var(--faint); line-height: 1.5; }
  /* Team identity + welcome popup (John, 2026-09-02) */
  .tm-logo { display: inline-grid; place-items: center; border-radius: 22%; overflow: hidden; background: var(--accent-soft); color: var(--accent); font-weight: 800; flex: none; }
  .tm-logo img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .tm-logo.mono { font-size: 40%; }
  .tm-prof { display: flex; gap: 18px; align-items: flex-start; padding: 16px; border: 1px solid var(--line); border-radius: 12px; background: color-mix(in srgb, var(--text) 3%, transparent); }
  .tm-prof-logo .tm-logo { font-size: 34px; }
  .tm-prof-fields { flex: 1; min-width: 0; }
  .tm-prof-name { width: 100%; background: var(--bg); border: 1px solid var(--line); border-radius: 9px; color: var(--text); font-size: 14px; font-weight: 600; padding: 9px 12px; }
  .tm-prof-name:focus { outline: none; border-color: var(--accent); }
  .tm-prof-name:disabled { opacity: .7; }
  .tm-prof-acts { display: flex; gap: 8px; margin-top: -8px; }
  .tm-feat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
  .tm-feat { padding: 12px 12px; border: 1px solid var(--line); border-radius: 12px; display: flex; align-items: flex-start; gap: 10px; background: transparent; text-align: left; cursor: pointer; font-family: inherit; transition: border-color .13s ease, background .13s ease, transform .13s ease, box-shadow .13s ease; }
  .tm-feat:hover { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); background: var(--accent-soft); transform: translateY(-1px); box-shadow: 0 6px 18px -12px rgba(0,0,0,.5); }
  .tm-feat-ic { flex: none; width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center; color: #0b0b0d; background: var(--fd-tint, var(--accent)); box-shadow: 0 2px 8px -3px color-mix(in srgb, var(--fd-tint, var(--accent)) 60%, transparent); }
  .tm-feat-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
  .tm-feat-t { font-size: 12.5px; font-weight: 600; color: var(--text); }
  .tm-feat-d { font-size: 11px; color: var(--faint); line-height: 1.45; }
  .tm-feat-go { flex: none; color: var(--faint); font-size: 18px; line-height: 1; opacity: 0; transform: translateX(-3px); transition: opacity .13s ease, transform .13s ease; align-self: center; }
  .tm-feat:hover .tm-feat-go { opacity: 1; transform: translateX(0); color: var(--accent); }
  .tm-feature-detail { width: min(460px, 92vw); padding: 0; overflow: hidden; }
  .tm-fd-hero { display: flex; align-items: center; gap: 13px; padding: 20px 22px; background: linear-gradient(135deg, color-mix(in srgb, var(--fd-tint) 22%, transparent), color-mix(in srgb, var(--fd-tint) 6%, transparent)); border-bottom: 1px solid var(--line); }
  .tm-fd-glyph { flex: none; width: 44px; height: 44px; border-radius: 12px; display: grid; place-items: center; color: #0b0b0d; background: var(--fd-tint); box-shadow: 0 4px 14px -5px color-mix(in srgb, var(--fd-tint) 70%, transparent); }
  .tm-fd-htxt h3 { margin: 0 0 3px; font-size: 16px; }
  .tm-fd-why { margin: 0; font-size: 12px; color: var(--muted); line-height: 1.45; }
  .tm-feature-summary { color: var(--muted); font-size: 13px; line-height: 1.55; padding: 16px 22px 0; margin: 0; }
  .tm-feature-how { margin: 14px 0 0; padding: 0 22px; }
  .tm-feature-how b { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--faint); }
  .tm-fd-steps { margin: 10px 0 0; padding: 0; list-style: none; counter-reset: fd; display: flex; flex-direction: column; gap: 9px; }
  .tm-fd-steps li { position: relative; padding-left: 30px; font-size: 13px; color: var(--text); line-height: 1.5; counter-increment: fd; }
  .tm-fd-steps li::before { content: counter(fd); position: absolute; left: 0; top: 0; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; font-size: 11px; font-weight: 700; color: #0b0b0d; background: var(--fd-tint, var(--accent)); }
  .tm-fd-acts { padding: 18px 22px 20px; }
  /* ---- Team → Policy tab (John, 2026-09-03: "make this a real end-to-end feature") ---- */
  .tp-wrap { display: flex; flex-direction: column; gap: 18px; padding-bottom: 72px; }
  .tp-sec { border: 1px solid var(--line); border-radius: 12px; padding: 16px 16px 14px; background: color-mix(in srgb, var(--panel) 70%, transparent); }
  .tp-sec-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; margin-bottom: 12px; }
  .tp-sec-t { font-size: 13.5px; font-weight: 700; color: var(--text); }
  .tp-sec-d { font-size: 11.5px; color: var(--faint); line-height: 1.5; margin-top: 2px; max-width: 520px; }
  .tp-seg { flex: none; display: inline-flex; border: 1px solid var(--line); border-radius: 999px; padding: 2px; background: var(--bg); }
  .tp-seg button { border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 12px; font-weight: 600; padding: 5px 12px; border-radius: 999px; cursor: pointer; }
  .tp-seg button.on { background: var(--accent); color: #0b0b0d; }
  .tp-seg button:disabled { cursor: default; opacity: .6; }
  .tp-models { display: flex; flex-direction: column; gap: 12px; transition: opacity .15s; }
  .tp-models.off { opacity: .45; }
  .tp-eng-h { display: flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 600; color: var(--text); margin-bottom: 7px; }
  .tp-eng-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
  .tp-eng-v { color: var(--faint); font-weight: 400; }
  .tp-eng-acts { margin-left: auto; display: flex; gap: 8px; }
  .tp-link { border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 11px; cursor: pointer; padding: 0; }
  .tp-link:hover:not(:disabled) { color: var(--accent); text-decoration: underline; }
  .tp-link:disabled { opacity: .4; cursor: default; }
  .tp-chips { display: flex; flex-wrap: wrap; gap: 7px; }
  .tp-chip { display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px 6px 8px; border-radius: 999px; border: 1px solid var(--line); background: transparent; color: var(--muted); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; transition: all .13s ease; }
  .tp-chip-mark { width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid var(--line); display: grid; place-items: center; flex: none; transition: all .13s ease; }
  .tp-chip.on { border-color: color-mix(in srgb, var(--chip) 60%, var(--line)); background: color-mix(in srgb, var(--chip) 14%, transparent); color: var(--text); }
  .tp-chip.on .tp-chip-mark { background: var(--chip); border-color: var(--chip); }
  .tp-chip.on .tp-chip-mark::after { content: ""; width: 4px; height: 7px; border: solid #0b0b0d; border-width: 0 2px 2px 0; transform: rotate(45deg) translate(-0.5px, -0.5px); }
  .tp-chip:not(.on) { text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--faint) 60%, transparent); }
  .tp-chip:disabled { cursor: default; }
  .tp-chip:hover:not(:disabled) { transform: translateY(-1px); }
  .tp-count { margin-top: 12px; font-size: 11.5px; color: var(--faint); }
  .tp-count.warn { color: #f59e0b; }
  .tp-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid var(--line); }
  .tp-row.tp-master { border-top: 0; padding-top: 2px; }
  .tp-row-txt { flex: 1; min-width: 0; }
  .tp-row-t { font-size: 12.5px; font-weight: 600; color: var(--text); }
  .tp-row-d { font-size: 11px; color: var(--faint); line-height: 1.45; margin-top: 1px; }
  .tp-conns { margin-top: 6px; transition: opacity .15s; }
  .tp-conns.off { opacity: .45; }
  .tp-conn-ic { flex: none; width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; font-size: 12px; font-weight: 700; color: var(--text); background: var(--accent-soft); border: 1px solid var(--line); }
  .tp-conn.blocked .tp-conn-ic { background: transparent; color: var(--faint); }
  .tp-conn.blocked .tp-row-t { color: var(--muted); }
  .tp-state { flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; padding: 3px 8px; border-radius: 999px; color: #0b0b0d; background: var(--accent); }
  .tp-conn.blocked .tp-state { background: transparent; color: var(--faint); border: 1px solid var(--line); }
  .tp-sw { flex: none; width: 36px; height: 20px; border-radius: 999px; border: 0; background: var(--line); position: relative; cursor: pointer; transition: background .15s; padding: 0; }
  .tp-sw::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #cfcfcf; transition: transform .15s, background .15s; }
  .tp-sw.on { background: var(--accent); }
  .tp-sw.on::after { transform: translateX(16px); background: #0b0b0d; }
  .tp-sw:disabled { cursor: default; opacity: .55; }
  .tp-foot { position: sticky; bottom: 0; margin: 0 -4px -4px; padding: 12px 16px; display: flex; align-items: center; justify-content: space-between; gap: 12px; background: color-mix(in srgb, var(--panel) 92%, transparent); backdrop-filter: blur(10px); border-top: 1px solid var(--line); border-radius: 0 0 12px 12px; }
  .tp-foot.dirty { border-top-color: color-mix(in srgb, var(--accent) 50%, var(--line)); }
  .tp-prov { font-size: 11px; color: var(--faint); min-width: 0; }
  .tp-acts { display: flex; gap: 8px; flex: none; }
  .tm-usage-card { border: 1px solid var(--line); border-radius: 10px; padding: 12px; margin-bottom: 9px; }
  .tm-usage-card-head { display: flex; justify-content: space-between; gap: 12px; font-size: 12.5px; }
  .tm-usage-card-head span, .tm-usage-split { color: var(--faint); font-size: 11.5px; }
  .tm-usage-split { margin-top: 7px; }
  .tm-usage-models { white-space: pre-line; color: var(--muted); font-size: 11.5px; line-height: 1.6; margin-top: 8px; }
  .tm-usage-events { margin-top: 8px; background: none; border: none; color: var(--accent); padding: 0; cursor: pointer; font-size: 11.5px; }
  .tm-usage-event-list { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); color: var(--muted); font-size: 11px; line-height: 1.7; }
  .tmw-overlay { display: flex; backdrop-filter: blur(4px); }
  .tmw-card { width: min(520px, 92vw); max-height: 88vh; overflow-y: auto; background: var(--panel); border: 1px solid var(--line); border-radius: 18px; box-shadow: 0 30px 90px rgba(0,0,0,.55); padding: 30px 30px 22px; transform: translateY(12px) scale(.98); opacity: 0; transition: transform .28s cubic-bezier(.2,.8,.2,1), opacity .22s ease; }
  .tmw-card.in { transform: none; opacity: 1; }
  .tmw-hero { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px; padding-bottom: 20px; border-bottom: 1px solid var(--line); }
  .tmw-hero .tm-logo { box-shadow: 0 0 0 6px var(--accent-soft); }
  .tmw-h { font-size: 21px; font-weight: 800; letter-spacing: -.3px; color: var(--text); margin-top: 6px; }
  .tmw-sub { font-size: 13px; color: var(--muted); line-height: 1.55; max-width: 400px; }
  .tmw-plan { color: var(--accent); font-weight: 800; }
  .tmw-list { display: flex; flex-direction: column; gap: 2px; padding: 16px 0 6px; }
  .tmw-row { display: flex; gap: 12px; align-items: flex-start; padding: 8px 6px; border-radius: 8px; }
  .tmw-row:hover { background: color-mix(in srgb, var(--text) 4%, transparent); }
  .tmw-check { flex: none; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent); font-size: 12px; font-weight: 800; margin-top: 1px; }
  .tmw-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
  .tmw-t { font-size: 13px; font-weight: 600; color: var(--text); }
  .tmw-d { font-size: 11.5px; color: var(--faint); line-height: 1.45; }
  .tmw-foot { display: flex; justify-content: flex-end; gap: 8px; padding-top: 14px; border-top: 1px solid var(--line); margin-top: 8px; }
  /* Shared sessions (John, 2026-09-02) */
  /* Author chip sits UNDER the message text as its own line, never overlaid on top of
     it (John, 2026-09-06: the old absolute top-right chip sat on top of the bubble). */
  .msg-by { display: inline-flex; align-items: center; gap: 4px; margin: 4px 0 0 0; font-size: 10px; font-weight: 700; letter-spacing: .3px; color: var(--accent); background: var(--accent-soft); border-radius: 999px; padding: 1px 8px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .msg-by svg { width: 11px; height: 11px; flex: none; }
  .shared-head .od-count, .shared-owner { color: var(--faint); }
  .shared-owner { font-size: 10.5px; margin-left: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 90px; }
  .row.shared-session .sname { max-width: 55%; }
  .shq { border-top: 1px solid var(--line); background: color-mix(in srgb, var(--text) 2.5%, transparent); padding: 8px 12px 6px; max-height: 190px; overflow-y: auto; }
  .shq[hidden] { display: none; }
  .shq-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
  .shq-title { font-size: 11px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--faint); }
  .shq-count { font-size: 10.5px; font-weight: 700; color: var(--accent); background: var(--accent-soft); border-radius: 999px; padding: 0 7px; }
  .shq-hint { margin-left: auto; font-size: 10.5px; color: var(--faint); }
  .shq-row { display: flex; align-items: center; gap: 9px; padding: 5px 6px; border-radius: 8px; }
  .shq-row:hover { background: color-mix(in srgb, var(--text) 5%, transparent); }
  .shq-row.st-running { background: var(--accent-soft); }
  .shq-row.st-paused { opacity: .6; }
  .shq-av { width: 22px; height: 22px; border-radius: 50%; flex: none; display: grid; place-items: center; font-size: 10px; font-weight: 800; color: var(--accent); background: var(--accent-soft); }
  .shq-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
  .shq-by { font-size: 10.5px; font-weight: 700; color: var(--text); }
  .shq-t { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .shq-st { font-size: 10.5px; color: var(--faint); min-width: 44px; text-align: right; }
  .shq-acts { display: flex; gap: 2px; opacity: 0; transition: opacity .12s; }
  .shq-row:hover .shq-acts { opacity: 1; }
  .shq-btn { background: none; border: 1px solid var(--line); border-radius: 6px; color: var(--muted); font-size: 10.5px; padding: 2px 6px; cursor: pointer; }
  .shq-btn:hover { color: var(--text); border-color: var(--accent); }
  .shp-card { width: min(560px, 92vw); }
  /* Move to… popup (John, 2026-09-10): chips for the sessions being moved, a folder tree to pick from. */
  .mvt-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0 10px; }
  .mvt-chip { display: inline-flex; align-items: center; gap: 4px; font-size: 12.5px; color: var(--text); background: color-mix(in srgb, var(--text) 6%, transparent); border: 1px solid var(--line); border-radius: 999px; padding: 4px 10px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mvt-chip-x { background: none; border: none; color: var(--faint); cursor: pointer; font-size: 15px; line-height: 1; padding: 0 0 0 2px; }
  .mvt-chip-x:hover { color: var(--text); }
  .mvt-matches { max-height: 200px; margin-bottom: 10px; }
  .mvt-where { flex: none; font-size: 11.5px; color: var(--faint); }
  .mvt-lbl { font-size: 11px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; color: var(--faint); margin: 6px 0 6px; }
  .mvt-dest { max-height: 300px; }
  .mvt-row.on { background: var(--accent-soft); }
  .mvt-row.on .shp-mail { color: var(--accent); font-weight: 600; }
  .tmw-foot .btn-primary.busy { position: relative; padding-left: 30px; opacity: .85; cursor: default; }
  .tmw-foot .btn-primary.busy::before { content: ''; position: absolute; left: 11px; top: 50%; width: 12px; height: 12px; margin-top: -6px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: acctSpin .7s linear infinite; }
  .tmw-foot .btn-primary.shp-go-err { background: #ff6b6b; border-color: #ff6b6b; color: #1a1a1a; }
  .shp-h .tmw-h { text-align: left; margin-top: 0; }
  .shp-h .tmw-sub { text-align: left; max-width: none; }
  .shp-modes { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 18px 0 14px; }
  .shp-mode { text-align: left; display: flex; flex-direction: column; gap: 3px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: none; color: var(--text); cursor: pointer; }
  .shp-mode.on { border-color: var(--accent); background: var(--accent-soft); }
  .shp-mode-t { font-size: 13px; font-weight: 700; }
  .shp-mode-d { font-size: 11.5px; color: var(--faint); }
  .shp-list { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; max-height: 280px; overflow-y: auto; }
  .shp-row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; cursor: pointer; }
  .shp-row + .shp-row { border-top: 1px solid var(--line); }
  .shp-row:hover { background: color-mix(in srgb, var(--text) 4%, transparent); }
  .shp-row.dim { opacity: .55; cursor: default; }
  .shp-row .tm-av { width: 26px; height: 26px; font-size: 11px; }
  .shp-mail { flex: 1; font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; }
  .shp-role { flex: none; font-size: 12px; color: var(--text); background: color-mix(in srgb, var(--text) 5%, transparent); border: 1px solid var(--line); border-radius: 8px; padding: 3px 6px; cursor: pointer; appearance: auto; }
  .shp-x { flex: none; background: none; border: none; color: #e5484d; cursor: pointer; font-size: 18px; line-height: 1; padding: 0 2px; opacity: .75; }
  .shp-x:hover { opacity: 1; }
  .shp-row.off { opacity: .5; }
  .shp-row.off:hover { opacity: .8; }
  .shp-add { flex: none; font-size: 12px; color: var(--faint); border: 1px solid var(--line); border-radius: 8px; padding: 3px 9px; }
  .shp-row.off:hover .shp-add { color: var(--text); border-color: color-mix(in srgb, var(--text) 30%, transparent); }
  /* Search-first roster: type to find a teammate; nobody listed until you do. Scales to 500+ seats. */
  .shp-search { width: 100%; box-sizing: border-box; margin: 0 0 10px; font-size: 13px; color: var(--text); background: color-mix(in srgb, var(--text) 4%, transparent); border: 1px solid var(--line); border-radius: 10px; padding: 9px 12px; }
  .shp-search:focus { outline: none; border-color: var(--accent); background: color-mix(in srgb, var(--text) 6%, transparent); }
  .shp-search::placeholder { color: var(--faint); }
  .shp-chosen { max-height: 168px; margin-bottom: 10px; }
  .shp-results .tm-hint { padding: 12px 4px; }
  .btn-ghost.danger { color: #e0603f; }
  .shared-pill { margin-left: 6px; font-size: 10px; font-weight: 700; letter-spacing: .3px; color: var(--accent); border: 1px solid var(--accent); border-radius: 999px; padding: 0 7px; white-space: nowrap; flex: none; }
  .shf { display: flex; flex-direction: column; }
  .shf-head .fname { flex: 1; }
  .shf-head .fcount { font-size: 10.5px; color: var(--faint); margin-right: 4px; }
  .shf-kids { display: flex; flex-direction: column; }
  .shf-group { padding-left: 22px; color: var(--muted); font-size: 12.5px; cursor: pointer; }
  .shf-group .ficon { display: inline-block; width: 12px; transition: transform .12s; font-size: 10px; }
  .shf-group.open .ficon { transform: rotate(90deg); }
  .shf-session { padding-left: 26px; }
  .row.folder .shared-pill { margin-left: 4px; }
  .admin-testing-tiers { display: flex; gap: 6px; flex-wrap: wrap; margin: 6px 0 2px; }

/* Watchers — background-work transparency under Active Sessions (2026-08-30) */
#watchersBox { padding: 0 10px 4px; }
#watchersBox .sec-head { padding: 8px 4px 4px; }
.watcher-row { display: flex; align-items: center; gap: 7px; padding: 3px 6px; margin-bottom: 2px; border-radius: 4px; font-size: 12px; color: var(--muted); }
.watcher-row .wdot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); animation: micpulse 2.2s ease-in-out infinite; flex: 0 0 auto; }
.watcher-row .wname { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.watcher-row .wsess { font-size: 10.5px; color: var(--faint); }

/* Staged-update banner: an installed fix is on disk but the running app predates it. */
.stale-code-bar {
  position: fixed; top: 0; left: 50%; transform: translateX(-50%);
  z-index: 10000; padding: 5px 14px; border-radius: 0 0 8px 8px;
  background: #ff6500; color: #111; font-size: 12px; font-weight: 700;
  box-shadow: 0 6px 20px rgba(0,0,0,.4); pointer-events: none;
}

/* Purple in-reply Journal doc link — [[doc: id|label]] renders as this, never a bare id. */
.scrap-doc-link {
  color: #a880fa; font-weight: 600; cursor: pointer; text-decoration: none;
  border-bottom: 1px solid rgba(168,128,250,.45);
}
.scrap-doc-link:hover { color: #c4a6ff; border-bottom-color: #c4a6ff; }
/* [Session name] in a reply → clickable link that opens the session. */
.sess-mention-link {
  color: var(--accent); font-weight: 600; cursor: pointer; text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
}
.sess-mention-link:hover { border-bottom-color: var(--accent); }
.acct-mfa-setup { margin-top: 12px; }
.acct-mfa-secret { display: block; margin-top: 10px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 4px; color: var(--accent); background: rgba(0,0,0,.22); font: 600 13px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .08em; overflow-wrap: anywhere; user-select: all; }
.tm-msg.pending { opacity: .68; }
  /* Manage team audit fixes (2026-09-03): policy modal checkboxes, readable audit rows. */
  .tmpol-chk { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: 13px; color: var(--text); cursor: pointer; }
  .tmpol-chk input { accent-color: var(--accent); }
  /* Team audit (2026-09-06, //maddox): filter row, day groups, sentence rows with a category glyph. */
  .ta-filters { justify-content: space-between; }
  .ta-search { flex: 1 1 220px; max-width: 320px; box-sizing: border-box; background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; font: inherit; font-size: 12.5px; outline: none; }
  .ta-search:focus { border-color: var(--accent); }
  .ta-day { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); margin: 14px 0 6px 2px; }
  .ta-day:first-child { margin-top: 2px; }
  .ta-group { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: color-mix(in srgb, var(--text) 2%, transparent); }
  .ta-row { display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 10px 14px; border-top: 1px solid var(--line); }
  .ta-row:first-child { border-top: 0; }
  .ta-ic { width: 26px; height: 26px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center; color: var(--muted); background: color-mix(in srgb, var(--text) 6%, transparent); }
  .ta-ic svg { width: 14px; height: 14px; }
  .ta-row[data-cat="people"] .ta-ic { color: #5b8def; background: rgba(91,141,239,.14); }
  .ta-row[data-cat="sharing"] .ta-ic { color: #e58a2f; background: rgba(229,138,47,.14); }
  .ta-row[data-cat="policy"] .ta-ic { color: #a78bfa; background: rgba(167,139,250,.16); }
  .ta-row[data-cat="billing"] .ta-ic { color: #34a853; background: rgba(52,168,83,.14); }
  .ta-row[data-cat="settings"] .ta-ic { color: var(--muted); }
  .ta-body { min-width: 0; }
  .ta-line { font-size: 13px; color: var(--text); line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ta-line b { font-weight: 600; }
  .ta-who { color: var(--text); }
  .ta-sub { font-size: 11px; color: var(--faint); margin-top: 2px; }
  .ta-when { color: var(--faint); font-size: 11.5px; white-space: nowrap; font-variant-numeric: tabular-nums; }

  /* Folder/subfolder acronym prefix on session titles: dimmed so the name stands out (theme-safe opacity). */
  .title-acr { opacity: .5; font-weight: inherit; }

  /* Installing-update screen (shown on click, before the app quits to swap bundles). */
  #install-cover { position: fixed; inset: 0; z-index: 99999; display: none; align-items: center; justify-content: center; background: var(--bg, #0d0d0d); color: var(--text); }
  #install-cover .ic-box { display: flex; flex-direction: column; align-items: center; gap: 14px; max-width: 420px; text-align: center; padding: 24px; }
  #install-cover .ic-title { font-size: 16px; font-weight: 600; }
  #install-cover .ic-sub { font-size: 12.5px; color: var(--muted); line-height: 1.5; }
  #install-cover .ic-spin { width: 28px; height: 28px; border-radius: 50%; border: 3px solid var(--line); border-top-color: var(--accent); animation: ic-rot .9s linear infinite; }
  @keyframes ic-rot { to { transform: rotate(360deg); } }

/* Paywall creator-code (affiliate) row */
.pw-refcode { margin-top: 14px; text-align: center; font-size: 13px; }
.pw-refcode-toggle { background: none; border: none; color: rgba(255,255,255,.6); font-size: 12.5px; cursor: pointer; text-decoration: underline; padding: 4px; }
.pw-refcode-toggle:hover { color: rgba(255,255,255,.9); }
.pw-refcode-form { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: center; }
.pw-refcode-in { background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.18); border-radius: 8px; color: #fff; padding: 7px 10px; font-size: 13px; letter-spacing: .08em; text-transform: uppercase; width: 160px; }
.pw-refcode-in:focus { outline: none; border-color: var(--accent, #ff6a44); }
.pw-refcode-apply { background: rgba(255,255,255,.12); border: 1px solid rgba(255,255,255,.2); border-radius: 8px; color: #fff; padding: 7px 12px; font-size: 12.5px; cursor: pointer; }
.pw-refcode-apply:hover { background: rgba(255,255,255,.2); }
.pw-refcode-msg { font-size: 12px; color: rgba(255,255,255,.7); }

  /* ---- Solace (//ask · ⌘K · avatar menu) -----------------------------------------
     The in-app helper. Same modal shell as every other sheet; a scrolling thread of
     plain bubbles, starter questions in the empty state, one-line composer. Accent
     comes from the user's pick (never hardcoded), radius 3px like everything else. */
  .ask-modal { width: 560px; max-height: 84vh; padding: 0; overflow: hidden; }
  .ask-head { display: flex; align-items: center; gap: 10px; padding: 16px 18px 12px; border-bottom: 1px solid var(--line); }
  /* Solace's living orb: a breathing CSS halo (GPU) under the canvas shell. No tile,
     no border: the orb floats. The halo brightens and quickens while she is thinking. */
  .ask-mark { position: relative; width: 46px; height: 46px; display: grid; place-items: center; flex: 0 0 auto; }
  .ask-halo { position: absolute; inset: 8%; border-radius: 50%; pointer-events: none;
    background: radial-gradient(circle, rgba(var(--accent-rgb), .55) 0%, rgba(var(--accent-rgb), .18) 45%, rgba(var(--accent-rgb), 0) 72%);
    filter: blur(7px); opacity: .75; animation: ask-breathe 3.6s ease-in-out infinite; }
  .ask-mark.thinking .ask-halo { opacity: 1; animation-duration: 1.4s; inset: 0; }
  .ask-mark-sphere { position: relative; display: block; width: 46px; height: 46px; background: transparent; }
  .ask-hero-wrap { position: relative; display: block; width: 168px; height: 168px; margin: 0 auto 4px; }
  .ask-hero-wrap .ask-halo { inset: 14%; filter: blur(18px); }
  .ask-hero { position: relative; display: block; width: 168px; height: 168px; }
  @keyframes ask-breathe { 0%, 100% { transform: scale(.92); opacity: .6; } 50% { transform: scale(1.06); opacity: .95; } }
  @media (prefers-reduced-motion: reduce) { .ask-halo { animation: none; } }
  .ask-title { flex: 1; min-width: 0; }
  .ask-title h3 { margin: 0; font-size: 15px; }
  .ask-sub { color: var(--muted); font-size: 12px; line-height: 1.35; margin-top: 2px; }
  .ask-clear, .ask-x { background: transparent; border: 1px solid var(--line); color: var(--muted); border-radius: 3px; cursor: pointer; font-size: 12px; padding: 5px 9px; }
  .ask-x { padding: 4px 8px; }
  .ask-clear:hover, .ask-x:hover { color: var(--text); background: var(--hover); }
  .ask-thread { flex: 1 1 auto; min-height: 240px; overflow-y: auto; padding: 16px 18px; display: flex; flex-direction: column; gap: 10px; }
  .ask-msg { max-width: 88%; border-radius: 3px; padding: 10px 12px; font-size: 13.5px; line-height: 1.5; word-break: break-word; }
  .ask-msg.me { align-self: flex-end; background: var(--accent-soft); color: var(--text); white-space: pre-wrap; }
  .ask-msg.ow { align-self: flex-start; background: var(--panel-2); border: 1px solid var(--line); color: var(--text); }
  .ask-msg.ow p { margin: 0 0 8px; }
  .ask-msg.ow p:last-child { margin-bottom: 0; }
  .ask-msg.ow ul, .ask-msg.ow ol { margin: 4px 0 8px 18px; }
  .ask-cards { align-self: flex-start; max-width: 88%; display: flex; flex-direction: column; gap: 6px; margin-top: -4px; }
  .ask-card-row { display: flex; align-items: center; gap: 10px; text-align: left; padding: 8px 10px; border-radius: 3px; border: 1px solid var(--line); background: var(--panel-2); color: inherit; cursor: pointer; width: 100%; }
  .ask-card-row:hover { border-color: var(--accent); background: var(--accent-soft); }
  .ask-card-kind { flex: 0 0 auto; font-size: 10.5px; font-weight: 600; letter-spacing: .3px; text-transform: uppercase; color: var(--accent); border: 1px solid var(--accent); border-radius: 3px; padding: 2px 6px; }
  .ask-card-txt { flex: 1 1 auto; min-width: 0; }
  .ask-card-t { display: block; font-size: 13px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ask-card-d { display: block; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 1px; }
  .ask-wait { display: flex; gap: 5px; align-items: center; padding: 12px 14px; }
  .ask-wait span { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); opacity: .35; animation: ask-dot 1.2s infinite ease-in-out; }
  .ask-wait span:nth-child(2) { animation-delay: .2s; }
  .ask-wait span:nth-child(3) { animation-delay: .4s; }
  @keyframes ask-dot { 0%, 80%, 100% { opacity: .35; transform: translateY(0); } 40% { opacity: 1; transform: translateY(-2px); } }
  .ask-empty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 10px 0 2px; }
  .ask-hello { font-size: 15px; font-weight: 600; color: var(--text); text-align: center; }
  .ask-starters { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
  .ask-starter { background: var(--panel-2); border: 1px solid var(--line); color: var(--text); border-radius: 3px; padding: 7px 11px; font-size: 12.5px; cursor: pointer; text-align: left; }
  .ask-starter:hover { border-color: var(--accent); color: var(--accent); }
  .ask-compose { display: flex; align-items: flex-end; gap: 8px; padding: 12px 18px; border-top: 1px solid var(--line); }
  .ask-input { flex: 1; resize: none; min-height: 36px; max-height: 120px; background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; color: var(--text); font: inherit; font-size: 13.5px; line-height: 1.4; padding: 8px 10px; outline: none; }
  .ask-input:focus { border-color: var(--accent); }
  .ask-send { width: 36px; height: 36px; display: grid; place-items: center; background: var(--accent); color: var(--on-accent); border: none; border-radius: 3px; cursor: pointer; flex: 0 0 auto; }
  .ask-send:disabled { opacity: .45; cursor: default; }
  .ask-foot { padding: 0 18px 12px; color: var(--faint); font-size: 11.5px; }
  .ask-foot a { color: var(--muted); text-decoration: underline; cursor: pointer; }
  .ask-foot a:hover { color: var(--accent); }

/* ---- Background Task Transparency & Active Job Tracking (100% visibility) ---- */
.mc-chip.has-running-jobs { border-color: rgba(var(--bo-rgb), .6); }
.mc-jobs-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .02em;
  padding: 1px 7px;
  border-radius: 999px;
  background: rgba(var(--bo-rgb), .18);
  color: var(--bo-txt);
  cursor: pointer;
  white-space: nowrap;
}
.mc-badge-dot.working {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--bo-lt);
  animation: micpulse 1.15s ease-in-out infinite;
}

/* Background task live log viewer modal */
.bg-log-overlay {
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, .75);
}
.bg-log-modal {
  width: 720px;
  max-width: 92vw;
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  background: var(--panel-2, #161616);
  border: 1px solid var(--line);
  border-radius: 4px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .6);
  padding: 0;
  overflow: hidden;
}
.bg-log-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}
.bg-log-head-t {
  display: flex;
  align-items: center;
  gap: 10px;
}
.bg-log-head-t h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
}
.bg-log-status-pill {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 3px;
  background: var(--hover);
  color: var(--muted);
}
.bg-log-status-pill.pending {
  color: var(--bo-txt);
  background: rgba(var(--bo-rgb), .16);
}
.bg-log-status-pill.done, .bg-log-status-pill.completed {
  color: #30a46c;
  background: rgba(48, 164, 108, .16);
}
.bg-log-status-pill.failed, .bg-log-status-pill.error {
  color: #e5484d;
  background: rgba(229, 72, 77, .16);
}
.bg-log-status-pill.cancelled, .bg-log-status-pill.stopped {
  color: var(--muted);
  background: rgba(128, 128, 128, .16);
}
.bg-log-meta {
  padding: 10px 18px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  font-size: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  color: var(--muted);
}
.bg-log-meta-row strong {
  color: var(--text);
  margin-right: 4px;
}
.bg-log-meta code {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace);
  font-size: 11px;
  background: rgba(var(--bo-rgb), .08);
  padding: 2px 5px;
  border-radius: 3px;
  color: var(--text);
}
.bg-log-path {
  word-break: break-all;
  opacity: .85;
  font-size: 11px;
}
.bg-log-body {
  flex: 1 1 auto;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 260px;
  max-height: 52vh;
  background: #0d0f12;
}
.bg-log-pre {
  flex: 1;
  margin: 0;
  padding: 14px 18px;
  overflow-y: auto;
  overflow-x: auto;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace);
  font-size: 11.5px;
  line-height: 1.5;
  color: #d0d7de;
  white-space: pre-wrap;
  word-break: break-all;
  user-select: text;
  -webkit-user-select: text;
}
.bg-log-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 18px;
  border-top: 1px solid var(--line);
  background: var(--panel);
  font-size: 11.5px;
  color: var(--muted);
}
.bg-log-actions {
  display: flex;
  gap: 8px;
  align-items: center;
}

/* In-pane background task live card - retired (appear only in composer jobs chip at bottom right) */
.msg.assistant.bg-task-card,
.pane-body .bg-task-card,
.pane-body .mc-job-card {
  display: none !important;
}
.bg-card-inner {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.bg-card-job {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.bg-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
}
.bg-card-t {
  font-weight: 600;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  letter-spacing: -.1px;
}
.bg-card-eng {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .4px;
  padding: 1px 5px;
  border-radius: 3px;
  background: rgba(var(--bo-rgb), .14);
  color: var(--bo-txt);
  flex-shrink: 0;
}
.bg-card-timer {
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.bg-card-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: 4px;
  flex-shrink: 0;
}
.bg-card-actions .bg-card-btn {
  font-size: 10.5px;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: 4px;
  height: 20px;
  line-height: 18px;
  background: var(--hover);
  border: 1px solid var(--line);
  color: var(--text);
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}
.bg-card-actions .bg-card-btn:hover {
  background: var(--active);
  border-color: var(--accent);
}
.bg-card-actions .bg-card-btn.danger {
  color: #ff6b6b;
  border-color: rgba(255, 107, 107, .25);
  background: rgba(255, 107, 107, .08);
}
.bg-card-actions .bg-card-btn.danger:hover {
  background: rgba(255, 107, 107, .2);
  border-color: #ff6b6b;
}
.bg-card-prog {
  margin: 1px 0;
}
.bg-card-prog .job-prog {
  padding: 0;
  gap: 8px;
}
.bg-card-prog .job-prog-track {
  height: 5px;
  border-radius: 3px;
  background: rgba(var(--bo-rgb), .18);
}
.bg-card-prog .job-prog-fill {
  border-radius: 3px;
  background: var(--bo-lt);
}
.bg-card-prog .job-prog-pct {
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--bo-txt);
  min-width: 32px;
  text-align: right;
}

/* Master Control Requests Tab: Active & Recent Background Jobs */
.mcx-jobs-sec {
  margin-bottom: 16px;
}
.mc-active-jobs-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}
.mc-job-card {
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel-2);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: border-color .15s ease, background .15s ease;
}
.mc-job-card.running {
  border-left: 3px solid var(--bo-lt);
  background: rgba(var(--bo-rgb), .04);
}
.mc-job-card.running.live-run {
  border-left-color: var(--accent);
  cursor: pointer;
}
.mc-job-card.done {
  opacity: .88;
}
.mc-job-card.done.failed {
  border-left: 3px solid #e5484d;
}
.mc-job-card.done.cancelled {
  border-left: 3px solid var(--muted);
}
.mc-job-top {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.mc-job-title-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
}
.mc-job-title {
  font-weight: 600;
  color: var(--text);
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mc-job-engine {
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .4px;
  padding: 1px 5px;
  border-radius: 2px;
  background: rgba(var(--bo-rgb), .12);
  color: var(--bo-txt);
  flex-shrink: 0;
}
.mc-job-timer {
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.mc-job-meta {
  font-size: 11px;
  color: var(--muted);
  display: flex;
  gap: 10px;
  align-items: center;
}
.mc-job-meta code {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace);
  font-size: 10.5px;
  background: rgba(0, 0, 0, .2);
  padding: 1px 4px;
  border-radius: 2px;
}
.mc-job-cmd {
  font-size: 11px;
  padding: 4px 8px;
  background: rgba(0, 0, 0, .22);
  border-radius: 3px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mc-job-cmd code {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace);
  color: var(--bo-txt);
}
.mc-job-prog .job-prog {
  padding: 0;
  margin: 2px 0;
}
.mc-job-tail {
  font-size: 11px;
  line-height: 1.4;
  padding: 4px 8px;
  background: rgba(0, 0, 0, .24);
  border-radius: 3px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-left: 2px solid var(--bo-lt);
}
.mc-job-tail.dim {
  font-style: italic;
  opacity: .6;
  border-left-color: var(--line);
}
.mc-tail-lbl {
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--bo-txt);
  margin-right: 4px;
}
.mc-job-result {
  font-size: 11.5px;
  color: var(--muted);
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace);
  background: rgba(0, 0, 0, .18);
  padding: 4px 8px;
  border-radius: 3px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mc-job-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
}
.mc-job-action {
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 3px;
  cursor: pointer;
}

/* ---- Scheduled Jobs & Recurring Tasks (2026-09-22) ---- */
.sched-sec { margin-top: 14px; border-top: 1px solid var(--line, rgba(255, 255, 255, .08)); padding-top: 10px; }
.sched-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.sched-head-actions { display: flex; align-items: center; gap: 8px; }
.sched-add-btn { font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 999px; border: 1px solid var(--line, rgba(255, 255, 255, .15)); background: var(--panel-2, rgba(255, 255, 255, .06)); color: var(--text); cursor: pointer; transition: all .12s; }
.sched-add-btn:hover { background: var(--hover, rgba(255, 255, 255, .12)); border-color: var(--text); }
.sched-row.paused { opacity: .65; }
.sched-item.paused .auto-dot { opacity: .4; }
.sched-modal { width: 540px; max-width: 94vw; }
.sched-modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.sched-modal-head h3 { margin: 0; font-size: 16px; font-weight: 600; }
.sched-form { display: flex; flex-direction: column; gap: 14px; }
.sched-form-row { display: flex; gap: 12px; }
.sched-field { display: flex; flex-direction: column; gap: 6px; }
.sched-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--muted, rgba(255, 255, 255, .5)); }
.sched-input, .sched-select, .sched-textarea { width: 100%; box-sizing: border-box; background: var(--panel-2, rgba(255, 255, 255, .05)); border: 1px solid var(--line, rgba(255, 255, 255, .14)); border-radius: 6px; color: var(--text); padding: 8px 10px; font: inherit; font-size: 13px; outline: none; transition: border-color .15s; }
.sched-input:focus, .sched-select:focus, .sched-textarea:focus { border-color: var(--accent, #4d94ff); }
.sched-textarea { resize: vertical; line-height: 1.45; }
.sched-field-check { margin-top: 4px; }
.sched-check-label { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text); cursor: pointer; }
.sched-check-label input { cursor: pointer; width: auto; margin: 0; }
.sched-modal-foot { display: flex; align-items: center; justify-content: space-between; margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--line, rgba(255, 255, 255, .08)); }
.sched-foot-right { display: flex; gap: 8px; margin-left: auto; }
.sched-btn-cancel { padding: 7px 14px; border-radius: 999px; background: transparent; border: 1px solid var(--line, rgba(255, 255, 255, .15)); color: var(--text); font-size: 12.5px; cursor: pointer; }
.sched-btn-cancel:hover { background: var(--hover, rgba(255, 255, 255, .08)); }
.sched-btn-save { padding: 7px 18px; border-radius: 999px; background: var(--accent, #4d94ff); border: none; color: var(--on-accent, #fff); font-size: 12.5px; font-weight: 600; cursor: pointer; }
.sched-btn-del { padding: 7px 14px; border-radius: 999px; background: transparent; border: 1px solid rgba(229, 72, 77, .4); color: #e5484d; font-size: 12px; cursor: pointer; }
.sched-btn-del:hover { background: rgba(229, 72, 77, .12); border-color: #e5484d; }

/* ONE scrollbar everywhere (John, 2026-09-25): a 2px black line that only shows while
   that element is scrolling. renderer.js adds .is-scrolling to whatever element fires a
   scroll event and removes it shortly after it stops. !important because many panels
   carried their own widths and colours (8px beige thumbs, 3px dark ones). Elements that
   hide their scrollbar (display: none) stay hidden: only width and colour are set here.
   Note: Chromium ignores these pseudo-elements on any element with scrollbar-width or
   scrollbar-color set, so keep those properties off (auto) everywhere. */
::-webkit-scrollbar { width: 2px !important; height: 2px !important; background: transparent !important; }
::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent !important; }
::-webkit-scrollbar-thumb { background: transparent !important; border: 0 !important; border-radius: 0 !important; }
.is-scrolling::-webkit-scrollbar-thumb { background: #000 !important; }
/* Queue chip during a branch-out: "queued | left •" (John, 2026-09-25). */
.q-chip.q-queue .q-sep { width: 1px; height: 12px; background: var(--line); margin: 0 6px; flex: 0 0 auto; }
.q-chip.q-queue .q-bo-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--text); margin-left: 4px; flex: 0 0 auto; }
