/* ════════════════════════════════════════════════════════════════════
   Tacit Web - one token layer drives every surface and every theme.
   8 themes via [data-theme] on <html>. Colour, type, tracking, spacing,
   elevation and motion are all tokens; a theme may recolour and re-shade,
   and may never re-space, re-type or re-time.
   ════════════════════════════════════════════════════════════════════ */

:root {
  /* Theme-independent colours, and only these two. `--on-accent` is the foreground
     on `--accent`; a theme whose accent is light overrides it in its own block.
     `--shade` is what shadows and scrims are mixed from, so a warm theme casts a
     warm shadow instead of a black one. */
  --on-accent: #fff;
  --shade: #000;

  /* Type. The platform's own text face leads: nothing here is downloaded, so a
     stack naming a face this app does not ship is a promise it cannot keep.
     Optical sizing is on because Segoe UI Variable and SF Pro both carry a real
     optical axis, and small text is most of this interface. */
  --font: system-ui, -apple-system, "Segoe UI Variable Text", "Segoe UI",
          "Noto Sans", "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas,
          "DejaVu Sans Mono", monospace;

  --radius: 12px;
  --radius-sm: 8px;
  --sidebar-w: 264px;
  --content-w: 800px;

  /* ── scale: type, spacing, radius, tracking. :root only, no [data-theme]
     block redefines these, so a theme can never move the layout. ── */
  /* Type ladder: 9 steps, adjacent ratio 1.125, the band operate.md prescribes for
     an Operate surface (1.125-1.2). --fs-5 is exactly 1rem; 10px is the floor.
     Roles: 1 micro-badge, 2 dense UI, 3 UI default + code, 4 reading, 5 emphasis,
            6 heading small, 7 heading, 8 display, 9 hero number. */
  --fs-1: 10px;
  --fs-2: 11.25px;
  --fs-3: 12.65px;
  --fs-4: 14.25px;
  --fs-5: 16px;
  --fs-6: 18px;
  --fs-7: 20.3px;
  --fs-8: 22.8px;
  --fs-9: 25.7px;

  /* Spacing ladder: 12 steps on a 4-unit base, with the 2px middle steps an 8-only
     scale misses (layout.md). */
  --sp-1: 1px;
  --sp-2: 2px;
  --sp-3: 4px;
  --sp-4: 6px;
  --sp-5: 8px;
  --sp-6: 10px;
  --sp-7: 12px;
  --sp-8: 14px;
  --sp-9: 16px;
  --sp-10: 20px;
  --sp-11: 24px;
  --sp-12: 40px;

  /* Radius ladder: 6 steps. Corners are optical rather than spatial, so this is the
     one family allowed to skip the 4-unit grid at the small end. */
  --rd-1: 2px;
  --rd-2: 4px;
  --rd-3: 6px;
  --rd-4: 8px;
  --rd-5: 12px;
  --rd-6: 16px;

  /* Tracking ladder: 4 steps, in em and not px. It was 13 raw values mixing both.
     `.2px .3px .4px .5px .7px .8px 1.1px 1.4px .04em .05em .06em .07em 0` - which is
     a continuum dressed as a scale, the same defect the spacing ladder replaced.
     px tracking is wrong in principle as well as in variety: 1.4px is 0.14em at the
     10px it was set on, but 0.07em at 20px, so one declaration meant two things.
     The widest step here is 0.06em; the labels that used to carry 0.14em were the
     small-caps-tracked-micro-label look, and 0.06em says the same thing readable. */
  --tr-1: -0.015em;   /* display and large headings: tighten */
  --tr-2: 0em;        /* body and UI default */
  --tr-3: 0.02em;     /* small UI text, badges, metadata */
  --tr-4: 0.06em;     /* uppercase micro-labels */

  /* Motion: four durations and three curves. Exponential ease-out is the default
     because a decelerating element reads as arriving rather than departing, and
     every duration is inside operate.md's 150-250ms band for the states people
     wait on. Nothing here is decoration; the blanket at the end of the file
     switches all of it off under prefers-reduced-motion. */
  --dur-1: 90ms;      /* micro: hover, press */
  --dur-2: 150ms;     /* standard: colour, border, small transform */
  --dur-3: 220ms;     /* structural: cards, expansion, panels */
  --dur-4: 320ms;     /* large: overlays, sidebar */
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-soft: cubic-bezier(.33, 1, .68, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);

  /* Elevation: three levels, each an offset plus a soft blur, mixed from --shade so
     the shadow belongs to the theme's own ground. Two layers on the upper two,
     a tight contact shadow under a wide ambient one is what reads as height; a
     single wide blur reads as a glow, which is decoration. In-flow surfaces take a
     border and no shadow; only what floats above the page casts one. */
  --sh-1: 0 1px 2px color-mix(in srgb, var(--shade) 26%, transparent);
  --sh-2: 0 1px 2px color-mix(in srgb, var(--shade) 24%, transparent),
          0 6px 16px color-mix(in srgb, var(--shade) 22%, transparent);
  --sh-3: 0 2px 6px color-mix(in srgb, var(--shade) 26%, transparent),
          0 18px 50px color-mix(in srgb, var(--shade) 34%, transparent);

  /* Purpose aliases: the seam a density change is allowed to move. Named by role,
     not by step, because a step number says nothing about why a size exists. */
  --fs-read: var(--fs-4);
  --fs-uirow: var(--fs-3);
  --fs-meta: var(--fs-2);
  --sp-row: var(--sp-5);
  --sp-turn: var(--sp-5);
  --sp-gap: var(--sp-10);
  /* How much of a long, collapsible thing you get before it scrolls. The reasoning
     body and the tool-call block read this because they make the same promise: one
     turn cannot grow the transcript without limit. */
  --peek-h: 300px;
  --radius-pill: 999px;
}

/* ── theme: graphite (default dark), warm graphite ground, petrol accent ── */
:root, [data-theme="graphite"] {
  color-scheme: dark;
  --bg: #1a1712;
  --bg-2: #231f19;
  --bg-3: #2b2720;
  --bg-hover: #37312a;
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .19);
  --text: #eae7e3;
  --muted: #a69f94;
  --fadetext: #7a7266;
  --accent: #619abc;
  --accent-rgb: 97, 154, 188;
  --on-accent: #000;
  --accent-2: #6dc3bc;
  --accent2-rgb: 109, 195, 188;
  --user-bubble: #312c25;
  --user-bubble-text: #ccc6bf;
  --err: #c9605a;
  --err-rgb: 201, 96, 90;
  --warn: #caa357;
  --warn-rgb: 202, 163, 87;
  --ok: #6fa56c;
  --code-bg: #120f0b;
  --code-text: #dcd8d3;
  --scroll: #413b33;
  --scroll-hover: #575249;
  --select-arrow: rgba(166, 159, 148, .9);
  --shade: #12100c;
  --dim: rgba(18, 16, 12, .62);
}

/* ── theme: vellum (light), warm paper, printer's ink, ultramarine ── */
[data-theme="verdigris"] {
  color-scheme: dark;
  --bg: #111918;
  --bg-2: #182120;
  --bg-3: #202a29;
  --bg-hover: #293534;
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .19);
  --text: #e3e9e8;
  --muted: #93a4a2;
  --fadetext: #667775;
  --accent: #c88c5f;
  --accent-rgb: 200, 140, 95;
  --on-accent: #000;
  --accent-2: #79acd0;
  --accent2-rgb: 121, 172, 208;
  --user-bubble: #242f2e;
  --user-bubble-text: #bfcac8;
  --err: #cf5a6a;
  --err-rgb: 207, 90, 106;
  --warn: #bdb86f;
  --warn-rgb: 189, 184, 111;
  --ok: #77aa78;
  --code-bg: #0b1111;
  --code-text: #d3dbda;
  --scroll: #323f3d;
  --scroll-hover: #485654;
  --select-arrow: rgba(147, 164, 162, .9);
  --shade: #0b1111;
  --dim: rgba(11, 17, 17, .62);
}

/* ── theme: verdigris (cool dark), grey-green ground, copper accent ── */
[data-theme="mono"] {
  color-scheme: dark;
  --bg: #171717;
  --bg-2: #1f1f1f;
  --bg-3: #282828;
  --bg-hover: #323232;
  --line: rgba(255, 255, 255, .11);
  --line-2: rgba(255, 255, 255, .22);
  --text: #e8e8e8;
  --muted: #a0a0a0;
  --fadetext: #737373;
  --accent: #e6e6e6;
  --accent-rgb: 230, 230, 230;
  --on-accent: #000;
  --accent-2: #b1b1b1;
  --accent2-rgb: 177, 177, 177;
  --user-bubble: #2c2c2c;
  --user-bubble-text: #c7c7c7;
  --err: #d8625c;
  --err-rgb: 216, 98, 92;
  --warn: #cfaa58;
  --warn-rgb: 207, 170, 88;
  --ok: #75ab72;
  --code-bg: #101010;
  --code-text: #d9d9d9;
  --scroll: #3c3c3c;
  --scroll-hover: #525252;
  --select-arrow: rgba(160, 160, 160, .9);
  --shade: #101010;
  --dim: rgba(16, 16, 16, .62);
}

/* ── theme: oxide (dark), iron ground, chalk accent; semantics own every hue ── */
[data-theme="amethyst"] {
  color-scheme: dark;
  --bg: #19161c;
  --bg-2: #211d25;
  --bg-3: #29262f;
  --bg-hover: #34303a;
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .19);
  --text: #e9e7ec;
  --muted: #a39dac;
  --fadetext: #76707f;
  --accent: #a08eca;
  --accent-rgb: 160, 142, 202;
  --on-accent: #000;
  --accent-2: #7db8bf;
  --accent2-rgb: 125, 184, 191;
  --user-bubble: #2f2a34;
  --user-bubble-text: #c9c5cf;
  --err: #cb5e58;
  --err-rgb: 203, 94, 88;
  --warn: #cca459;
  --warn-rgb: 204, 164, 89;
  --ok: #6fa56c;
  --code-bg: #110f14;
  --code-text: #dbd7df;
  --scroll: #3e3944;
  --scroll-hover: #55505c;
  --select-arrow: rgba(163, 157, 172, .9);
  --shade: #100c14;
  --dim: rgba(16, 12, 20, .62);
}

/* ── theme: signal (light), chart series: colour encodes, never decorates ── */
[data-theme="nocturne"] {
  color-scheme: dark;
  --bg: #14171d;
  --bg-2: #1c1f26;
  --bg-3: #24282f;
  --bg-hover: #2e323b;
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .19);
  --text: #e5e8ed;
  --muted: #9aa0ad;
  --fadetext: #6d7381;
  --accent: #c0b26c;
  --accent-rgb: 192, 178, 108;
  --on-accent: #000;
  --accent-2: #79afbd;
  --accent2-rgb: 121, 175, 189;
  --user-bubble: #292d35;
  --user-bubble-text: #c3c7d0;
  --err: #d05e74;
  --err-rgb: 208, 94, 116;
  --warn: #d47a25;
  --warn-rgb: 212, 122, 37;
  --ok: #6ca56e;
  --code-bg: #0e1015;
  --code-text: #d6d9e0;
  --scroll: #373c46;
  --scroll-hover: #4e535d;
  --select-arrow: rgba(154, 160, 173, .9);
  --shade: #0e0c14;
  --dim: rgba(14, 12, 20, .62);
}

/* ── theme: mono, neutral greyscale; status stays saturated ── */
[data-theme="lagoon"] {
  color-scheme: dark;
  --bg: #11191a;
  --bg-2: #182123;
  --bg-3: #1f2a2c;
  --bg-hover: #283537;
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .19);
  --text: #e3e9ea;
  --muted: #92a4a7;
  --fadetext: #64777b;
  --accent: #52afb4;
  --accent-rgb: 82, 175, 180;
  --on-accent: #000;
  --accent-2: #96a6d5;
  --accent2-rgb: 150, 166, 213;
  --user-bubble: #232f31;
  --user-bubble-text: #becacc;
  --err: #d0615c;
  --err-rgb: 208, 97, 92;
  --warn: #cea359;
  --warn-rgb: 206, 163, 89;
  --ok: #80a35c;
  --code-bg: #0a1113;
  --code-text: #d2dbdd;
  --scroll: #313e41;
  --scroll-hover: #485558;
  --select-arrow: rgba(146, 164, 167, .9);
  --shade: #0a1216;
  --dim: rgba(10, 18, 22, .62);
}

/* ── theme: amethyst (dark), plum ground, iris accent; a stone, not a lamp ── */
[data-theme="rosewood"] {
  color-scheme: dark;
  --bg: #1c1518;
  --bg-2: #251c20;
  --bg-3: #2e2429;
  --bg-hover: #3a2f34;
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .19);
  --text: #ece6e9;
  --muted: #ab9ba2;
  --fadetext: #7f6d76;
  --accent: #c790a4;
  --accent-rgb: 199, 144, 164;
  --on-accent: #000;
  --accent-2: #7ab6b7;
  --accent2-rgb: 122, 182, 183;
  --user-bubble: #34292e;
  --user-bubble-text: #cfc4c9;
  --err: #d35d5d;
  --err-rgb: 211, 93, 93;
  --warn: #d0a35b;
  --warn-rgb: 208, 163, 91;
  --ok: #75a564;
  --code-bg: #140e11;
  --code-text: #dfd6da;
  --scroll: #44383e;
  --scroll-hover: #5b4e54;
  --select-arrow: rgba(171, 155, 162, .9);
  --shade: #150e12;
  --dim: rgba(21, 14, 18, .62);
}

/* ── theme: celadon (light), jade-glaze ground, deep celadon accent ── */
[data-theme="absinthe"] {
  color-scheme: dark;
  --bg: #121915;
  --bg-2: #1a211d;
  --bg-3: #212a25;
  --bg-hover: #2b352f;
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .19);
  --text: #e4e9e6;
  --muted: #96a49c;
  --fadetext: #68776e;
  --accent: #9fba6f;
  --accent-rgb: 159, 186, 111;
  --on-accent: #000;
  --accent-2: #8aabcd;
  --accent2-rgb: 138, 171, 205;
  --user-bubble: #262f2a;
  --user-bubble-text: #c0cac4;
  --err: #d0615c;
  --err-rgb: 208, 97, 92;
  --warn: #de9148;
  --warn-rgb: 222, 145, 72;
  --ok: #59a88e;
  --code-bg: #0c110e;
  --code-text: #d4dbd7;
  --scroll: #343f39;
  --scroll-hover: #4a564f;
  --select-arrow: rgba(150, 164, 156, .9);
  --shade: #0c120e;
  --dim: rgba(12, 18, 14, .62);
}

/* ── theme: contrast (AAA dark), an accessibility instrument, not a taste ── */
[data-theme="iris"] {
  color-scheme: dark;
  --bg: #14181b;
  --bg-2: #1c2024;
  --bg-3: #24282d;
  --bg-hover: #2e3338;
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .19);
  --text: #e6e8eb;
  --muted: #9aa1a8;
  --fadetext: #6d747c;
  --accent: #8190d2;
  --accent-rgb: 129, 144, 210;
  --on-accent: #000;
  --accent-2: #7ab5bc;
  --accent2-rgb: 122, 181, 188;
  --user-bubble: #292d32;
  --user-bubble-text: #c3c8cd;
  --err: #d0615c;
  --err-rgb: 208, 97, 92;
  --warn: #cea359;
  --warn-rgb: 206, 163, 89;
  --ok: #72a467;
  --code-bg: #0e1013;
  --code-text: #d6d9dd;
  --scroll: #373c42;
  --scroll-hover: #4e5359;
  --select-arrow: rgba(154, 161, 168, .9);
  --shade: #0d0e13;
  --dim: rgba(13, 14, 19, .62);
}

/* ── theme: contrast-light (AAA light), the other half of the pair ── */
[data-theme="slate"] {
  color-scheme: dark;
  --bg: #3d4246;
  --bg-2: #373c40;
  --bg-3: #32373b;
  --bg-hover: #2c3135;
  --line: rgba(255, 255, 255, .13);
  --line-2: rgba(255, 255, 255, .24);
  --text: #f8f9fa;
  --muted: #dbdee1;
  --fadetext: #bcc1c5;
  --accent: #9ae1ff;
  --accent-rgb: 154, 225, 255;
  --on-accent: #000;
  --accent-2: #f4c9fe;
  --accent2-rgb: 244, 201, 254;
  --user-bubble: #353a3e;
  --user-bubble-text: #f6f7f8;
  --err: #ffadae;
  --err-rgb: 255, 173, 174;
  --warn: #ffcf84;
  --warn-rgb: 255, 207, 132;
  --ok: #a9e9b1;
  --code-bg: #25292d;
  --code-text: #f5f6f7;
  --scroll: #565c60;
  --scroll-hover: #6d7277;
  --select-arrow: rgba(219, 222, 225, .9);
  --shade: #15171a;
  --dim: rgba(21, 23, 26, .62);
}

/* ── theme: nocturne (dark), indigo-slate ground, one brass lamp ── */
[data-theme="oxide"] {
  color-scheme: dark;
  --bg: #1e1511;
  --bg-2: #281c18;
  --bg-3: #31241f;
  --bg-hover: #3e2e29;
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .19);
  --text: #eee6e3;
  --muted: #b19a92;
  --fadetext: #846d64;
  --accent: #e6ded8;
  --accent-rgb: 230, 222, 216;
  --on-accent: #000;
  --accent-2: #72b5cf;
  --accent2-rgb: 114, 181, 207;
  --user-bubble: #372923;
  --user-bubble-text: #d3c4be;
  --err: #d15b58;
  --err-rgb: 209, 91, 88;
  --warn: #cda655;
  --warn-rgb: 205, 166, 85;
  --ok: #72a66c;
  --code-bg: #160e0a;
  --code-text: #e2d6d2;
  --scroll: #483831;
  --scroll-hover: #604e47;
  --select-arrow: rgba(177, 154, 146, .9);
  --shade: #150d09;
  --dim: rgba(21, 13, 9, .62);
}

/* ── theme: kinpaku-dark (dark), black lacquer ground, gold leaf, patina teal ── */
[data-theme="kinpaku-dark"] {
  color-scheme: dark;
  --bg: #100e0a;
  --bg-2: #17140f;
  --bg-3: #1f1b14;
  --bg-hover: #292319;
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .19);
  --text: #f0ead8;
  --muted: #a89d81;
  --fadetext: #7c7360;
  --accent: #d9b45c;
  --accent-rgb: 217, 180, 92;
  --on-accent: #000;
  --accent-2: #6fb3ad;
  --accent2-rgb: 111, 179, 173;
  --user-bubble: #221d14;
  --user-bubble-text: #cfc6ae;
  --err: #d0453a;
  --err-rgb: 208, 69, 58;
  --warn: #d47a25;
  --warn-rgb: 212, 122, 37;
  --ok: #6fae6a;
  --code-bg: #0a0907;
  --code-text: #ded6c2;
  --scroll: #38311f;
  --scroll-hover: #4c4330;
  --select-arrow: rgba(168, 157, 129, .9);
  --shade: #080705;
  --dim: rgba(8, 7, 5, .62);
}

/* ── theme: lagoon (dark), deep teal-slate ground, water cyan ── */
[data-theme="contrast"] {
  color-scheme: dark;
  --bg: #000000;
  --bg-2: #0a0a0a;
  --bg-3: #171717;
  --bg-hover: #242424;
  --line: rgba(255, 255, 255, .45);
  --line-2: rgba(255, 255, 255, .75);
  --text: #ffffff;
  --muted: #e8e8e8;
  --fadetext: #c4c4c4;
  --accent: #ffd60a;
  --accent-rgb: 255, 214, 10;
  --on-accent: #000;
  --accent-2: #4ad9ff;
  --accent2-rgb: 74, 217, 255;
  --user-bubble: #141414;
  --user-bubble-text: #ffffff;
  --err: #ff5c5c;
  --err-rgb: 255, 92, 92;
  --warn: #ff9500;
  --warn-rgb: 255, 149, 0;
  --ok: #3ef07a;
  --code-bg: #000000;
  --code-text: #ffffff;
  --scroll: #3a3a3a;
  --scroll-hover: #5c5c5c;
  --select-arrow: rgba(232, 232, 232, .9);
  --shade: #000;
  --dim: rgba(0, 0, 0, .62);
}

/* ── theme: rosewood (dark), plum-rose ground, dusty mauve ── */
[data-theme="vellum"] {
  color-scheme: light;
  --bg: #f1f0ed;
  --bg-2: #fbfaf9;
  --bg-3: #e9e8e3;
  --bg-hover: #dedcd6;
  --line: rgba(26, 23, 16, .11);
  --line-2: rgba(26, 23, 16, .20);
  --text: #221e14;
  --muted: #615a4b;
  --fadetext: #888171;
  --accent: #3e58ab;
  --accent-rgb: 62, 88, 171;
  --on-accent: #fff;
  --accent-2: #006776;
  --accent2-rgb: 0, 103, 118;
  --user-bubble: #e5e3de;
  --user-bubble-text: #3b3527;
  --err: #b12725;
  --err-rgb: 177, 39, 37;
  --warn: #864f00;
  --warn-rgb: 134, 79, 0;
  --ok: #346729;
  --code-bg: #e5e3de;
  --code-text: #272218;
  --scroll: #bebab1;
  --scroll-hover: #a09b8f;
  --select-arrow: rgba(97, 90, 75, .9);
  --shade: #1a1710;
  --dim: rgba(26, 23, 16, .38);
}

/* ── theme: absinthe (dark), green-slate ground, chartreuse ── */
[data-theme="signal"] {
  color-scheme: light;
  --bg: #eef0f2;
  --bg-2: #f9fafb;
  --bg-3: #e5e8ea;
  --bg-hover: #d9dde0;
  --line: rgba(20, 26, 30, .11);
  --line-2: rgba(20, 26, 30, .20);
  --text: #181f24;
  --muted: #525d63;
  --fadetext: #78848b;
  --accent: #046382;
  --accent-rgb: 4, 99, 130;
  --on-accent: #fff;
  --accent-2: #68476f;
  --accent2-rgb: 104, 71, 111;
  --user-bubble: #e0e3e6;
  --user-bubble-text: #2d373d;
  --err: #b01f1c;
  --err-rgb: 176, 31, 28;
  --warn: #804e00;
  --warn-rgb: 128, 78, 0;
  --ok: #356630;
  --code-bg: #e0e3e6;
  --code-text: #1c2429;
  --scroll: #b5bcc0;
  --scroll-hover: #949da2;
  --select-arrow: rgba(82, 93, 99, .9);
  --shade: #141a1e;
  --dim: rgba(20, 26, 30, .38);
}

/* ── theme: iris (dark), cool neutral ground, deep violet-blue ── */
[data-theme="celadon"] {
  color-scheme: light;
  --bg: #eef1f0;
  --bg-2: #f9fafa;
  --bg-3: #e5e9e8;
  --bg-hover: #d8dedc;
  --line: rgba(16, 26, 26, .11);
  --line-2: rgba(16, 26, 26, .20);
  --text: #16211e;
  --muted: #4f5f5b;
  --fadetext: #768682;
  --accent: #126b74;
  --accent-rgb: 18, 107, 116;
  --on-accent: #fff;
  --accent-2: #5c5382;
  --accent2-rgb: 92, 83, 130;
  --user-bubble: #dfe4e3;
  --user-bubble-text: #2b3935;
  --err: #b12725;
  --err-rgb: 177, 39, 37;
  --warn: #864f00;
  --warn-rgb: 134, 79, 0;
  --ok: #386626;
  --code-bg: #dfe4e3;
  --code-text: #1b2523;
  --scroll: #b3bdba;
  --scroll-hover: #929f9b;
  --select-arrow: rgba(79, 95, 91, .9);
  --shade: #101a1a;
  --dim: rgba(16, 26, 26, .38);
}

/* ── theme: slate (MID-TONE), cool grey at L*0.45, amber indicator ── */
[data-theme="frost"] {
  color-scheme: light;
  --bg: #eef0f1;
  --bg-2: #f9fafb;
  --bg-3: #e5e8ea;
  --bg-hover: #d9dddf;
  --line: rgba(17, 22, 28, .11);
  --line-2: rgba(17, 22, 28, .20);
  --text: #191f22;
  --muted: #535d62;
  --fadetext: #798489;
  --accent: #006b71;
  --accent-rgb: 0, 107, 113;
  --on-accent: #fff;
  --accent-2: #5b5184;
  --accent2-rgb: 91, 81, 132;
  --user-bubble: #e0e3e5;
  --user-bubble-text: #2e373c;
  --err: #b22423;
  --err-rgb: 178, 36, 35;
  --warn: #854e00;
  --warn-rgb: 133, 78, 0;
  --ok: #3c6521;
  --code-bg: #e0e3e5;
  --code-text: #1d2428;
  --scroll: #b5bcbf;
  --scroll-hover: #959da1;
  --select-arrow: rgba(83, 93, 98, .9);
  --shade: #11161c;
  --dim: rgba(17, 22, 28, .38);
}

/* ── theme: frost (light), blue-white ground, deep cyan ── */
[data-theme="monotype"] {
  color-scheme: light;
  --bg: #f0f0f0;
  --bg-2: #fafafa;
  --bg-3: #e8e8e8;
  --bg-hover: #dcdcdc;
  --line: rgba(0, 0, 0, .12);
  --line-2: rgba(0, 0, 0, .22);
  --text: #1e1e1e;
  --muted: #5b5b5b;
  --fadetext: #828282;
  --accent: #202020;
  --accent-rgb: 32, 32, 32;
  --on-accent: #fff;
  --accent-2: #505050;
  --accent2-rgb: 80, 80, 80;
  --user-bubble: #e3e3e3;
  --user-bubble-text: #353535;
  --err: #b22423;
  --err-rgb: 178, 36, 35;
  --warn: #824e00;
  --warn-rgb: 130, 78, 0;
  --ok: #30662b;
  --code-bg: #e3e3e3;
  --code-text: #232323;
  --scroll: #bababa;
  --scroll-hover: #9b9b9b;
  --select-arrow: rgba(91, 91, 91, .9);
  --shade: #000000;
  --dim: rgba(0, 0, 0, .38);
}

/* ── theme: monotype (light), neutral ground, the accent is ink ── */
[data-theme="foxglove"] {
  color-scheme: light;
  --bg: #f1f0ed;
  --bg-2: #fbfaf9;
  --bg-3: #e9e8e4;
  --bg-hover: #dfdcd7;
  --line: rgba(26, 22, 16, .11);
  --line-2: rgba(26, 22, 16, .20);
  --text: #221e15;
  --muted: #615a4d;
  --fadetext: #888173;
  --accent: #6c4d87;
  --accent-rgb: 108, 77, 135;
  --on-accent: #fff;
  --accent-2: #006770;
  --accent2-rgb: 0, 103, 112;
  --user-bubble: #e5e3de;
  --user-bubble-text: #3b3529;
  --err: #b22624;
  --err-rgb: 178, 38, 36;
  --warn: #864e00;
  --warn-rgb: 134, 78, 0;
  --ok: #346628;
  --code-bg: #e5e3de;
  --code-text: #272219;
  --scroll: #bebab2;
  --scroll-hover: #a09b90;
  --select-arrow: rgba(97, 90, 77, .9);
  --shade: #1a1610;
  --dim: rgba(26, 22, 16, .38);
}

/* ── theme: foxglove (light), warm neutral ground, muted plum ── */
[data-theme="sorrel"] {
  color-scheme: light;
  --bg: #f1f0ed;
  --bg-2: #fafaf9;
  --bg-3: #e9e8e3;
  --bg-hover: #dedcd6;
  --line: rgba(25, 23, 16, .11);
  --line-2: rgba(25, 23, 16, .20);
  --text: #211e14;
  --muted: #5f5b4b;
  --fadetext: #868271;
  --accent: #3d5c95;
  --accent-rgb: 61, 92, 149;
  --on-accent: #fff;
  --accent-2: #00686d;
  --accent2-rgb: 0, 104, 109;
  --user-bubble: #e4e3de;
  --user-bubble-text: #393527;
  --err: #b22624;
  --err-rgb: 178, 38, 36;
  --warn: #864e00;
  --warn-rgb: 134, 78, 0;
  --ok: #40631b;
  --code-bg: #e4e3de;
  --code-text: #262318;
  --scroll: #bdbbb1;
  --scroll-hover: #9f9c8f;
  --select-arrow: rgba(95, 91, 75, .9);
  --shade: #191710;
  --dim: rgba(25, 23, 16, .38);
}

/* ── theme: kinpaku (light), gold-leaf paper ground, patina teal ── */
[data-theme="kinpaku"] {
  color-scheme: light;
  --bg: #f6f2e7;
  --bg-2: #fdfbf4;
  --bg-3: #ede7d7;
  --bg-hover: #e2dac4;
  --line: rgba(33, 26, 8, .11);
  --line-2: rgba(33, 26, 8, .20);
  --text: #1f1a10;
  --muted: #5c5341;
  --fadetext: #837a63;
  --accent: #7a5c12;
  --accent-rgb: 122, 92, 18;
  --on-accent: #fff;
  --accent-2: #14676b;
  --accent2-rgb: 20, 103, 107;
  --user-bubble: #e8e0cc;
  --user-bubble-text: #3a3220;
  --err: #b22624;
  --err-rgb: 178, 38, 36;
  --warn: #9c4a00;
  --warn-rgb: 156, 74, 0;
  --ok: #3f6a3a;
  --code-bg: #ece5d3;
  --code-text: #241d0e;
  --scroll: #cfc6ad;
  --scroll-hover: #b3a883;
  --select-arrow: rgba(92, 83, 65, .9);
  --shade: #211a08;
  --dim: rgba(33, 26, 8, .38);
}

/* ── theme: sorrel (light), pale clay ground, deep olive-bronze ── */
[data-theme="contrast-light"] {
  color-scheme: light;
  --bg: #ffffff;
  --bg-2: #f4f4f4;
  --bg-3: #e6e6e6;
  --bg-hover: #d9d9d9;
  --line: rgba(0, 0, 0, .55);
  --line-2: rgba(0, 0, 0, .85);
  --text: #000000;
  --muted: #1f1f1f;
  --fadetext: #3d3d3d;
  --accent: #0033cc;
  --accent-rgb: 0, 51, 204;
  --on-accent: #fff;
  --accent-2: #004d40;
  --accent2-rgb: 0, 77, 64;
  --user-bubble: #ededed;
  --user-bubble-text: #000000;
  --err: #b30000;
  --err-rgb: 179, 0, 0;
  --warn: #8a5000;
  --warn-rgb: 138, 80, 0;
  --ok: #006b2e;
  --code-bg: #dcdcdc;
  --code-text: #000000;
  --scroll: #8a8a8a;
  --scroll-hover: #5c5c5c;
  --select-arrow: rgba(31, 31, 31, .9);
  --shade: #000;
  --dim: rgba(0, 0, 0, .38);
}

/* ── reset / base ─────────────────────────────────────────────── */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
[hidden] {
  display: none !important;
}
html, body {
  height: 100%;
}
body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  /* Segoe UI Variable and SF Pro both carry a real optical axis, and most
     of this interface is small type -- which is exactly what it is for. */
  font-optical-sizing: auto;
}
button {
  font-family: inherit;
  cursor: pointer;
}
button:focus-visible, select:focus-visible, input:focus-visible, textarea:focus-visible,
a:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  /* The ring is drawn from the palette, not left to the browser: a focus
     indicator is part of the design, and the default is the one thing on this
     page that belongs to no theme. */
  transition: outline-offset var(--dur-2) var(--ease-out);
}
svg {
  display: block;
}
::selection {
  background: var(--accent);
  color: var(--on-accent);
}

.app {
  display: flex;
  height: 100vh;
}

/* Text fields get a caret you can see. The composer is where an operator spends most of
   the session; a theme-neutral caret on a tinted ground reads as "not focused" when it is. */
input, textarea {
  caret-color: var(--accent);
}

/* ── density ─────────────────────────────────────────────────────────────
   Three settings, not a slider: the ladder is discrete and a continuous multiplier
   would re-create the 1px continuum this revamp just removed. Only the purpose
   aliases move, so the type and spacing ladders stay theme-independent and the
   transcript's rhythm is the thing that changes. */
[data-density="compact"] {
  --fs-read: var(--fs-3);
  --fs-uirow: var(--fs-2);
  --fs-meta: var(--fs-1);
  --sp-row: var(--sp-3);
  --sp-turn: var(--sp-3);
  --sp-gap: var(--sp-7);
}
[data-density="roomy"] {
  --fs-read: var(--fs-5);
  --fs-uirow: var(--fs-4);
  --fs-meta: var(--fs-2);
  --sp-row: var(--sp-6);
  --sp-turn: var(--sp-6);
  --sp-gap: var(--sp-11);
}

/* scrollbars */
::-webkit-scrollbar {
  width: 9px;
  height: 9px;
}
::-webkit-scrollbar-thumb {
  background: var(--scroll);
  border-radius: var(--rd-3);
  border: 2px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover {
  background: var(--scroll-hover);
}
::-webkit-scrollbar-track {
  background: transparent;
}

/* ════════════════════ SIDEBAR ════════════════════ */
.sidebar {
  width: var(--sidebar-w);
  min-width: var(--sidebar-w);
  background: var(--bg-2);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
}
.sidebar.hidden {
  margin-left: calc(var(--sidebar-w) * -1);
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  padding: var(--sp-10) var(--sp-10) var(--sp-8);
}
.brand-icon {
  width: 22px;
  height: 22px;
  padding: var(--sp-4);
  box-sizing: content-box;
  fill: var(--accent);
  border-radius: var(--radius-sm);
  background: none;
  border: 0;
}
.brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}
.brand-name {
  font-weight: 700;
  font-size: var(--fs-5);
  letter-spacing: var(--tr-1);
}
.brand-sub {
  font-size: var(--fs-2);
  color: var(--muted);
  letter-spacing: var(--tr-3);
}

.new-chat-btn {
  margin: var(--sp-2) var(--sp-8) var(--sp-8);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-5);
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  border-radius: var(--rd-4);
  padding: var(--sp-6);
  font-size: var(--fs-4);
  font-weight: 600;
}
.new-chat-btn:hover {
  background: color-mix(in srgb, var(--accent) 84%, var(--text));
}
.new-chat-btn svg {
  width: 15px;
  height: 15px;
}

.section-label {
  font-size: var(--fs-2);
  text-transform: uppercase;
  letter-spacing: var(--tr-4);
  color: var(--muted);
  padding: var(--sp-6) var(--sp-10) var(--sp-4);
  font-weight: 600;
}

.session-list {
  flex: 1;
  overflow-y: auto;
  padding: 0 var(--sp-6);
}
.session-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-5) var(--sp-6);
  border-radius: var(--radius-sm);
  margin-bottom: var(--sp-1);
  font-size: var(--fs-3);
  color: var(--muted);
  cursor: pointer;
  border: 1px solid transparent;
  white-space: nowrap;
  overflow: hidden;
}
.session-item:hover {
  background: var(--bg-3);
  color: var(--text);
}
.session-item.active {
  background: color-mix(in srgb, var(--accent) 16%, var(--bg-2));
  color: var(--text);
  border-color: rgba(var(--accent-rgb), .35);
}
.session-item .s-icon {
  width: 13px;
  height: 13px;
  flex: none;
  opacity: .7;
}
.session-item.active .s-icon {
  opacity: 1;
  color: var(--accent);
}
.session-item .s-title {
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
}
.session-item .s-del {
  display: none;
  border: 0;
  background: none;
  color: var(--muted);
  padding: var(--sp-2);
}
.session-item:hover .s-del {
  display: block;
}
.session-item .s-del:hover {
  color: var(--err);
}
.session-item .s-del svg {
  width: 12px;
  height: 12px;
}

/* ── left-bar activity indicators (plan item 2) ─────────────────────── */
/* One dot per session row: grey idle, pulsing accent while a turn runs. */
.session-item .s-dot {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: var(--muted);
  opacity: .35;
}
.session-item.working .s-dot {
  background: var(--accent);
  opacity: 1;
  animation: s-dot-pulse 1.4s ease-in-out infinite;
}
.session-item.working {
  color: var(--text);
}
@keyframes s-dot-pulse {
  0%, 100% {
  opacity: 1;
  transform: scale(1);
}
  50% {
  opacity: .45;
  transform: scale(.82);
}
}
/* Per-row stop control, shown only while that session has a turn running. */
.session-item .s-stop {
  display: none;
  border: 0;
  background: none;
  color: var(--err);
  padding: var(--sp-2);
  cursor: pointer;
}
.session-item.working .s-stop {
  display: block;
}
.session-item .s-stop:hover {
  color: var(--text);
}
.session-item .s-stop svg {
  width: 12px;
  height: 12px;
}
/* The pulse above is switched off by the blanket `prefers-reduced-motion` rule at
   the bottom of this file - one rule for every animation, not one per selector. */

/* inline session rename input (sidebar + topbar) */
.rename-input {
  width: 100%;
  min-width: 0;
  font: inherit;
  color: var(--text);
  background: var(--bg-3);
  border: 1px solid var(--accent);
  border-radius: var(--rd-3);
  padding: var(--sp-2) var(--sp-4);
}
.top-title .rename-input {
  max-width: 340px;
  font-weight: 600;
}
.top-title {
  cursor: text;
}

/* segmented control */
.seg {
  display: flex;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--rd-4);
  padding: var(--sp-3);
  margin-bottom: var(--sp-3);
}
.seg button {
  flex: 1;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: var(--fs-3);
  font-weight: 600;
  padding: var(--sp-5);
  border-radius: var(--rd-3);
}
.seg button.active {
  background: var(--accent);
  color: var(--on-accent);
}

/* ── One card language (the deleted plan, item 5) ──────────────────────────────────────
   Panels used to each re-declare their whole chrome: 8 cards, 5 padding pairs,
   3 radius dialects, 4 head class names. The shell is the single declaration
   site; a panel rule now carries only what is genuinely its own, and every
   remaining difference is a named exception. tests/test_panel_cards.py pins
   the exception set, so a ninth card cannot drift back into re-declaring chrome. */
.card {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--rd-5);
}
.card-head {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
}
.card-actions {
  display: flex;
  gap: var(--sp-4);
}

/* compact control card, provider / model / thinking in one tile */
.ctl-card {
  margin: var(--sp-5) var(--sp-7) var(--sp-7);
  padding: var(--sp-3);
  display: flex;
  flex-direction: column;
}
.ctl-row {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-3) var(--sp-5);
}
.ctl-row + .ctl-row {
  border-top: 1px solid var(--line);
}
.ctl-label {
  font-size: var(--fs-2);
  text-transform: uppercase;
  letter-spacing: var(--tr-4);
  color: var(--muted);
  font-weight: 600;
  min-width: 56px;
  flex: none;
}
.ctl-select {
  flex: 1;
  min-width: 0;
  appearance: none;
  -webkit-appearance: none;
  background-color: transparent;
  color: var(--text);
  border: 1px solid transparent;
  border-radius: var(--rd-3);
  padding: var(--sp-4) var(--sp-10) var(--sp-4) var(--sp-5);
  font-size: var(--fs-3);
  font-family: inherit;
  cursor: pointer;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--select-arrow) 50%),
    linear-gradient(135deg, var(--select-arrow) 50%, transparent 50%);
  background-position: calc(100% - 11px) 55%, calc(100% - 6px) 55%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
}
.ctl-select:hover {
  background-color: var(--bg-hover);
  border-color: var(--line-2);
}
.ctl-select:focus {
  background-color: var(--bg-2);
  border-color: var(--accent);
}

/* ════════════════════ MAIN / TOPBAR ════════════════════ */
.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  /* Measured floor for the top bar: eight 32px controls, the gaps between them, the
     workspace glyph and the context bar, with the model line and the running total
     already shed. A 400px floor was the first guess and it was 90px short, which is the
     difference between the controls sitting inside the bar and landing on the panel
     beside it. Below this width the panels are what gives, not the controls. */
  min-width: 540px;
  position: relative;
  /* A query container, so the top bar can shed content by the width it actually has.
     See the @container rules after the top bar rules below. */
  container-type: inline-size;
  container-name: main;
}

.topbar {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-6) var(--sp-9);
  border-bottom: 1px solid var(--line);
  background: var(--bg-2);
}
.top-title {
  /* The slack in the top bar belongs here. The session name is the one line with an
     ellipsis already, so when the meta line grows, or the Assistant panel opens and
     takes 330px, this shrinks and the controls to the right never move. */
  flex: 1 1 auto;
  min-width: 0;
  text-wrap: balance;
  font-size: var(--fs-4);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.top-meta {
  /* This line changes text whenever the session changes model, endpoint or
     quantization. It used to sit at the right end of the free space with
     `margin-left: auto`, so every time its text grew, the workspace chip, the token
     meter and the six icon buttons slid right behind it: 60px in one step, measured.
     It takes its own width and no slack, and the session title beside it is what gives
     instead, because that one already has an ellipsis. Making the META the flexible one
     was the first attempt and it is wrong: with the Assistant panel open at 1280 the row
     is full, so the meta collapsed to zero and the model line disappeared. `0 1 auto` is
     the other order: it keeps its own width whenever there is room and truncates with an
     ellipsis when there is not, which is what the row needs, because the alternative is
     the eight controls on its right spilling over the panel beside them. Measured at
     1920x1080 with both panels open, refusing to shrink put the last icon 42px outside
     the bar. */
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: var(--fs-2);
  color: var(--muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* The top bar sheds content by viewport width further down this file, which is the
   wrong measure twice over. The main column narrows when the Assistant panel and the
   delegation panel open beside it, and no viewport query knows: at 1280 with both open
   the column was 216px while the bar needs about 690 to show everything it holds, so
   the eight controls on its right spilled over the panel next to them. These key off
   the column, in the order a reader would give up: the model line, then the running
   token total, then the workspace name, then the context bar itself. The controls are
   last, and they are the point. */
@container main (max-width: 760px) {
  .top-meta {
    display: none;
  }
}
@container main (max-width: 660px) {
  .tok-meter .tok-count {
    display: none;
  }
}
@container main (max-width: 640px) {
  #wdLabel {
    display: none;
  }
}
.icon-btn {
  width: 32px;
  height: 32px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--rd-4);
  color: var(--muted);
}
.icon-btn:hover {
  background: var(--bg-3);
  color: var(--text);
  border-color: var(--line);
}
.icon-btn svg {
  width: 18px;
  height: 18px;
}

/* per-session tool-set chip */
.toolset-chip {
  flex: none;
  font-size: var(--fs-2);
  font-weight: 600;
  font-family: var(--mono);
  color: var(--warn);
  background: transparent;
  border: 1px solid var(--warn);
  border-radius: var(--radius-pill);
  padding: var(--sp-2) var(--sp-6);
}
.toolset-chip:hover {
  background: rgba(var(--warn-rgb), .12);
}

/* token meter, cumulative tokens + live context-fill bar (topbar) */
.tok-meter {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  font-size: var(--fs-2);
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  padding: var(--sp-3) var(--sp-6);
  background: var(--bg);
}
.tok-count {
  color: var(--text);
  font-weight: 600;
  /* "71k tok" is 46px and "90.2k tok" is 59px, and the meter is what the icon buttons
     are measured from, so an unreserved count made the whole right cluster pulse 13px
     every time the total crossed a round number. 10ch is the widest string `fmtTok`
     can produce ("999.9k tok"), the figures are tabular already, and right-aligning
     keeps the growing number against the bar instead of drifting in its own box. */
  min-width: 10ch;
  text-align: right;
}
.tok-ctx {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
}
.tok-bar {
  width: 44px;
  height: 5px;
  border-radius: var(--rd-2);
  background: var(--bg-3);
  overflow: hidden;
}
.tok-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--accent-2);
  border-radius: var(--rd-2);
  transition: width .4s ease, background .3s ease;
}
.tok-fill.warn {
  background: var(--warn);
}
.tok-fill.alert {
  background: var(--err);
}
.tok-fill.auto-zone {
  background: var(--ok);
}
.tok-meter.compacting .tok-fill { animation: tokPulse 1s ease-in-out infinite; width: 100%; }
/* A hand compaction runs with no turn in flight, so the composer needs its own
   quiet state rather than the busy one: the input is shut while the record is
   folded, and the meter above it pulses instead of filling. */
body.compacting #input,
body.compacting #sendBtn { opacity: .55; cursor: progress; }
@keyframes tokPulse { 50% {
  opacity: .3;
} }
.tok-pct {
  min-width: 3ch;
}
.tok-auto {
  font-size: var(--fs-1);
  font-weight: 700;
  letter-spacing: var(--tr-3);
  text-transform: uppercase;
  color: var(--ok);
  border: 1px solid var(--ok);
  border-radius: var(--radius-pill);
  padding: 0 var(--sp-4);
  line-height: 1.6;
}

/* jump-to-latest button */
.jump-btn {
  position: absolute;
  right: 24px;
  bottom: 112px;
  z-index: 20;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  background: var(--bg-2);
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--sh-2);
}
.jump-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
}
.jump-btn svg {
  width: 16px;
  height: 16px;
}

/* ════════════════════ MESSAGES ════════════════════ */
.messages {
  flex: 1;
  overflow-y: auto;
}
.messages-inner {
  max-width: var(--content-w);
  margin: 0 auto;
  padding: var(--sp-11) var(--sp-10) var(--sp-10);
  display: flex;
  flex-direction: column;
  gap: var(--sp-gap);
}

.empty {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-6);
  color: var(--muted);
  text-align: center;
  padding: var(--sp-10);
}
.empty-mark {
  width: 64px;
  height: 64px;
  border-radius: var(--rd-6);
  background: rgba(var(--accent-rgb), .10);
  border: 1px solid rgba(var(--accent-rgb), .3);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--sp-5);
}
.empty-mark svg {
  width: 30px;
  height: 30px;
  fill: var(--accent);
}
.empty h2 {
  color: var(--text);
  text-wrap: balance;
  font-size: var(--fs-8);
  font-weight: 700;
}
.empty p {
  font-size: var(--fs-4);
  line-height: 1.6;
}
.suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
  justify-content: center;
  margin-top: var(--sp-9);
}
.chip {
  background: var(--bg-3);
  border: 1px solid var(--line-2);
  color: var(--text);
  padding: var(--sp-5) var(--sp-9);
  border-radius: var(--radius-pill);
  font-size: var(--fs-3);
}
.chip:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), .10);
}

/* message rows */
.msg {
  display: flex;
  gap: var(--sp-7);
}
.avatar {
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-2);
  font-weight: 700;
  letter-spacing: var(--tr-3);
  margin-top: var(--sp-2);
}
.msg.user .avatar {
  background: var(--user-bubble);
  color: var(--user-bubble-text);
  border: 1px solid var(--line);
}
.msg.assistant .avatar {
  background: var(--accent);
  color: var(--on-accent);
}
.msg-body {
  flex: 1;
  min-width: 0;
}
.msg-role {
  font-size: var(--fs-2);
  font-weight: 700;
  color: var(--muted);
  margin-bottom: var(--sp-3);
  letter-spacing: var(--tr-4);
  text-transform: uppercase;
  /* A row, not a label: the role name on the left and the clock pinned to the
     right edge of the same column the message body ends at. Both roles share
     .msg-body's width, so every time lands in one place and the column can be
     scanned top to bottom. */
  display: flex;
  align-items: baseline;
  gap: var(--sp-4);
}
.msg-role-name {
  flex: none;
}
.msg-time {
  /* Always shown, never behind a pointer: a hover-only time does not exist on
     touch, and this is metadata a reader should be able to check without asking.
     It borrows the tool counter's rung rather than inventing one -- same mono,
     same --fs-meta, same --muted, same tabular figures, because a proportional
     time is the one thing that makes a column of times unreadable. HH:MM only:
     a date on every row is noise, and the full stamp is on title=. The tracking
     and weight are reset because they are inherited from an uppercase label and
     both would spread the digits apart. */
  margin-left: auto;
  flex: none;
  font-family: var(--mono);
  font-size: var(--fs-meta);
  font-weight: 400;
  letter-spacing: var(--tr-2);
  text-transform: none;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.msg.assistant .msg-role {
  color: var(--accent);
}
/* Who sent this row, when it was not the person. A tag on the side of the
   role line: the row is still a user row, still reads as the user's turn,
   the agent has no idea an Assistant exists, and neither should the layout. */
.msg-tag {
  display: inline-block;
  margin-left: var(--sp-4);
  padding: var(--sp-1) var(--sp-4);
  font-size: var(--fs-1);
  font-weight: 700;
  letter-spacing: var(--tr-3);
  text-transform: uppercase;
  vertical-align: 1px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  color: var(--muted);
  background: rgba(var(--accent-rgb), .08);
}
.msg-tag.autonomous {
  color: var(--accent);
  border-color: rgba(var(--accent-rgb), .45);
}
/* The seam of a preview tail (backend/store.py's REGISTRY_PREVIEW): the rows on
   screen are the end of the conversation, and saying so is the difference between
   a session that looks short and one that is honestly still loading. */
.transcript-gap {
  margin: var(--sp-2) 0 var(--sp-4);
  text-align: center;
  font-size: var(--fs-2);
  letter-spacing: var(--tr-3);
  color: var(--muted);
  border-top: 1px dashed var(--line);
  padding-top: var(--sp-3);
}
/* The undo point a turn left behind, on the row that caused it (PLAN item 4). It
   is the role line's third member and it borrows the sender tag's pill so the
   line reads as one piece of furniture: same radius, same hairline, same muted
   ink, taking the accent only under the pointer because it is a control and not a
   label. Deliberately NOT margin-left:auto -- the clock owns the right edge, and
   a column of times that drifts with the width of a button is not a column. */
.msg-snap {
  flex: none;
  margin-left: var(--sp-4);
  padding: var(--sp-1) var(--sp-4);
  font-family: inherit;
  font-size: var(--fs-1);
  font-weight: 700;
  letter-spacing: var(--tr-3);
  text-transform: uppercase;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  color: var(--muted);
  background: rgba(var(--accent-rgb), .08);
  cursor: pointer;
}
.msg-snap:hover, .msg-snap:focus-visible {
  color: var(--accent);
  border-color: rgba(var(--accent-rgb), .45);
}
.msg-content {
  font-size: var(--fs-read);
  line-height: 1.65;
  overflow-wrap: break-word;
}
.msg.user .msg-content {
  white-space: pre-wrap;
  background: rgba(var(--accent-rgb), .07);
  border: 1px solid rgba(var(--accent-rgb), .2);
  border-radius: var(--rd-2) var(--radius) var(--radius) var(--radius);
  padding: var(--sp-6) var(--sp-8);
}

/* Measure. craft-floor.md: body prose runs 65-75ch; this sat at ~103ch. Tables and
   code blocks deliberately stay on the shell's full width -- operate.md: "data and
   compact UI can run denser". */
.msg-content p, .msg-content ul, .msg-content ol, .msg-content blockquote {
  max-width: 72ch;
}
.msg.user .msg-content {
  max-width: 72ch;
}
.msg-content p {
  text-wrap: pretty;
  margin: 0 0 var(--sp-6);
}
.msg-content p:last-child {
  margin-bottom: 0;
}
.msg-content h1, .msg-content h2, .msg-content h3, .msg-content h4 {
  text-wrap: balance;
  margin: var(--sp-8) 0 var(--sp-5);
  line-height: 1.35;
}
.msg-content h1 {
  font-size: var(--fs-7);
} .msg-content h2 {
  font-size: var(--fs-6);
} .msg-content h3 {
  font-size: var(--fs-5);
}
.msg-content h2 {
  padding-bottom: var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.msg-content ul, .msg-content ol {
  margin: var(--sp-4) 0 var(--sp-6) var(--sp-11);
}
.msg-content li {
  margin: var(--sp-3) 0;
}
.msg-content li::marker {
  color: var(--accent);
}
.msg-content a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid rgba(var(--accent-rgb), .4);
}
.msg-content a:hover {
  border-bottom-color: var(--accent);
}
.msg-content blockquote {
  border-left: 3px solid var(--accent);
  padding: var(--sp-3) var(--sp-8);
  color: var(--muted);
  margin: var(--sp-6) 0;
  background: rgba(var(--accent-rgb), .05);
  border-radius: 0 var(--rd-4) var(--rd-4) 0;
}
.msg-content del {
  color: var(--muted);
}
.msg-content code {
  font-family: var(--mono);
  font-size: var(--fs-3);
  background: rgba(var(--accent2-rgb), .08);
  border: 1px solid rgba(var(--accent2-rgb), .2);
  border-radius: var(--rd-3);
  padding: var(--sp-2) var(--sp-4);
}
.msg-content table {
  border-collapse: separate;
  border-spacing: 0;
  margin: var(--sp-7) 0;
  font-size: var(--fs-3);
  display: block;
  overflow-x: auto;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
}
.msg-content th, .msg-content td {
  border-bottom: 1px solid var(--line);
  padding: var(--sp-4) var(--sp-8);
  text-align: left;
}
.msg-content th {
  background: var(--bg-3);
  font-weight: 600;
  font-size: var(--fs-3);
  white-space: nowrap;
}
.msg-content tr:last-child td {
  border-bottom: 0;
}
.msg-content tbody tr:hover {
  background: rgba(var(--accent-rgb), .05);
}

/* code blocks */
.code-block {
  position: relative;
  background: var(--code-bg);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-4);
  margin: var(--sp-7) 0;
  overflow: hidden;
}
.code-block pre {
  padding: var(--sp-8) var(--sp-9);
  overflow-x: auto;
}
.code-block code {
  background: none;
  border: 0;
  padding: 0;
  font-size: var(--fs-3);
  line-height: 1.6;
  color: var(--code-text);
}
.code-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--sp-4) var(--sp-7);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-2);
  color: var(--muted);
  font-family: var(--mono);
}
.copy-btn {
  border: 1px solid var(--line-2);
  background: transparent;
  color: var(--muted);
  font-size: var(--fs-2);
  font-weight: 600;
  padding: var(--sp-2) var(--sp-6);
  border-radius: var(--rd-3);
}
.copy-btn:hover {
  color: var(--text);
  border-color: var(--accent);
}

/* reasoning block */
.reason-block {
  margin: 0 0 var(--sp-6);
}
.reason-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-5);
  font-size: var(--fs-3);
  color: var(--muted);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  padding: var(--sp-3) var(--sp-7);
}
.reason-toggle::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-2);
}
.reason-toggle:hover {
  color: var(--text);
  border-color: var(--line-2);
}
.reason-body {
  display: none;
  margin-top: var(--sp-5);
  /* Set in from the margin, the way a blockquote is. This used to be a 2px accent
     border, which craft-floor.md bans on a callout; italic + muted + indentation carry
     the same separation without the stripe. */
  margin-left: var(--sp-9);
  padding: var(--sp-6) var(--sp-8);
  color: var(--muted);
  font-size: var(--fs-3);
  line-height: 1.6;
  white-space: pre-wrap;
  max-height: var(--peek-h);
  overflow-y: auto;
  font-style: italic;
}
.reason-block.open .reason-body {
  display: block;
}

/* The tool-call block. `.tools` had no rule at all before this one: every call a
   turn emitted stacked into an unbounded column, so a turn with twenty calls pushed
   the transcript twenty cards tall and the newest call - the one you are actually
   waiting for - landed below the fold. From the third card up it is a fixed-height
   box that scrolls, the same promise the reasoning body makes about a long thing.
   The recessed ground is what sells the containment: the cards are --bg-2 on a
   --bg-2 panel, so a box of them needs a channel of its own or it reads as a list
   with a scrollbar attached by accident. */
.tools:has(.tool-card:nth-of-type(3)) {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--rd-4);
  padding: var(--sp-4);
  max-height: var(--peek-h);
  overflow-y: auto;
  /* Scrolling off the end must not hand the wheel to the transcript behind it. While
     the pointer is in this box, the box is the end of the line. */
  overscroll-behavior: contain;
}
/* One call in a bordered box inside a message that is already a box is a frame around
   a frame, and two is still a list rather than a pile - so the box only appears when
   there is something to contain. */
.tools:has(.tool-card:nth-of-type(3)) > .tool-card {
  /* The card's own turn margin is right in transcript flow and wrong in a padded
     scroll area, where it fattens the top and bottom of the box. In here, the gap
     between cards is the box's business. */
  margin: 0;
}
.tools:has(.tool-card:nth-of-type(3)) > .tool-card + .tool-card {
  margin-top: var(--sp-4);
}

/* tool call cards */
.tool-card {
  margin: var(--sp-turn) 0;
  border: 1px solid var(--line);
  border-radius: var(--rd-4);
  background: var(--bg-2);
  overflow: hidden;
  font-size: var(--fs-uirow);
}
.tool-head {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  padding: var(--sp-row) var(--sp-7);
  cursor: pointer;
  user-select: none;
}
.tool-head:hover {
  background: var(--bg-3);
}
.tool-badge {
  font-family: var(--mono);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: var(--tr-3);
  color: var(--accent-2);
  background: rgba(var(--accent2-rgb), .09);
  border: 1px solid rgba(var(--accent2-rgb), .3);
  border-radius: var(--rd-3);
  padding: var(--sp-2) var(--sp-5);
}
.tool-card.err .tool-badge {
  color: var(--err);
  background: rgba(var(--err-rgb), .09);
  border-color: rgba(var(--err-rgb), .35);
}

/* ── tool-call rail ───────────────────────────────────────────────────────
   A turn's tool calls read as a bar chart of time, not a list of text. Each card
   carries a bar whose length is that call's elapsed time on a FIXED log scale
   (300ms..30s, set in app.js) so a 40ms file read and a 20s build stay comparable
   across turns - normalizing each turn against its own slowest call would make a
   fast turn and a slow turn look identical, which is the one thing a readout is
   for. scaleX, not width: animate.md bans animating layout-driving properties, and
   a transcript that reflowed on every tool_end would be worse than no chart. It
   sits below the head rather than inside it because .tool-args already owns the
   flex space and truncating the command to buy a chart would be a bad trade.
   Colour only where a state needs attention: a finished call is neutral, because
   green on every card is noise (colorize.md, don't spend the accent on
   decoration, and the strongest colour owns a deliberate region). */
.tool-rail {
  position: relative;
  height: 2px;
  background: var(--line-2);
}
.tool-rail::after {
  content: "";
  position: absolute;
  inset: 0;
  transform-origin: left;
  transform: scaleX(var(--dur, 0));
  background: var(--muted);
  transition: transform 180ms cubic-bezier(.16, 1, .3, 1);
}
.tool-card.run .tool-rail::after {
  background: var(--accent);
}
.tool-card.err .tool-rail::after {
  background: var(--err);
}
/* The turn's aggregate readout: how many calls, how long, which was slowest. */
.rail-sum {
  display: flex;
  gap: var(--sp-5);
  justify-content: flex-end;
  padding-top: var(--sp-3);
  font-family: var(--mono);
  font-size: var(--fs-meta);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.tool-args {
  color: var(--muted);
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: var(--mono);
  font-size: var(--fs-meta);
}
.tool-meta {
  /* live run counter: "12s · 4.1 KB", set only once output arrives */
  flex: none;
  font-family: var(--mono);
  font-size: var(--fs-meta);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  /* so the ticking seconds do not jitter */
}
.tool-spin {
  /* static pending marker, no motion */
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
  border: 2px solid var(--line-2);
  border-top-color: var(--accent);
}
.tool-body {
  display: none;
  /* It already had a 280px cap, but a cap nobody can see reads as "the card got
     taller": a border-top made the output look like more card rather than like
     something inside one. So it becomes a sunk well in its own right - its own
     ground, a border all round, a corner, and an inset from the card's edges,
     which is the same treatment the reasoning block gets and the reason that one
     reads as contained. The scroll inside it is now obvious instead of implied. */
  margin: var(--sp-5) var(--sp-7) var(--sp-7);
  border: 1px solid var(--line);
  border-radius: var(--rd-4);
  background: var(--code-bg);
  box-shadow: inset 0 1px 2px color-mix(in srgb, var(--shade) 22%, transparent);
  padding: var(--sp-6) var(--sp-8);
  max-height: var(--peek-h);
  overflow: auto;
}
.tool-card.open .tool-body {
  display: block;
}
.tool-body pre {
  font-family: var(--mono);
  font-size: var(--fs-3);
  white-space: pre-wrap;
  color: var(--muted);
}

/* ════════════════════ COMPOSER ════════════════════ */
.composer-wrap {
  padding: 0 var(--sp-10) var(--sp-8);
}
/* ── task strip: the session's task list, above the composer ── */
.task-strip {
  max-width: var(--content-w);
  margin: 0 auto var(--sp-5);
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-5);
  padding: var(--sp-4) var(--sp-6);
  font-size: var(--fs-3);
  color: var(--muted);
}
.task-strip-icon {
  color: var(--accent);
  flex: 0 0 auto;
}
.task-strip-count {
  flex: 0 0 auto;
  font-weight: 600;
  color: var(--text);
}
.task-strip-list {
  flex: 1;
  min-width: 0;
  max-height: 150px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-2) 0;
}
.task-strip-item {
  display: flex;
  align-items: baseline;
  gap: var(--sp-5);
  line-height: 1.45;
}
.task-strip-item .tick {
  color: var(--accent);
  flex: 0 0 auto;
  font-weight: 700;
}
.task-strip-item.done {
  color: var(--fadetext);
  text-decoration: line-through;
}
.task-strip-item .task-text {
  word-break: break-word;
}
.task-strip-close {
  flex: 0 0 auto;
  border: 0;
  background: none;
  color: var(--fadetext);
  cursor: pointer;
  font-size: var(--fs-2);
  padding: var(--sp-2) var(--sp-3);
}
.task-strip-close:hover {
  color: var(--text);
}
.composer {
  max-width: var(--content-w);
  margin: 0 auto;
  display: flex;
  align-items: flex-end;
  gap: var(--sp-5);
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-5);
  padding: var(--sp-5) var(--sp-5) var(--sp-5) var(--sp-8);
}
.composer textarea {
  flex: 1;
  background: none;
  border: 0;
  resize: none;
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-4);
  line-height: 1.5;
  max-height: 200px;
  padding: var(--sp-5) 0;
}
.composer textarea::placeholder {
  color: var(--fadetext);
}
/* The textarea is borderless inside a rounded box, so the global focus ring drew a
   square around the writing area while `.composer:focus-within` lit the rounded
   border at the same time: two indicators for one state, and the square is the
   uglier of the two. Dropping an outline is only legal because the container's
   stays, and it is strengthened here so it does not merely survive the removal. */
.composer textarea:focus-visible {
  outline: none;
}
.composer:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 var(--sp-1) color-mix(in srgb, var(--accent) 32%, transparent);
}
/* Same doubling in the Assistant: its textarea IS the box, so the border colour is
   the indicator and the outline is a second one drawn over it. */
.as-input textarea:focus-visible {
  outline: none;
}
.composer-side {
  flex: 0 0 auto;
  color: var(--muted);
}
.composer-side.active {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, var(--bg-2));
  border-color: rgba(var(--accent-rgb), .4);
}
.send-btn {
  width: 36px;
  height: 36px;
  flex: none;
  border: 0;
  border-radius: var(--rd-5);
  background: var(--accent);
  color: var(--on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
}
.send-btn:hover {
  background: color-mix(in srgb, var(--accent) 84%, var(--text));
}
.send-btn svg {
  width: 16px;
  height: 16px;
}
.send-btn.stop {
  background: transparent;
  color: var(--err);
  border: 1px solid var(--err);
}
.send-btn.stop:hover {
  background: rgba(var(--err-rgb), .12);
}
/* busy: send becomes "steer the running turn", amber outline cue */
.send-btn.steer {
  background: transparent;
  color: var(--warn);
  border: 1px solid var(--warn);
}
.send-btn.steer:hover {
  background: rgba(var(--warn-rgb), .12);
}
.composer-hint {
  max-width: var(--content-w);
  margin: var(--sp-4) auto 0;
  text-align: center;
  font-size: var(--fs-2);
  color: var(--fadetext);
}
.composer-hint.booting {
  color: var(--muted);
}
.composer-hint.booting::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: var(--sp-4);
  border-radius: 50%;
  background: var(--warn);
  vertical-align: 1px;
}

/* attachment chips */
.attach-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
  padding: 0 var(--sp-2) var(--sp-5);
  max-width: var(--content-w);
  margin: 0 auto;
}
.att-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  font-size: var(--fs-3);
  border: 1px solid rgba(var(--accent-rgb), .3);
  border-radius: var(--radius-sm);
  padding: var(--sp-3) var(--sp-5);
  background: rgba(var(--accent-rgb), .06);
}
.att-chip img {
  width: 22px;
  height: 22px;
  object-fit: cover;
  border-radius: var(--rd-3);
}
.att-chip button {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-size: var(--fs-4);
  line-height: 1;
  padding: var(--sp-2);
}
.att-chip button:hover {
  color: var(--err);
}

/* ════════════════════ PLAN STRIP ════════════════════ */
.plan-strip {
  margin: 0 var(--sp-10) var(--sp-6);
  border: 1px solid rgba(var(--accent-rgb), .3);
  border-radius: var(--rd-5);
  background: rgba(var(--accent-rgb), .05);
  padding: var(--sp-7) var(--sp-8);
}
.ps-head {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  flex-wrap: wrap;
}
.ps-icon {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
}
/* The approved-plan strip is a terminal state, so its dot takes the status
   colour rather than the in-progress accent. A class, not an inline style: a
   literal `#3fb950` in the JS froze midnight's green into all eight themes. */
.ps-icon.ok {
  background: var(--ok);
}
.ps-phase {
  font-weight: 700;
  font-size: var(--fs-3);
}
.ps-detail {
  color: var(--muted);
  font-size: var(--fs-3);
  flex: 1;
  min-width: 120px;
}
/* .ps-ok / .ps-warn used to live here. The approval wrote two files (the plan
   record and the project's PLAN.md), and either could fail alone, so the strip
   needed a colour per copy and a refused PLAN.md had not to read like a success.
   One file is written now and it either exists or the approval threw, so the
   markup that needed them is gone and the rules went with it. */
.ps-cancel {
  border: 1px solid var(--line-2);
  background: transparent;
  color: var(--muted);
  border-radius: var(--rd-3);
  padding: var(--sp-3) var(--sp-6);
  font-size: var(--fs-3);
  font-weight: 600;
}
.ps-cancel:hover {
  color: var(--err);
  border-color: var(--err);
}
.ps-explorers {
  margin-top: var(--sp-6);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.ps-exp {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  font-size: var(--fs-3);
}
.ps-exp-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
  background: var(--accent);
}
.ps-exp.done .ps-exp-dot {
  background: var(--ok);
}
.ps-exp-label {
  font-weight: 600;
}
.ps-exp-act {
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ps-progress {
  margin-top: var(--sp-6);
  height: 3px;
  border-radius: var(--rd-1);
  background: var(--bg-3);
  overflow: hidden;
}
.ps-progress-bar {
  height: 100%;
  background: var(--accent);
}

/* clarifying questions card */
.pq-list {
  margin-top: var(--sp-7);
  display: flex;
  flex-direction: column;
  gap: var(--sp-7);
}
.pq-q {
  font-size: var(--fs-4);
  font-weight: 600;
  margin-bottom: var(--sp-4);
}
.pq-opts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
}
.pq-opt {
  border: 1px solid var(--line-2);
  background: var(--bg-2);
  color: var(--text);
  border-radius: var(--radius-pill);
  padding: var(--sp-3) var(--sp-7);
  font-size: var(--fs-3);
}
.pq-opt:hover {
  border-color: var(--accent);
}
.pq-opt.picked {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.pq-opt.other {
  color: var(--muted);
  font-style: italic;
}
.pq-typed {
  margin-top: var(--sp-5);
  width: 100%;
  background: var(--bg-3);
  color: var(--text);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-4);
  padding: var(--sp-4) var(--sp-6);
  font-size: var(--fs-3);
  font-family: inherit;
}
.pq-typed:focus {
  border-color: var(--accent);
}
.pq-actions, .pr-actions {
  margin-top: var(--sp-8);
  display: flex;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
/* The draft the strip shows for approval. It carries .msg-content for the
   markdown rules, which set a transcript's 14.5px prose; a plan lives in a strip
   above the composer, so it is tightened a step. A real plan is longer than the
   strip is, and the composer has to stay reachable without scrolling the page, so
   the body scrolls on its own. */
.pr-body {
  max-height: 38vh;
  overflow-y: auto;
  margin-top: var(--sp-6);
  font-size: var(--fs-4);
  line-height: 1.6;
  padding: var(--sp-6) var(--sp-8);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
}

/* ════════════════════ SESSION MENU ════════════════════ */
.sess-menu-wrap {
  position: relative;
}
.sess-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 7px);
  z-index: 40;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-4);
  padding: var(--sp-3);
  min-width: 210px;
  box-shadow: var(--sh-3);
  max-height: 70vh;
  overflow-y: auto;
  display: none;
}
.sess-menu.open {
  display: block;
}
.sess-menu button {
  text-align: left;
  background: none;
  border: none;
  color: var(--text);
  padding: var(--sp-5) var(--sp-6);
  font-size: var(--fs-3);
  border-radius: var(--rd-3);
  cursor: pointer;
  display: block;
  width: 100%;
  white-space: nowrap;
}
.sess-menu button:hover {
  background: var(--bg-3);
}

/* ════════════════════ SETTINGS OVERLAY ════════════════════ */
.harness-overlay {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: var(--dim);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-11);
}
.ho-shell {
  width: min(1020px, 96vw);
  height: min(700px, 92vh);
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  box-shadow: var(--sh-3);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.ho-head {
  display: flex;
  align-items: center;
  gap: var(--sp-9);
  padding: var(--sp-7) var(--sp-9);
  border-bottom: 1px solid var(--line);
}
.ho-title {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  font-weight: 700;
  font-size: var(--fs-4);
}
.ho-title svg {
  color: var(--accent);
}
.ho-tabs {
  display: flex;
  gap: var(--sp-3);
  flex: 1;
}
.ho-tab {
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
  font-size: var(--fs-3);
  font-weight: 600;
  padding: var(--sp-5) var(--sp-8);
  border-radius: var(--rd-4);
}
.ho-tab:hover {
  color: var(--text);
  background: var(--bg-3);
}
.ho-tab.active {
  color: var(--text);
  background: var(--bg-3);
  border-color: var(--line-2);
}
.ho-close {
  margin-left: auto;
}
.ho-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--sp-9) var(--sp-10);
}
.ho-foot {
  padding: var(--sp-5) var(--sp-9);
  border-top: 1px solid var(--line);
  font-size: var(--fs-3);
  color: var(--muted);
  min-height: 33px;
  font-family: var(--mono);
}
.ho-foot .err {
  color: var(--err);
}
.ho-loading {
  color: var(--muted);
  font-size: var(--fs-3);
  padding: var(--sp-10) 0;
}
.ho-empty {
  color: var(--muted);
  font-size: var(--fs-3);
  padding: var(--sp-8) 0;
}
.ho-empty.sm {
  padding: var(--sp-4) 0;
  font-size: var(--fs-3);
}
.ho-sub {
  font-size: var(--fs-3);
  color: var(--muted);
}
.ho-sub code {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--accent-2);
}
.ho-err {
  color: var(--err);
  font-size: var(--fs-3);
}
.ho-section {
  font-size: var(--fs-1);
  text-transform: uppercase;
  letter-spacing: var(--tr-4);
  color: var(--muted);
  font-weight: 600;
  margin: var(--sp-10) 0 var(--sp-5);
  display: flex;
  align-items: center;
  gap: var(--sp-5);
}
.ho-section:first-child {
  margin-top: 0;
}
.ho-count {
  background: rgba(var(--accent-rgb), .10);
  color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), .3);
  border-radius: var(--radius-pill);
  padding: var(--sp-1) var(--sp-5);
  font-size: var(--fs-1);
  font-weight: 700;
}

/* settings buttons */
.ho-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  background: var(--bg-3);
  border: 1px solid var(--line-2);
  color: var(--text);
  font-size: var(--fs-3);
  font-weight: 600;
  padding: var(--sp-4) var(--sp-8);
  border-radius: var(--radius-sm);
}
.ho-btn:hover {
  border-color: var(--accent);
}
.ho-btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.ho-btn.primary:hover {
  background: color-mix(in srgb, var(--accent) 84%, var(--text));
}
.ho-btn.danger {
  color: var(--err);
}
.ho-btn.danger:hover {
  border-color: var(--err);
  background: rgba(var(--err-rgb), .08);
}
.ho-btn.small {
  padding: var(--sp-3) var(--sp-6);
  font-size: var(--fs-2);
  border-radius: var(--rd-3);
}
.ho-toolbar {
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  margin-bottom: var(--sp-8);
}

/* forms */
.ho-form {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--rd-5);
  padding: var(--sp-8);
  margin-bottom: var(--sp-9);
}
.ho-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-6);
}
.ho-form label, .block-label {
  font-size: var(--fs-2);
  color: var(--muted);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  font-weight: 600;
}
.block-label {
  margin-top: var(--sp-6);
}
.ho-form input, .ho-form select, .ho-form textarea {
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-4);
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-3);
  padding: var(--sp-5) var(--sp-6);
}
.ho-form textarea {
  font-family: inherit;
  resize: vertical;
  line-height: 1.55;
}
.ho-form input:focus, .ho-form textarea:focus, .ho-form select:focus {
  border-color: var(--accent);
}
.ho-form-actions {
  display: flex;
  gap: var(--sp-5);
  margin-top: var(--sp-7);
}

/* provider cards */
.prov-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-7);
}
.prov-card {
  padding: var(--sp-8) var(--sp-9);
}
.prov-head {
  justify-content: space-between;
  gap: var(--sp-6);
}
.prov-name {
  font-weight: 700;
  font-size: var(--fs-4);
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
.prov-meta {
  font-size: var(--fs-3);
  color: var(--muted);
  margin: var(--sp-4) 0 var(--sp-6);
}
.prov-meta code {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--accent-2);
}
.badge {
  font-size: var(--fs-1);
  font-weight: 700;
  letter-spacing: var(--tr-4);
  text-transform: uppercase;
  padding: var(--sp-2) var(--sp-5);
  border-radius: var(--radius-pill);
  background: rgba(var(--accent-rgb), .10);
  color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), .3);
}
.badge.key {
  background: rgba(var(--accent2-rgb), .08);
  color: var(--accent-2);
  border-color: rgba(var(--accent2-rgb), .3);
  text-transform: none;
  font-family: var(--mono);
  letter-spacing: var(--tr-2);
  font-weight: 600;
}
.badge.default {
  background: rgba(var(--warn-rgb), .10);
  color: var(--warn);
  border-color: rgba(var(--warn-rgb), .35);
}
.model-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin-bottom: var(--sp-6);
}
.model-row {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--sp-4) var(--sp-6);
  font-size: var(--fs-3);
}
.model-row.is-default {
  border-color: rgba(var(--warn-rgb), .5);
}
.model-id {
  font-family: var(--mono);
  font-size: var(--fs-3);
}
.model-ctx {
  font-size: var(--fs-2);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.model-spacer {
  flex: 1;
}
.model-add {
  display: flex;
  gap: var(--sp-5);
  align-items: center;
  flex-wrap: wrap;
}
.model-add input {
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-4);
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-3);
  padding: var(--sp-4) var(--sp-6);
}
.model-add input:focus {
  border-color: var(--accent);
}
.model-add .model-add-id {
  flex: 1;
  min-width: 200px;
}
.model-add .model-add-name {
  flex: 1;
  min-width: 160px;
}
.chk {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  font-size: var(--fs-3);
  color: var(--muted);
  cursor: pointer;
}
.chk input {
  accent-color: var(--accent);
}
.probe-results {
  margin-top: var(--sp-7);
  border-top: 1px dashed var(--line-2);
  padding-top: var(--sp-6);
}
.probe-head {
  font-size: var(--fs-3);
  color: var(--text);
  margin-bottom: var(--sp-5);
  font-weight: 600;
}
.probe-ids {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
}
.probe-ids .chk {
  font-family: var(--mono);
  font-size: var(--fs-3);
  color: var(--text);
}

/* skills */
.skill-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-6);
}
.skill-card {
  padding: var(--sp-7) var(--sp-8);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.skill-head {
  gap: var(--sp-5);
}
.skill-name {
  font-weight: 700;
  font-size: var(--fs-3);
}
.skill-del {
  margin-left: auto;
}
.skill-desc {
  font-size: var(--fs-3);
  color: var(--muted);
  line-height: 1.5;
}
.skill-body summary {
  font-size: var(--fs-2);
  color: var(--accent-2);
  cursor: pointer;
  font-weight: 600;
  user-select: none;
}
.skill-body summary:hover {
  text-decoration: underline;
}
.skill-body pre {
  margin-top: var(--sp-4);
  font-family: var(--mono);
  font-size: var(--fs-2);
  white-space: pre-wrap;
  color: var(--muted);
  max-height: 220px;
  overflow-y: auto;
  line-height: 1.55;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--rd-4);
  padding: var(--sp-5) var(--sp-6);
}

/* extensions */
.ext-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.ext-row {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--sp-5) var(--sp-6);
  font-size: var(--fs-3);
}
.ext-name {
  font-family: var(--mono);
  font-size: var(--fs-3);
}

/* tools toggles */
.tool-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.tool-row {
  display: flex;
  align-items: center;
  gap: var(--sp-7);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--sp-5) var(--sp-7);
  font-size: var(--fs-3);
}
.tool-row.off {
  opacity: .5;
}
.tool-name {
  font-family: var(--mono);
  font-size: var(--fs-3);
  font-weight: 600;
  min-width: 130px;
}
.tool-desc {
  flex: 1;
  color: var(--muted);
  font-size: var(--fs-3);
  line-height: 1.4;
}
.tgl {
  width: 38px;
  height: 20px;
  flex: none;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line-2);
  background: var(--bg-2);
  position: relative;
  padding: 0;
}
.tgl-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--muted);
}
.tgl.on {
  background: rgba(var(--accent-rgb), .4);
  border-color: var(--accent);
}
.tgl.on .tgl-knob {
  left: 20px;
  background: var(--accent);
}

/* appearance panel, theme cards */
/* Theme groups. Twenty equal cards in one grid is a wall: there is no way to rule
   out half of them, so every scan re-reads the whole set. The label is sentence-case
   and quiet on purpose -- a shouty tracked-caps section header would be the loudest
   thing in a panel whose job is to show swatches, and the rule after it is what
   actually closes the group off. */
.theme-group + .theme-group { margin-top: var(--sp-8); }
.theme-group-label {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  font-size: var(--fs-3);
  font-weight: 600;
  color: var(--muted);
  margin-bottom: var(--sp-5);
}
.theme-group-label::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--line);
}
.theme-group-count {
  font-family: var(--mono);
  font-size: var(--fs-1);
  color: var(--muted);
  /* --sp-1 is 1px, and the scale exists so that a stray literal cannot creep back
     in: this file's own test rejects a raw px in padding. */
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.theme-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--sp-6);
}
.sw-graphite { background: linear-gradient(135deg, #619abc 50%, #6dc3bc 50%); }
.sw-vellum { background: linear-gradient(135deg, #3e58ab 50%, #006776 50%); }
.sw-verdigris { background: linear-gradient(135deg, #c88c5f 50%, #79acd0 50%); }
.sw-oxide { background: linear-gradient(135deg, #e6ded8 50%, #72b5cf 50%); }
.sw-signal { background: linear-gradient(135deg, #046382 50%, #68476f 50%); }
.sw-mono { background: linear-gradient(135deg, #e6e6e6 50%, #b1b1b1 50%); }
.sw-amethyst { background: linear-gradient(135deg, #a08eca 50%, #7db8bf 50%); }
.sw-celadon { background: linear-gradient(135deg, #126b74 50%, #5c5382 50%); }
.sw-contrast { background: linear-gradient(135deg, #ffd60a 50%, #4ad9ff 50%); }
.sw-contrast-light { background: linear-gradient(135deg, #0033cc 50%, #004d40 50%); }
.sw-nocturne { background: linear-gradient(135deg, #c0b26c 50%, #79afbd 50%); }
.sw-lagoon { background: linear-gradient(135deg, #52afb4 50%, #96a6d5 50%); }
.sw-rosewood { background: linear-gradient(135deg, #c790a4 50%, #7ab6b7 50%); }
.sw-absinthe { background: linear-gradient(135deg, #9fba6f 50%, #8aabcd 50%); }
.sw-iris { background: linear-gradient(135deg, #8190d2 50%, #7ab5bc 50%); }
.sw-slate { background: linear-gradient(135deg, #9ae1ff 50%, #f4c9fe 50%); }
.sw-frost { background: linear-gradient(135deg, #006b71 50%, #5b5184 50%); }
.sw-monotype { background: linear-gradient(135deg, #202020 50%, #505050 50%); }
.sw-foxglove { background: linear-gradient(135deg, #6c4d87 50%, #006770 50%); }
.sw-sorrel { background: linear-gradient(135deg, #3d5c95 50%, #00686d 50%); }
.sw-kinpaku-dark { background: linear-gradient(135deg, #d9b45c 50%, #6fb3ad 50%); }
.sw-kinpaku { background: linear-gradient(135deg, #7a5c12 50%, #14676b 50%); }

.theme-card {
  display: flex;
  align-items: center;
  gap: var(--sp-7);
  text-align: left;
  padding: var(--sp-7) var(--sp-8);
  color: var(--text);
}
.theme-card:hover {
  border-color: var(--line-2);
}
.theme-card.active {
  border-color: var(--accent);
}
.theme-dot {
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  flex: none;
  border: 1px solid color-mix(in srgb, var(--shade) 30%, transparent);
}
.theme-meta {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.theme-meta b {
  font-size: var(--fs-3);
  font-weight: 600;
}
.theme-meta small {
  font-size: var(--fs-2);
  color: var(--muted);
}
.theme-check {
  margin-left: auto;
  color: var(--accent);
  font-weight: 700;
  font-size: var(--fs-2);
  text-transform: uppercase;
  letter-spacing: var(--tr-4);
}

/* ════════════════════ TERMINAL ════════════════════ */
.term-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--dim);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-12);
}
.term-shell {
  width: min(1000px, 94vw);
  height: min(620px, 78vh);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-5);
  box-shadow: var(--sh-3);
}
.term-head {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  flex: 0 0 auto;
  padding: var(--sp-5) var(--sp-6);
  border-bottom: 1px solid var(--line);
  background: var(--bg-2);
}
.term-title {
  font-size: var(--fs-3);
  font-weight: 600;
  color: var(--text);
}
.term-cwd {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 45%;
}
.term-shell-name {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--fadetext);
  margin-left: auto;
}
.term-btn {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--muted);
  border-radius: var(--rd-3);
  padding: var(--sp-3) var(--sp-6);
  font-size: var(--fs-2);
  cursor: pointer;
  font-family: inherit;
}
.term-btn:hover {
  border-color: var(--accent);
  color: var(--text);
}
.term-out {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--sp-7) var(--sp-8);
  font-family: var(--mono);
  font-size: var(--fs-3);
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text);
}
.term-out > div {
  margin-bottom: var(--sp-2);
}
.term-echo {
  color: var(--accent);
}
.term-stdout {
  color: var(--text);
}
.term-stderr {
  color: var(--err);
}
.term-note {
  color: var(--fadetext);
  font-style: italic;
}
.term-input-row {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  flex: 0 0 auto;
  padding: var(--sp-6) var(--sp-8);
  border-top: 1px solid var(--line);
  background: var(--bg-2);
}
.term-prompt {
  font-family: var(--mono);
  font-size: var(--fs-3);
  color: var(--accent);
}
.term-input-row input {
  flex: 1;
  background: transparent;
  border: 0;
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-3);
  padding: var(--sp-2) 0;
}
.term-input-row input::placeholder {
  color: var(--fadetext);
}

@media (max-width: 760px) {
  .term-overlay {
  padding: 0;
}
  .term-shell {
  width: 100%;
  height: 100%;
  border-radius: 0;
}
}


/* ════════════════════ TOAST ════════════════════ */
.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%) translateY(80px);
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  color: var(--text);
  padding: var(--sp-6) var(--sp-9);
  border-radius: var(--radius-pill);
  font-size: var(--fs-3);
  font-weight: 500;
  z-index: 120;
  box-shadow: var(--sh-3);
  max-width: 82vw;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.toast.show {
  transform: translateX(-50%) translateY(0);
}

/* ════════════════════ RESPONSIVE ════════════════════ */
@media (max-width: 760px) {
  .sidebar {
  position: absolute;
  z-index: 50;
  height: 100%;
  margin-left: calc(var(--sidebar-w) * -1);
  box-shadow: var(--sh-2);
}
  .sidebar.open {
  margin-left: 0;
}
  .skill-grid, .ho-form-grid {
  grid-template-columns: 1fr;
}
  .top-meta {
  display: none;
}
  .tok-meter .tok-count {
  display: none;
}   /* keep the context bar only */
  .jump-btn {
  bottom: 100px;
  right: 16px;
}
  .empty h2 {
  font-size: var(--fs-7);
}
}

/* ════════════════ MOBILE (finishes the block above) ════════════════
   The 760px block already turns the sidebar into an off-canvas panel and
   app.js:2594 already picks `.open` vs `.hidden` by innerWidth, so the drawer
   half-exists. What it does not have: anything to tap to close it, any height
   that survives a mobile URL bar, any allowance for a notch or a home
   indicator, and touch targets sized for a finger. There is no
   env(safe-area-inset-*) anywhere in this file, and index.html's viewport meta
   lacked viewport-fit=cover - without that token every env() resolves to zero,
   so the insets are added here AND in the meta, or they do nothing.

   Deliberately NOT done: no `overflow-x: hidden` on body. The off-canvas
   sidebar lives at a negative margin, so clipping an ancestor would clip the
   drawer's own transition, and a blanket clip hides the real offender instead
   of fixing it. Overflow is handled per-container below. */
@media (max-width: 760px) {
  /* 100vh on a phone is the layout viewport, which is taller than what you can */
  .app {
    height: 100vh;
    height: 100dvh;
  }

  /* drawer: fixed, scrollable, and with a scrim to tap away ───────── */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    height: 100dvh;
    max-width: 84vw;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* the home indicator sits over the bottom of the drawer, exactly where the */
    padding-bottom: calc(var(--sp-6) + env(safe-area-inset-bottom));
    padding-left: env(safe-area-inset-left);
  }
  .sidebar.open {
    margin-left: 0;
    box-shadow: var(--sh-3);
  }
  .app:has(.sidebar.open)::after {
    content: "";
    position: fixed;
    inset: 0;
    background: color-mix(in srgb, var(--shade) 42%, transparent);
    z-index: 45;   /* under the drawer (50), over everything else */
  }

  /* header ─────────────────────────────────────────────────────────── */
  .topbar {
    padding-left: calc(var(--sp-5) + env(safe-area-inset-left));
    padding-right: calc(var(--sp-5) + env(safe-area-inset-right));
  }
  .icon-btn {
    min-width: 44px;
    min-height: 44px;
  }
  /* The workspace chip and the mode segment are the two things a thumb has to */
  .wd-chip, .seg button, .new-chat-btn, .ho-btn.small, .jump-btn {
    min-height: 44px;
  }
  .ctl-select, .sess-menu button {
    min-height: 40px;
    font-size: var(--fs-5);   /* 16px exactly; below it iOS zooms on focus */
  }
  .sess-menu {
    max-width: calc(100vw - 2 * var(--sp-5));
  }

  /* message list: no sideways page scroll ──────────────────────────── */
  .messages {
    padding-left: calc(var(--sp-5) + env(safe-area-inset-left));
    padding-right: calc(var(--sp-5) + env(safe-area-inset-right));
  }
  .msg img, .msg video, .msg svg, .msg canvas, .msg table {
    max-width: 100%;
    height: auto;
  }
  .msg pre, .msg code {
    max-width: 100%;
  }
  .ho-shell, .snap-shell, .term-shell {
    width: 100%;
    max-width: 100vw;
    box-sizing: border-box;
  }

  /* composer: full width, clear of the home indicator and the keyboard ─ */
  .composer {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    padding-left: calc(var(--sp-5) + env(safe-area-inset-left));
    padding-right: calc(var(--sp-5) + env(safe-area-inset-right));
    padding-bottom: calc(var(--sp-5) + env(safe-area-inset-bottom));
  }
  .composer textarea, .composer input {
    font-size: var(--fs-5);
  }
  #sendBtn, #stopBtn {
    min-height: 44px;
    min-width: 44px;
  }

  /* Toast and jump button are both bottom-anchored fixed elements, which is */
  .toast {
    bottom: calc(24px + env(safe-area-inset-bottom));
    max-width: calc(100vw - 2 * var(--sp-6));
    white-space: normal;
  }
  .jump-btn {
    bottom: calc(100px + env(safe-area-inset-bottom));
    min-width: 44px;
    min-height: 44px;
  }
}

/* A pointer-driven layout must not be assumed when there is no hover: the
   assistant pane's action row is already revealed on (hover: none) at :4826,
   and the transcript's hover-revealed meta line (item 5's note) is the other
   place where "hover" is a thing that does not exist here. */
@media (hover: none) and (pointer: coarse) {
  .msg-turn-meta, .msg-tools-meta {
    opacity: 1;
  }
}

/* ── message edit (go back in time) ─────────────────────────────── */
.msg .msg-body {
  position: relative;
}
.msg-edit {
  position: absolute;
  top: 0;
  right: 0;
  width: 26px;
  height: 26px;
  padding: var(--sp-3);
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s;
  border-radius: var(--rd-3);
}
.msg-edit svg {
  width: 100%;
  height: 100%;
}
.msg.user:hover .msg-edit, .msg-edit:focus-visible {
  opacity: 1;
}
.msg-edit:hover {
  color: var(--text);
  background: var(--bg-hover);
}
.edit-area {
  width: 100%;
  min-height: 72px;
  resize: vertical;
  font: inherit;
  font-size: var(--fs-4);
  line-height: 1.55;
  color: var(--text);
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  padding: var(--sp-6) var(--sp-7);
}
.edit-area:focus {
  border-color: var(--accent);
}
.edit-actions {
  display: flex;
  gap: var(--sp-5);
  justify-content: flex-end;
  margin-top: var(--sp-5);
}
.edit-actions .ho-btn {
  padding: var(--sp-4) var(--sp-8);
  font-size: var(--fs-3);
}

/* ════════════════════ GIT PANEL ════════════════════ */
.git-shell {
  width: min(1120px, 96vw);
  height: min(760px, 92vh);
}
.snap-shell {
  width: min(760px, 94vw);
  height: min(640px, 90vh);
}
#snapNote {
  margin-bottom: var(--sp-5);
}
#snapNote.err {
  color: var(--err);
}
.git-repo {
  flex: 1;
  min-width: 0;
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--rd-4);
  padding: var(--sp-4) var(--sp-6);
  margin: 0 var(--sp-6);
}
.git-overlay .ho-body {
  padding: 0;
  overflow: hidden;
}
.git-body {
  display: grid;
  grid-template-columns: 340px 1fr;
  height: 100%;
}
.git-side, .git-main {
  overflow-y: auto;
  padding: var(--sp-9) var(--sp-9);
  min-height: 0;
}
.git-side {
  border-right: 1px solid var(--line);
}
.git-main {
  display: flex;
  flex-direction: column;
}
.git-actions {
  display: flex;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
.git-actions .ho-btn {
  flex: 1;
  justify-content: center;
}

.git-branchbar {
  margin-top: var(--sp-7);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--rd-4);
  padding: var(--sp-6) var(--sp-7);
}
.git-current {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  font-size: var(--fs-3);
  margin-bottom: var(--sp-6);
}
.git-branch-icon {
  color: var(--accent);
}
.git-track {
  font-size: var(--fs-2);
  color: var(--accent-2);
}
.git-track.dim {
  color: var(--fadetext);
}
.git-branch-row {
  display: flex;
  gap: var(--sp-4);
}
.git-select {
  flex: 1;
  min-width: 0;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-4);
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-3);
  padding: var(--sp-4) var(--sp-5);
}
.git-select:focus {
  border-color: var(--accent);
}

.git-changes {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-height: 220px;
  overflow-y: auto;
}
.git-file {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--rd-3);
  font-size: var(--fs-3);
}
.git-file:hover {
  background: var(--bg-3);
}
.git-glyph {
  width: 17px;
  text-align: center;
  font-weight: 700;
  font-size: var(--fs-2);
  font-family: var(--mono);
  border-radius: var(--rd-2);
}
.git-glyph.m {
  color: var(--warn);
}
.git-glyph.a {
  color: var(--ok);
}
.git-glyph.d {
  color: var(--err);
}
.git-glyph.r {
  color: var(--accent);
}
.git-glyph.u {
  color: var(--muted);
}
.git-file-path {
  flex: 1;
  font-family: var(--mono);
  font-size: var(--fs-2);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.git-file-path:hover {
  color: var(--accent);
  text-decoration: underline;
}
.git-file-btn {
  width: 20px;
  height: 20px;
  border-radius: var(--rd-3);
  border: 1px solid var(--line-2);
  background: var(--bg-2);
  color: var(--muted);
  font-size: var(--fs-4);
  line-height: 1;
  cursor: pointer;
}
.git-file-btn:hover {
  color: var(--text);
  border-color: var(--accent);
}

.git-commit {
  margin-top: var(--sp-7);
}
.git-commit textarea {
  width: 100%;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-3);
  padding: var(--sp-5) var(--sp-6);
  resize: vertical;
}
.git-commit textarea:focus {
  border-color: var(--accent);
}
.git-commit-actions {
  display: flex;
  gap: var(--sp-5);
  margin-top: var(--sp-5);
}
.git-commit-actions .ho-btn {
  flex: 1;
  justify-content: center;
}

.git-remotes {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.git-remote {
  display: flex;
  flex-direction: column;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--sp-4) var(--sp-6);
}
.git-remote strong {
  font-size: var(--fs-3);
}
.git-remote code {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.git-remote-add {
  display: flex;
  gap: var(--sp-4);
  margin-top: var(--sp-4);
}
.git-remote-add input {
  flex: 1;
  min-width: 0;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-4);
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-2);
  padding: var(--sp-4) var(--sp-5);
}
.git-remote-add input:focus {
  border-color: var(--accent);
}

.git-workdir {
  display: flex;
  gap: var(--sp-4);
  margin-top: var(--sp-6);
}
.git-workdir input {
  flex: 1;
  min-width: 0;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-4);
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-2);
  padding: var(--sp-4) var(--sp-5);
}
.git-workdir input:focus {
  border-color: var(--accent);
}

.git-github {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.git-gh-account {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  font-size: var(--fs-3);
  color: var(--text);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--sp-5) var(--sp-6);
}
.git-gh-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: 0 0 auto;
  background: var(--fadetext);
}
.git-gh-dot.ok {
  background: var(--ok);
}
.git-gh-dot.off {
  background: var(--err);
}
.git-gh-src {
  font-size: var(--fs-1);
  color: var(--fadetext);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  padding: 0 var(--sp-4);
}
.git-gh-err {
  color: var(--err);
  font-size: var(--fs-2);
}
.git-gh-av {
  width: 18px;
  height: 18px;
  border-radius: var(--rd-3);
  margin-left: auto;
}
.git-gh-row {
  display: flex;
  gap: var(--sp-4);
}
.git-gh-row input {
  flex: 1;
  min-width: 0;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-4);
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-2);
  padding: var(--sp-4) var(--sp-5);
}
.git-gh-row input:focus {
  border-color: var(--accent);
}
.git-gh-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-height: 220px;
  overflow-y: auto;
}
.git-gh-repo {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--rd-3);
}
.git-gh-repo:hover {
  background: var(--bg-3);
}
.git-gh-repo-name {
  flex: 1;
  min-width: 0;
  font-family: var(--mono);
  font-size: var(--fs-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.git-gh-priv {
  font-size: var(--fs-1);
  color: var(--warn);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  padding: 0 var(--sp-4);
}

.git-log {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  flex: 0 1 auto;
  max-height: 300px;
  overflow-y: auto;
  margin-bottom: var(--sp-4);
}
.git-commit-row {
  display: grid;
  grid-template-columns: 62px 1fr auto;
  align-items: baseline;
  gap: var(--sp-3) var(--sp-6);
  padding: var(--sp-4) var(--sp-4);
  border-radius: var(--rd-3);
}
.git-commit-row:hover {
  background: var(--bg-3);
}
.git-hash {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--accent-2);
}
.git-subject {
  font-size: var(--fs-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.git-ref {
  font-size: var(--fs-1);
  font-weight: 700;
  color: var(--accent);
  background: rgba(var(--accent-rgb), .1);
  border: 1px solid rgba(var(--accent-rgb), .3);
  border-radius: var(--radius-pill);
  padding: var(--sp-1) var(--sp-5);
  justify-self: start;
}
.git-meta {
  grid-column: 2 / 4;
  font-size: var(--fs-2);
  color: var(--fadetext);
}

.git-out {
  flex: 1;
  min-height: 120px;
  overflow: auto;
  margin: 0;
  padding: var(--sp-6) var(--sp-7);
  background: var(--code-bg);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-4);
  font-family: var(--mono);
  font-size: var(--fs-2);
  line-height: 1.5;
  color: var(--code-text);
  white-space: pre-wrap;
  word-break: break-word;
}
.git-cmdrow {
  display: flex;
  gap: var(--sp-5);
  margin-top: var(--sp-5);
}
.git-cmdrow input {
  flex: 1;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-3);
  padding: var(--sp-5) var(--sp-7);
}
.git-cmdrow input:focus {
  border-color: var(--accent);
}

@media (max-width: 820px) {
  .git-body {
  grid-template-columns: 1fr;
}
  .git-side {
  border-right: 0;
  border-bottom: 1px solid var(--line);
}
}

.git-projects {
  margin-top: var(--sp-3);
}
.git-projects .git-select {
  width: 100%;
}
.git-project-status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  margin-top: var(--sp-5);
  min-height: 18px;
}
.git-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-1) var(--sp-5);
  border-radius: var(--radius-pill);
  font-size: var(--fs-2);
  line-height: 1.7;
  color: var(--muted);
  background: var(--bg-3);
  border: 1px solid var(--line);
  text-decoration: none;
  white-space: nowrap;
}
.git-badge.repo {
  color: var(--ok);
}
.git-badge.branch {
  font-family: var(--mono);
  color: var(--accent-2);
}
.git-badge.gh {
  color: var(--accent);
}
.git-badge.link {
  color: var(--accent);
}
.git-badge.link:hover {
  border-color: var(--accent);
}
.git-badge.pub {
  color: var(--ok);
  border-color: var(--ok);
  background: transparent;
}
.git-badge.priv {
  color: var(--warn);
  border-color: var(--warn);
  background: transparent;
}
.git-badge.none {
  color: var(--fadetext);
}

.git-gh-fresh {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  font-size: var(--fs-2);
  color: var(--muted);
  cursor: pointer;
  user-select: none;
}
.git-gh-fresh input {
  accent-color: var(--accent);
  margin: 0;
}
.ho-btn.danger {
  color: var(--err);
  border-color: var(--err);
}
.ho-btn.danger:hover {
  background: rgba(var(--err-rgb), .12);
}

/* ── working project picker ─────────────────────────────── */
.wd-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.wd-chip {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  max-width: 220px;
  padding: var(--sp-3) var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--bg-2);
  color: var(--muted);
  font-size: var(--fs-3);
  cursor: pointer;
  white-space: nowrap;
}
.wd-chip:hover {
  border-color: var(--accent);
  color: var(--text);
}
.wd-chip span {
  overflow: hidden;
  text-overflow: ellipsis;
}
.wd-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  width: 340px;
  max-height: 60vh;
  overflow: auto;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--sh-3);
  padding: var(--sp-5);
}
.wd-head {
  font-size: var(--fs-2);
  color: var(--muted);
  padding: var(--sp-2) var(--sp-3) var(--sp-5);
  display: flex;
  justify-content: space-between;
  gap: var(--sp-5);
}
.wd-sec {
  font-size: var(--fs-1);
  text-transform: uppercase;
  letter-spacing: var(--tr-4);
  color: var(--fadetext);
  padding: var(--sp-5) var(--sp-3) var(--sp-3);
  display: flex;
  justify-content: space-between;
  gap: var(--sp-5);
  overflow: hidden;
  white-space: nowrap;
}
.wd-root {
  font-family: var(--mono);
  color: var(--fadetext);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wd-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.wd-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-1);
  padding: var(--sp-5) var(--sp-6);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  text-align: left;
  width: 100%;
}
.wd-item:hover {
  background: var(--bg-3);
  border-color: var(--line);
}
.wd-item.active {
  border-color: var(--accent);
}
.wd-name {
  font-size: var(--fs-3);
}
.wd-dir {
  font-size: var(--fs-2);
  font-family: var(--mono);
  color: var(--fadetext);
}
.wd-empty {
  font-size: var(--fs-3);
  color: var(--muted);
  padding: var(--sp-5) var(--sp-3);
}

/* ── workspace folder browser (our own explorer, same on every OS) ── */
.fs-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: color-mix(in srgb, var(--shade) 55%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-11);
}
.fs-shell {
  width: min(560px, 100%);
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  box-shadow: var(--sh-3);
  overflow: hidden;
}
.fs-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
  padding: var(--sp-7) var(--sp-8);
  border-bottom: 1px solid var(--line);
}
.fs-title {
  font-size: var(--fs-4);
  font-weight: 600;
  color: var(--text);
}
.fs-bar {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-6) var(--sp-8);
}
.fs-bar .fs-path {
  flex: 1;
  min-width: 0;
  padding: var(--sp-4) var(--sp-6);
  font-size: var(--fs-3);
  font-family: var(--mono);
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.fs-bar .fs-path:focus {
  border-color: var(--accent);
}
.fs-quick {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  padding: 0 var(--sp-8) var(--sp-5);
}
.fs-quick-btn {
  padding: var(--sp-4) var(--sp-6);
  font-size: var(--fs-3);
  border-radius: var(--radius-pill);
  cursor: pointer;
  background: var(--bg-3);
  border: 1px solid var(--line-2);
  color: var(--text);
}
.fs-quick-btn:hover {
  border-color: var(--accent);
}
.fs-list {
  flex: 1;
  overflow: auto;
  padding: var(--sp-4) var(--sp-8);
  border-top: 1px solid var(--line);
}
.fs-row {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  width: 100%;
  text-align: left;
  cursor: pointer;
  padding: var(--sp-5) var(--sp-6);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
}
.fs-row:hover {
  background: var(--bg-3);
  border-color: var(--line);
}
.fs-ic {
  color: var(--accent-2);
  font-size: var(--fs-3);
  width: 12px;
}
.fs-nm {
  font-size: var(--fs-3);
  font-family: var(--mono);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fs-empty {
  font-size: var(--fs-3);
  color: var(--muted);
  padding: var(--sp-8) var(--sp-4);
}
.fs-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
  padding: var(--sp-7) var(--sp-8);
  border-top: 1px solid var(--line);
}
.fs-note {
  font-size: var(--fs-2);
  color: var(--fadetext);
}
.fs-foot-actions {
  display: flex;
  gap: var(--sp-4);
}

/* ── platform panels: tokens, MCP, memory, plugins ─────────────────── */
.tok-table {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.tok-row {
  display: flex;
  align-items: baseline;
  gap: var(--sp-5);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-3);
}
.tok-label {
  flex: 1;
  color: var(--muted);
}
.tok-value {
  font-family: var(--mono);
  color: var(--text);
  font-weight: 600;
}
.tok-hint {
  color: var(--fadetext);
  font-size: var(--fs-2);
}
.tok-hero {
  display: flex;
  align-items: baseline;
  gap: var(--sp-6);
  margin: var(--sp-9) 0 var(--sp-3);
  padding: var(--sp-8) var(--sp-9);
  border: 1px solid rgba(var(--accent-rgb), .35);
  border-radius: var(--radius);
  background: rgba(var(--accent-rgb), .08);
}
.tok-hero-num {
  font-size: var(--fs-9);
  font-weight: 700;
  color: var(--accent);
  font-family: var(--mono);
}
.tok-hero-label {
  color: var(--muted);
  font-size: var(--fs-3);
}

.mcp-list, .mem-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}
.mcp-card, .plug-card {
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  padding: var(--sp-6) var(--sp-7);
}
.mcp-head {
  flex-wrap: wrap;
}
.mcp-name {
  font-weight: 600;
  color: var(--text);
  font-size: var(--fs-3);
}
.mcp-meta {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--fadetext);
  margin: var(--sp-4) 0;
  word-break: break-all;
}
.mcp-actions {
  flex-wrap: wrap;
  margin-top: var(--sp-5);
}
.mcp-add {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  align-items: center;
  margin: var(--sp-4) 0;
}
.mcp-in {
  padding: var(--sp-4) var(--sp-6);
  font-size: var(--fs-3);
  font-family: var(--mono);
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  min-width: 160px;
}
.mcp-in.sm {
  min-width: 80px;
  width: 90px;
}
.mcp-in:focus {
  border-color: var(--accent);
}
.mcp-tools {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-height: 320px;
  overflow: auto;
}
.mcp-tool {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-4) var(--sp-4);
  font-size: var(--fs-3);
  border-bottom: 1px solid var(--line);
}
.mcp-tool-name {
  font-family: var(--mono);
  color: var(--text);
}
.mcp-tool-desc {
  color: var(--fadetext);
  font-size: var(--fs-2);
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mcp-audit {
  max-height: 220px;
  overflow: auto;
  font-family: var(--mono);
  font-size: var(--fs-2);
}
.audit-row {
  display: flex;
  gap: var(--sp-5);
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--line);
}
.audit-event {
  color: var(--accent-2);
  min-width: 150px;
}
.audit-detail {
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mem-row {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-5) var(--sp-4);
  font-size: var(--fs-3);
  border-bottom: 1px solid var(--line);
}
.mem-row.off {
  opacity: .45;
}
.mem-text {
  flex: 1;
  color: var(--text);
}
.mem-actions {
  display: flex;
  gap: var(--sp-3);
}
.mem-preview {
  max-height: 220px;
  overflow: auto;
  padding: var(--sp-6);
  margin: var(--sp-3) 0;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--muted);
  white-space: pre-wrap;
}
.mem-candidates {
  margin: var(--sp-6) 0;
  padding: var(--sp-6);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--bg-3);
}
.mem-cand {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  margin: var(--sp-4) 0;
}
.mem-cand .mcp-in {
  flex: 1;
}
.plug-extra {
  margin-top: var(--sp-5);
}

.badge.on {
  border-color: var(--accent);
  color: var(--accent);
}
.badge.danger-low {
  color: var(--muted);
}
.badge.danger-medium {
  color: var(--warn);
}
.badge.danger-high {
  color: var(--err);
}
.badge.conf-high {
  color: var(--accent);
}
.badge.conf-low {
  color: var(--fadetext);
}
.badge.state-running {
  border-color: var(--accent);
  color: var(--accent);
}
.badge.state-error {
  color: var(--err);
}
.ho-loading {
  padding: var(--sp-11);
  color: var(--muted);
  font-size: var(--fs-3);
}
.ho-empty.sm {
  font-size: var(--fs-3);
  color: var(--muted);
  padding: var(--sp-5) var(--sp-2);
}
.ho-err {
  color: var(--err);
  font-size: var(--fs-3);
  margin: var(--sp-3) 0;
}
.ho-sub.sm {
  font-size: var(--fs-2);
}
/* The turns a proposal came from, quoted under it. A person cannot approve a
   rule they cannot check, so this is the part that has to read as evidence:
   stacked, indented off the rule itself, turn number in the accent colour. */
.prop-ev {
  display: block;
  margin-top: var(--sp-3);
  padding-left: var(--sp-5);
  border-left: 1px solid var(--line-2);
  line-height: 1.55;
}
.prop-ev b {
  font-weight: 400;
  color: var(--accent-2);
}

/* ── profiles ──────────────────────────────────────────────────────── */
.prof-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.prof-row {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-5) var(--sp-6);
  font-size: var(--fs-3);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  background: var(--bg-3);
}
.prof-row.on {
  border-color: var(--accent);
}
.prof-name {
  font-weight: 600;
  color: var(--text);
  min-width: 84px;
}
.prof-desc {
  flex: 1;
  color: var(--fadetext);
  font-size: var(--fs-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── commit identity ──────────────────────────────────────────────── */
.git-identity {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  padding: var(--sp-3) 0 var(--sp-4);
}
.git-id-row {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-3) 0;
}
.git-id-label {
  font-size: var(--fs-3);
  color: var(--muted);
  white-space: nowrap;
}
.git-id-row .git-select {
  flex: 1;
  min-width: 0;
}
.git-id-custom {
  display: flex;
  gap: var(--sp-4);
  padding: var(--sp-2) 0 var(--sp-4);
}
.git-id-custom input {
  flex: 1;
  min-width: 0;
  padding: var(--sp-4) var(--sp-5);
  font-size: var(--fs-3);
  font-family: var(--mono);
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.git-id-custom input:focus {
  border-color: var(--accent);
}

/* ── saved folders for the clone target ───────────────────────────── */
.saved-folders {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  padding: var(--sp-3) 0 var(--sp-4);
}
.saved-folder {
  display: inline-flex;
  align-items: stretch;
  overflow: hidden;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  background: var(--bg-3);
}
.sf-pick {
  border: 0;
  background: transparent;
  color: var(--text);
  font-size: var(--fs-2);
  padding: var(--sp-3) var(--sp-6);
  cursor: pointer;
  font-family: var(--mono);
}
.sf-pick:hover {
  background: var(--bg);
}
.sf-del {
  border: 0;
  border-left: 1px solid var(--line);
  background: transparent;
  color: var(--fadetext);
  font-size: var(--fs-3);
  padding: var(--sp-3) var(--sp-5);
  cursor: pointer;
}
.sf-del:hover {
  color: var(--err);
}

/* ── delegation panel (right of main, left of assistant) ────────────── */
/* A normal flex sibling of the sidebar, main, and assistant columns. */
.dg-panel {
  flex: 0 0 auto;
  width: 0;
  height: 100vh;
  overflow: hidden;
  background: var(--bg-2);
  border-left: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  transition: width .16s ease;
}
.dg-panel.open {
  width: min(400px, 40vw);
}
.dg-card {
  border-radius: var(--radius-sm);
  padding: var(--sp-5) var(--sp-6);
}
.dg-card.done {
  opacity: .55;
}
.dg-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  flex: 0 0 auto;
  animation: dgPulse 1.2s ease-in-out infinite;
}
.dg-card.done .dg-dot {
  animation: none;
  background: var(--fadetext);
}
@keyframes dgPulse { 0%, 100% {
  opacity: 1;
} 50% {
  opacity: .35;
} }
.dg-label {
  font-size: var(--fs-3);
  font-weight: 600;
  color: var(--text);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dg-age {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--fadetext);
}
.dg-activity {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--muted);
  margin-top: var(--sp-3);
  word-break: break-word;
}
/* The run's budget, sent by the backend as data. It stays put while the
   activity line above it changes several times a second, because what you are
   waiting *for* is the thing you want to still be able to read. */
.dg-budget {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--fadetext);
  margin-top: var(--sp-3);
}
.dg-toggle {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--rd-3);
  color: var(--muted);
  transition: transform .12s ease;
}
.dg-toggle:hover {
  background: var(--bg-hover);
  color: var(--text);
  border-color: var(--accent);
}
.dg-toggle svg {
  transition: transform .12s ease;
}
.dg-trace {
  margin-top: var(--sp-5);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  max-height: 300px;
  overflow-y: auto;
}
.dg-reason {
  font-style: italic;
  color: var(--accent-2);
  font-size: var(--fs-3);
  line-height: 1.5;
  padding: var(--sp-4) var(--sp-5);
  background: rgba(var(--accent2-rgb), .08);
  border: 1px solid rgba(var(--accent2-rgb), .2);
  border-radius: var(--rd-3);
  white-space: pre-wrap;
  word-break: break-word;
}
.dg-tool {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--muted);
  padding: var(--sp-3) var(--sp-5);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--rd-3);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.dg-tool-err {
  border-color: var(--err);
}
.dg-tool-name {
  font-weight: 600;
  color: var(--text);
}
.dg-args, .dg-result {
  margin: 0;
  padding: var(--sp-4) var(--sp-5);
  background: var(--bg);
  border: 1px solid var(--line-2);
  border-radius: var(--rd-2);
  overflow-x: auto;
  font-size: var(--fs-2);
  line-height: 1.4;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 150px;
  overflow-y: auto;
}
.dg-text {
  font-size: var(--fs-3);
  line-height: 1.5;
  color: var(--text);
  padding: var(--sp-4) var(--sp-5);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--rd-3);
  white-space: pre-wrap;
  word-break: break-word;
}
.dg-notify {
  font-size: var(--fs-2);
  color: var(--fadetext);
  font-style: italic;
}
.dg-empty {
  font-size: var(--fs-3);
  color: var(--fadetext);
  font-style: italic;
  text-align: center;
  padding: var(--sp-7);
}

/* ── assistant panel ──────────────────────────────────────────────── */
/* A normal flex sibling of the sidebar and the main column, so it is aligned
   with them rather than floating over the top of the app. */
.as-panel {
  flex: 0 0 auto;
  width: 0;
  height: 100vh;
  overflow: hidden;
  background: var(--bg-2);
  border-left: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  transition: width .16s ease;
}
.as-panel.open {
  width: min(400px, 40vw);
  /* Shrinkable. The main column has a 540px floor because that is what the top bar
     needs, and with the Assistant panel and the delegation panel both open on a 1280
     window they demand 800px of a 1016px row. Someone has to give, and it is not the
     controls: measured, the bar's right-hand cluster was landing 42px outside the bar
     and painting over the panel beside it. Both panels take 238px each at that width,
     and 318 at 1440, which is the whole cost of keeping the controls on screen. */
  flex: 0 1 auto;
  min-width: 0;
}
.as-head {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-6) var(--sp-7);
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}
.as-title {
  font-size: var(--fs-3);
  font-weight: 600;
  color: var(--text);
}
.as-sub {
  flex: 1;
  font-size: var(--fs-2);
  color: var(--fadetext);
}
.as-context {
  padding: var(--sp-6) var(--sp-7);
  border-bottom: 1px solid var(--line);
}
.as-cost {
  display: flex;
  align-items: baseline;
  gap: var(--sp-5);
}
.as-cost-num {
  font-family: var(--mono);
  font-size: var(--fs-6);
  font-weight: 700;
  color: var(--accent);
}
.as-cost-label {
  font-size: var(--fs-2);
  color: var(--muted);
}
.as-break {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
  margin: var(--sp-4) 0;
  font-size: var(--fs-2);
  font-family: var(--mono);
  color: var(--fadetext);
}
.as-controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4) var(--sp-7);
  margin-top: var(--sp-4);
}
.as-group {
  flex: 0 0 100%;
  font-size: var(--fs-2);
  text-transform: uppercase;
  letter-spacing: var(--tr-4);
  color: var(--fadetext);
  margin-top: var(--sp-3);
}
.as-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4) var(--sp-7);
  flex: 0 0 100%;
}
.as-sel {
  flex: 1 1 30%;
  min-width: 0;
  font-size: var(--fs-2);
  padding: var(--sp-3) var(--sp-4);
}
.as-pickers {
  gap: var(--sp-4);
}
.as-chk, .as-turns {
  font-size: var(--fs-2);
}
.as-turns input {
  width: 54px;
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-2);
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.as-messages {
  flex: 1;
  overflow: auto;
  padding: var(--sp-6) var(--sp-7);
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}
.as-msg {
  font-size: var(--fs-3);
  line-height: 1.5;
}
/* The assistant's own tool calls, drawn with the main chat's classes so one
   stylesheet styles both. They sit above the answer because that is the order they
   happened in, and the panel is narrow, so the head drops its argument summary
   rather than truncating it into noise. */
.as-tools {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
}
.as-tools .tool-card {
  margin: 0;
}
.as-tools .tool-args {
  display: none;
}
.as-body {
  white-space: pre-wrap;
  word-break: break-word;
}
.as-msg.me .as-body {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--sp-5) var(--sp-6);
}
.as-msg.them .as-body {
  color: var(--text);
}
/* The assistant's answers render as markdown with the main chat's renderer.
   The `md` class drops pre-wrap, which plain text needs and rendered HTML must
   not have; everything else is the main chat's scale, tightened for the
   narrower panel. */
.as-body.md {
  white-space: normal;
}
.as-body.md p {
  margin: 0 0 var(--sp-5);
}
.as-body.md p:last-child {
  margin-bottom: 0;
}
.as-body.md h1, .as-body.md h2, .as-body.md h3, .as-body.md h4 {
  margin: var(--sp-6) 0 var(--sp-4);
  line-height: 1.35;
}
.as-body.md h1 {
  font-size: var(--fs-5);
}
.as-body.md h2 {
  font-size: var(--fs-5);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line);
}
.as-body.md h3 {
  font-size: var(--fs-4);
}
.as-body.md h4 {
  font-size: var(--fs-3);
}
.as-body.md ul, .as-body.md ol {
  margin: var(--sp-4) 0 var(--sp-5) var(--sp-10);
}
.as-body.md li {
  margin: var(--sp-2) 0;
}
.as-body.md li::marker {
  color: var(--accent);
}
.as-body.md a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid rgba(var(--accent-rgb), .4);
}
.as-body.md blockquote {
  border-left: 3px solid var(--accent);
  padding: var(--sp-2) var(--sp-6);
  color: var(--muted);
  margin: var(--sp-5) 0;
  background: rgba(var(--accent-rgb), .05);
  border-radius: 0 var(--rd-3) var(--rd-3) 0;
}
.as-body.md code {
  font-family: var(--mono);
  font-size: var(--fs-3);
  background: rgba(var(--accent2-rgb), .08);
  border: 1px solid rgba(var(--accent2-rgb), .2);
  border-radius: var(--rd-3);
  padding: var(--sp-1) var(--sp-3);
}
.as-body.md table {
  border-collapse: separate;
  border-spacing: 0;
  margin: var(--sp-5) 0;
  font-size: var(--fs-3);
  display: block;
  overflow-x: auto;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
}
.as-body.md th, .as-body.md td {
  border-bottom: 1px solid var(--line);
  padding: var(--sp-3) var(--sp-6);
  text-align: left;
}
.as-body.md th {
  background: var(--bg-3);
  font-weight: 600;
  font-size: var(--fs-2);
  white-space: nowrap;
}
.as-body.md tr:last-child td {
  border-bottom: 0;
}
.as-body.md .code-block {
  margin: var(--sp-5) 0;
}
.as-body.md .code-block pre {
  padding: var(--sp-6) var(--sp-7);
}
.as-body.md .code-block code {
  font-size: var(--fs-3);
}
.as-empty {
  font-size: var(--fs-3);
  color: var(--muted);
  line-height: 1.6;
}
.as-note {
  font-size: var(--fs-2);
  color: var(--fadetext);
  margin-top: var(--sp-4);
}
.as-input {
  display: flex;
  gap: var(--sp-4);
  padding: var(--sp-6) var(--sp-7);
  border-top: 1px solid var(--line);
  flex: 0 0 auto;
}
.as-input textarea {
  flex: 1;
  min-width: 0;
  resize: none;
  padding: var(--sp-5) var(--sp-6);
  font-size: var(--fs-3);
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-family: inherit;
}
.as-input textarea:focus {
  border-color: var(--accent);
}
.as-send {
  border: 0;
  background: transparent;
  color: var(--accent);
  cursor: pointer;
  padding: var(--sp-3) var(--sp-4);
}
.as-send:disabled {
  opacity: .4;
  cursor: default;
}
.icon-btn.on {
  color: var(--accent);
}

/* ── the autonomous run: Goal, switch, budget ─────────────────────── */
/* The Goal outlives the conversation, so it is not styled as a message: no
   bubble, no tail, an inset block of its own. It is chrome of the session, and
   it sits above the thread rather than in it so "clear" cannot take it away. */
.as-run {
  flex: 0 0 auto;
  padding: var(--sp-6) var(--sp-7) var(--sp-6);
  border-bottom: 1px solid var(--line);
  background: var(--bg-2);
}
.as-run textarea {
  display: block;
  width: 100%;
  box-sizing: border-box;
  min-height: 42px;
  resize: vertical;
  padding: var(--sp-5) var(--sp-6);
  font-size: var(--fs-3);
  line-height: 1.45;
  font-family: inherit;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.as-run textarea:focus {
  border-color: var(--accent);
}
.as-run textarea::placeholder {
  color: var(--fadetext);
}
.as-run-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-5) var(--sp-6);
  margin-top: var(--sp-5);
}
/* The budget line is the only place a run says what it is doing. It gets the
   width the switch and reset do not need, and it truncates rather than
   wrapping - a run that pushes the strip apart on every cycle is worse than
   one that clips a long reason. */
.as-run-budget {
  flex: 1 1 90px;
  min-width: 0;
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--fadetext);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.as-run-budget.on {
  color: var(--accent);
}

/* ── per-message actions ──────────────────────────────────────────── */
/* Quiet until asked for. A thread of answers each wearing two buttons is noise;
   the row reveals them on hover, and focus-within covers the keyboard. Touch
   has no hover, so there they are simply always on. */
.as-acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-top: var(--sp-4);
  opacity: .4;
}
.as-msg:hover .as-acts, .as-acts:focus-within {
  opacity: 1;
}
@media (hover: none) { .as-acts {
  opacity: 1;
} }
.as-acts [data-del]:hover {
  color: var(--err);
  border-color: var(--err);
}

/* ── advanced switch in the settings header ───────────────────────── */
.ho-tabs {
  flex-wrap: wrap;
}
.adv-switch {
  margin-left: auto;
  align-self: center;
  font-size: var(--fs-2);
  color: var(--fadetext);
  white-space: nowrap;
  padding-left: var(--sp-5);
}
.adv-switch.on {
  color: var(--accent);
}
.adv-switch input {
  margin-right: var(--sp-3);
}

/* ── the prompt inventory (Settings > Prompts) ──────────────────────── */
.pc-group {
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  margin-bottom: var(--sp-5);
}
.pc-group > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-5);
  padding: var(--sp-6) var(--sp-7);
  cursor: pointer;
  list-style: none;
  font-size: var(--fs-uirow);
  color: var(--text);
  transition: color var(--dur-2) var(--ease-out);
}
.pc-group > summary::-webkit-details-marker { display: none; }
.pc-group > summary::before {
  content: "▸";
  color: var(--fadetext);
  font-size: var(--fs-2);
}
.pc-group[open] > summary::before { content: "▾"; }
.pc-group > summary:hover { color: var(--accent); }
.pc-item {
  border-top: 1px solid var(--line);
  padding: var(--sp-6) var(--sp-7);
}
.pc-name {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-5);
  font-size: var(--fs-3);
  color: var(--text);
}
.pc-text {
  margin: var(--sp-5) 0 0;
  padding: var(--sp-6) var(--sp-7);
  background: var(--code-bg);
  color: var(--code-text);
  border-radius: var(--radius-sm);
  font-family: var(--mono);
  font-size: var(--fs-2);
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 22em;
  overflow-y: auto;
}

/* ── snapshot timeline ─────────────────────────────────────────────── */
.snap-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}
.snap-card {
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  padding: var(--sp-6) var(--sp-7);
}
.snap-time {
  font-family: var(--mono);
  font-size: var(--fs-3);
  color: var(--text);
  font-weight: 600;
}
.snap-files {
  font-family: var(--mono);
  font-size: var(--fs-2);
  color: var(--fadetext);
  margin: var(--sp-4) 0;
  word-break: break-all;
}
.snap-extra {
  margin-top: var(--sp-5);
}
.compare-group {
  margin: var(--sp-4) 0;
}
.compare-label {
  font-size: var(--fs-2);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: var(--tr-4);
}
.compare-file {
  font-family: var(--mono);
  font-size: var(--fs-2);
  padding: var(--sp-1) 0 var(--sp-1) var(--sp-6);
}
.compare-group.chg .compare-file {
  color: var(--warn);
}
.compare-group.add .compare-file {
  color: var(--accent);
}
.compare-group.del .compare-file {
  color: var(--err);
}

/* ════════════════════ CONTROL STATES ════════════════════
   Hover was the only state this interface had. A control that cannot show being
   pressed or being unavailable is a control the person has to guess about, so the
   three missing states are declared once, for every button class, rather than
   per-component -- which is also why they sit together instead of scattered. */

/* Pressed: a 1px drop and a contact shadow. Not a scale -- scaling a full-width
   button makes the whole surface look like it moved. */
.send-btn:active:not(:disabled), .new-chat-btn:active:not(:disabled),
.icon-btn:active:not(:disabled), .ho-btn:active:not(:disabled),
.copy-btn:active:not(:disabled), .term-btn:active:not(:disabled),
.fs-quick-btn:active:not(:disabled), .git-file-btn:active:not(:disabled),
.jump-btn:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: inset 0 1px 2px color-mix(in srgb, var(--shade) 32%, transparent);
}

/* Unavailable: dimmed, and the cursor says so. The hover treatment is withdrawn
   rather than left running, because a button that still lights up under the
   pointer is a button that looks like it will do something. */
.send-btn:disabled, .new-chat-btn:disabled, .icon-btn:disabled,
.ho-btn:disabled, .copy-btn:disabled, .term-btn:disabled,
.fs-quick-btn:disabled, .git-file-btn:disabled, .jump-btn:disabled,
.seg button:disabled {
  opacity: .42;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}
/* ...including the primary button. An earlier draft kept the accent on a disabled
   Send, on the argument that unavailable is a state rather than an absence. It is
   also a second surface painting --on-accent, and the simpler rule is the truer
   one: a control that will not act does not respond to the pointer at all, and
   "will not act" is worth saying in every button's voice, not only the quiet ones. */
.send-btn:disabled:hover, .new-chat-btn:disabled:hover, .icon-btn:disabled:hover,
.ho-btn:disabled:hover, .copy-btn:disabled:hover, .term-btn:disabled:hover,
.fs-quick-btn:disabled:hover, .git-file-btn:disabled:hover,
.jump-btn:disabled:hover {
  background: var(--bg-3);
  color: var(--fadetext);
  border-color: var(--line);
  box-shadow: none;
}

/* ════════════════════ MOTION ════════════════════
   Durations and curves come from the token ladder in :root. Nothing here is
   decoration and nothing here is an entrance: this is an Operate surface, so
   motion reports a state change and gets out of the way (operate.md bans both
   decorative motion and orchestrated page-load sequences here). Exponential
   ease-out throughout, because a decelerating element reads as arriving.
   The reduced-motion blanket at the end of this file switches all of it off. */

/* Controls: the press and the hover are the same property moving, so one
   transition covers both. */
.ho-btn, .send-btn, .icon-btn, .jump-btn, .new-chat-btn, .copy-btn, .term-btn,
.git-file-btn, .fs-quick-btn, .seg button, .ho-tab, .reason-toggle, .dg-toggle,
.msg-edit {
  transition: background-color var(--dur-2) var(--ease-out),
              border-color var(--dur-2) var(--ease-out),
              color var(--dur-2) var(--ease-out),
              opacity var(--dur-2) var(--ease-out),
              transform var(--dur-1) var(--ease-out),
              box-shadow var(--dur-1) var(--ease-out);
}

/* Rows and list items: background and rule only. A row that slides or scales on
   hover is asking to be looked at, and these are looked through. */
.session-item, .tool-row, .model-row, .mem-row, .prof-row, .audit-row, .snap-card,
.git-commit-row, .git-gh-row, .git-id-row, .wd-item, .fs-row, .ext-row, .tok-row,
.task-strip-item, .attach-row, .as-run-row, .ctl-row {
  transition: background-color var(--dur-2) var(--ease-out),
              border-color var(--dur-2) var(--ease-out),
              color var(--dur-2) var(--ease-out);
}

/* Cards take the slower structural duration: they change shape or open, not just
   colour, and a shape change at 150ms reads as a flicker. */
.tool-card, .theme-card, .dg-card, .card, .ctl-card, .prov-card, .skill-card,
.mcp-card, .plug-card, .card-head {
  transition: background-color var(--dur-3) var(--ease-soft),
              border-color var(--dur-3) var(--ease-soft),
              box-shadow var(--dur-3) var(--ease-soft);
}

/* Chips and badges. */
.att-chip, .wd-chip, .toolset-chip, .chip, .badge, .tool-badge {
  transition: background-color var(--dur-2) var(--ease-out),
              border-color var(--dur-2) var(--ease-out),
              color var(--dur-2) var(--ease-out);
}

/* Fields: the focus ring arriving is the state being reported, so the border and
   the shadow both move. */
input, textarea, .ctl-select, .as-input, .rename-input, .mcp-in {
  transition: background-color var(--dur-2) var(--ease-out),
              border-color var(--dur-2) var(--ease-out),
              box-shadow var(--dur-2) var(--ease-out);
}

/* Links and inline affordances. */
.link, .msg-content a, .as-body.md a {
  transition: color var(--dur-1) var(--ease-out),
              background-color var(--dur-1) var(--ease-out);
}


/* ── reduced motion ───────────────────────────────────────────────────────
   the deleted plan, item 5: "Respect prefers-reduced-motion: every animation has an off
   state." One blanket rule at the end, rather than a `@media` bolted onto each
   animated selector - the per-selector version is the one that rots, and it had
   already rotted here: the session dot's pulse had an off state and the token
   meter (`tokPulse`), the delegation dot (`dgPulse`) and every width/opacity/
   transform transition did not.

   `.01ms` + `iteration-count: 1` instead of `animation: none` so an animation
   still *ends*: anything waiting on animationend/transitionend keeps working,
   it just happens instantly. Nothing in `static/` listens for those today - the
   idiom is chosen so this stays correct when something does. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
  animation-duration: .01ms !important;
  animation-delay: 0s !important;
  animation-iteration-count: 1 !important;
  transition-duration: .01ms !important;
  transition-delay: 0s !important;
  scroll-behavior: auto !important;
}
}
