/* ============================================================
   TOKENS — every colour used anywhere below is defined here,
   once, for light and dark. Nothing outside this block may use
   a raw hex value.

   The polish pass (2026-09-24, visual-review.md §2): one cool
   neutral ramp (no beige), one accent — blue — reserved for things
   you can click (primary button, link, focus ring, active nav, the
   brand mark), and one colour per state shared by every surface:
   amber needs a person, blue working, green done, red failed, grey
   idle. The --color-attention/-positive/-negative names are the
   same colours as --state-needs/-done/-failing, kept as names so
   no rule below had to change. Coloured text is only ever a state
   word or a callout's title — a paragraph is always --color-text.
   Every text/background pair is AA (4.5:1) in both themes; the
   table is in docs/visual-theme-contrast.md (written in the theme's
   last task).
   ============================================================ */
:root {
  color-scheme: light dark;

  /* surfaces */
  --color-bg: #f5f6f8;
  --color-surface: #ffffff;
  --color-surface-sunken: #eff1f4;
  --color-sidebar: #f5f6f8;

  /* borders: dividers and panel edges; things you operate */
  --color-border: #dfe2e8;
  --color-border-strong: #c9cdd6;
  /* the edge of a control you operate (inputs, selects, secondary buttons):
     the lightest value at 3:1 on every surface a control sits on (WCAG
     1.4.11) — surface, bg, sunken and each state's soft fill */
  --color-border-control: #858b99;
  --color-border-control-hover: #656b7a;

  /* text */
  --color-text: #0e1015;
  --color-text-secondary: #4a5160;
  --color-text-tertiary: #5f6675;

  /* chart series (usage charts): a categorical set that is not the state
     palette — green, red and amber mean done, failed and needs-you everywhere
     else. Fixed order; >= 3:1 on the surface; cached input is chart-1 at 38% */
  --chart-1: #4f46e5; --chart-2: #0d9488; --chart-3: #b7791f;
  --chart-4: #be185d; --chart-5: #0369a1; --chart-6: #4d7c0f;
  --chart-others: #c9cdd6; --chart-unattributed: #8a90a0;
  --chart-weekend: rgba(14, 16, 21, 0.035);

  /* accent — blue, interaction only */
  --color-accent: #2f4bf5;
  --color-accent-hover: #2338b8;
  --color-accent-soft: #eef1fe;
  /* a filled surface in the accent (primary button, launcher, send, poll bar):
     the same as the accent in light; in dark a deeper blue that carries white */
  --color-accent-solid: #2f4bf5;
  --color-on-accent-solid: #ffffff;
  --color-accent-solid-hover: #2338b8;

  /* state — one colour each, with a soft twin for a tinted surface */
  --state-needs: #a14f05;
  --state-needs-soft: #fdf3e4;
  --state-working: #1d5fc4;
  --state-working-soft: #e8f0fc;
  --state-done: #17753c;
  --state-done-soft: #e8f5ec;
  --state-failing: #b42318;
  --state-failing-soft: #fdeceb;
  --state-idle: #5f6675;
  --state-idle-soft: #eff1f4;

  /* Area hues (visual theme §1): where am I. Only on sidebar icons, icon
     chips, a card's accent details and the map's selected path — never on
     buttons, chips, badges, prose, links or anything carrying state. No
     area-hued text on a -soft fill (people-on-soft is 4.47:1). */
  --area-runs: #4f46e5;          --area-runs-soft: #eef2ff;
  --area-agents: #7c3aed;        --area-agents-soft: #f5f1ff;
  --area-reviews: #0f766e;       --area-reviews-soft: #e6f3f0;
  /* lime, 58deg from --state-needs's amber (design-fixes:38/39) */
  --area-commits: #4d7c0f;       --area-commits-soft: #f0f7e4;
  --area-integrations: #be185d;  --area-integrations-soft: #fdeef5;
  --area-models: #0369a1;        --area-models-soft: #e9f4fb;
  --area-people: #15803d;        --area-people-soft: #e8f5ec;
  --area-settings: #5a6070;      --area-settings-soft: #e2e5eb;
  /* the three doors (Home): the same accents as the areas they open */
  --door-agents: var(--area-agents);
  --door-reviews: var(--area-reviews);
  --door-prds: var(--area-runs);
  /* Person hues (§2, plan R7): an avatar's fill under white initials,
     picked by hashing the account id; the same in both themes. */
  /* person-4 (plum) and person-7 (olive) moved out of the needs/failing
     hue families (design-fixes:38/39) */
  --person-1: #0e7490; --person-2: #7c3aed; --person-3: #be185d; --person-4: #86198f;
  --person-5: #15803d; --person-6: #4338ca; --person-7: #3f6212; --person-8: #475569;
  --on-person: #ffffff;
  /* Severity (§3, plan R8): the findings bar, Critical to Minor. Moderate
     was #eab308 (R8): 1.92:1 on the surface, under spec §6's 3:1 floor for
     a graphic (TR-7, the whole-branch review) — darkened here. Retuned
     again (design-fixes:69, reviews:140/152) into a monotonic ramp: each
     step's contrast on the surface is strictly below the more severe
     step's, so Moderate is never darker than Major. */
  --sev-critical: var(--state-failing);
  --sev-major: #c2410c;
  --sev-moderate: #b7791f;
  /* its own grey, not --state-idle (design-fixes:69, reviews:140/152) */
  --sev-minor: #8a90a0;
  /* the older names, as the same colours */
  --color-neutral-bg: #eff1f4;
  --color-neutral-fg: #4a5160;
  --color-neutral-border: #dfe2e8;

  --color-attention-bg: var(--state-needs-soft);
  --color-attention-fg: var(--state-needs);
  --color-attention-border: #f1cf9a;

  --color-positive-bg: var(--state-done-soft);
  --color-positive-fg: var(--state-done);
  --color-positive-border: #b3dcc0;

  --color-negative-bg: var(--state-failing-soft);
  --color-negative-fg: var(--state-failing);
  --color-negative-border: #f4c1bc;

  /* diff */
  --color-diff-add-bg: #e8f5ec;
  --color-diff-add-fg: #17753c;
  --color-diff-del-bg: #fdeceb;
  --color-diff-del-fg: #b42318;

  /* elevation: panels are flat — the border does the work */
  --shadow-panel: none;
  --shadow-control: 0 1px 0 rgba(14, 16, 21, 0.04);
  --shadow-pop: 0 4px 16px rgba(14, 16, 21, 0.08), 0 1px 2px rgba(14, 16, 21, 0.06);
  /* the chat popup and its launcher: a card that floats over the page */
  --shadow-float: 0 12px 32px rgba(14, 16, 21, 0.14), 0 2px 6px rgba(14, 16, 21, 0.08);

  /* type — the website's three faces (2026-10-06, portal-site-theme):
     IBM Plex Sans for everything, Space Grotesk for page titles, section
     headings and the brand, IBM Plex Mono for code and small labels; all
     self-hosted below, each with a real system fallback */
  --font-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "Space Grotesk", "IBM Plex Sans", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  /* the PRD page's headings and lead (PRD V1 §8, the canvas): a system
     serif, nothing to download */
  --font-serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;

  /* short aliases (the 2026-09-15 design doc's names) */
  --surface: var(--color-surface);
  --ink: var(--color-text);
  --muted: var(--color-text-secondary);
  --line: var(--color-border);

  /* type scale (base 14px): size / line-height */
  --text-2xs: 11px;   /* 16 — the sidebar group label only */
  --text-xs: 12px;    /* 16 — table heads, badges, hints, crumbs */
  --text-sm: 13px;    /* 20 — secondary text, labels, buttons */
  --text-md: 14px;    /* 20 (body 22) — body, cells, inputs */
  --text-lg: 16px;    /* 24 — panel title, markdown h2 */
  --text-xl: 20px;    /* 28 — section heading */
  --text-2xl: 24px;   /* 32 — section title */
  --text-3xl: 30px;   /* 36 — page title */
  --text-prose: 15px; /* 26 — long-form reading */

  /* spacing — a 4px scale */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;

  --control-height: 36px;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 20px;    /* the chat popup only */
  --radius-pill: 999px; /* buttons, chips, the chat launcher and composer */
  --sidebar-width: 224px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #0e1015;
    --color-surface: #171a21;
    --color-surface-sunken: #1d212a;
    --color-sidebar: #0e1015;

    --color-border: #2a2f3a;
    --color-border-strong: #3a3f4b;
    --color-border-control: #6b7182;
    --color-border-control-hover: #8a90a0;

    --color-text: #e7e9ee;
    --color-text-secondary: #a3a9b6;
    --color-text-tertiary: #8d94a3;

    --chart-1: #7b78ee; --chart-2: #1f9c88; --chart-3: #b8862e;
    --chart-4: #e85a98; --chart-5: #3b8fc7; --chart-6: #6f9a2a;
    --chart-others: #3a3f4b; --chart-unattributed: #6b7182;
    --chart-weekend: rgba(255, 255, 255, 0.04);

    --color-accent: #8fa2ff;
    --color-accent-hover: #b3c0ff;
    --color-accent-soft: #1c2440;
    --color-accent-solid: #3d5afe;
    --color-on-accent-solid: #ffffff;
    --color-accent-solid-hover: #4964ff;

    --state-needs: #f2b04e;
    --state-needs-soft: #2e2310;
    --state-working: #8db8f5;
    --state-working-soft: #16263b;
    --state-done: #7ccf98;
    --state-done-soft: #14301e;
    --state-failing: #f39189;
    --state-failing-soft: #3a1c1a;
    --state-idle: #98a0ae;
    --state-idle-soft: #1f232c;

    --area-runs: #8d8bf5;          --area-runs-soft: #20233f;
    --area-agents: #a78bfa;        --area-agents-soft: #2a2145;
    --area-reviews: #3dbfa9;       --area-reviews-soft: #0f2b27;
    --area-commits: #a3c75a;       --area-commits-soft: #1e2a12;
    --area-integrations: #ef6aa5;  --area-integrations-soft: #3a1527;
    --area-models: #67b3e0;        --area-models-soft: #12283a;
    --area-people: #6fbe8c;        --area-people-soft: #14301e;
    --area-settings: #98a0ae;      --area-settings-soft: #262a34;
    --sev-critical: var(--state-failing);
    /* retuned into the monotonic ramp (design-fixes:69, reviews:140/152):
       each step reads with less contrast on the surface than the one
       before it, so Moderate never darker (more visible) than Major. */
    --sev-major: #e8843a;
    --sev-moderate: #a88a2a;
    /* its own grey, not --state-idle (design-fixes:69, reviews:140/152) */
    --sev-minor: #6b7182;

    --color-neutral-bg: #1d212a;
    --color-neutral-fg: #c9cdd6;
    --color-neutral-border: #2a2f3a;

    --color-attention-border: #5a4418;
    --color-positive-border: #22492f;
    --color-negative-border: #5e2629;

    --color-diff-add-bg: #14301e;
    --color-diff-add-fg: #7ccf98;
    --color-diff-del-bg: #3a1c1a;
    --color-diff-del-fg: #f39189;

    --shadow-panel: none;
    --shadow-control: 0 1px 0 rgba(0, 0, 0, 0.3);
    --shadow-pop: 0 8px 24px rgba(0, 0, 0, 0.5);
    --shadow-float: 0 16px 40px rgba(0, 0, 0, 0.6), 0 2px 8px rgba(0, 0, 0, 0.4);
  }

  /* a hair-thin edge so an avatar's hue doesn't melt into a dark card
     (shell:55) — a rule, not a token, since it is dark-only. */
  .avatar { box-shadow: 0 0 0 1px var(--color-border-strong); }
}

/* ============================================================
   TYPE — self-hosted, no CDN, no external fetch at runtime. Every woff2
   below lives in assets/fonts/ (embedded, served hashed like portal.css
   itself); each family's licence sits beside it (OFL-ibm-plex-sans.txt,
   OFL-space-grotesk.txt, OFL-ibm-plex-mono.txt, all SIL OFL 1.1). The hashed filename
   in each url() is computed offline the same way assets.go computes it at
   startup (sha256 of the file's bytes, first 10 hex chars); a case in
   assets_test.go checks every url() still names the embedded file's hash.
   Shipped weights: Plex Sans 400/500/600, Space Grotesk 600, Plex Mono
   400/500 — no rule below asks for any other.
   ============================================================ */
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/ibm-plex-sans-400.3b646991d3.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/ibm-plex-sans-500.0717336fb3.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/ibm-plex-sans-600.8960851d69.woff2") format("woff2");
}
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/space-grotesk-600.685bbbf69f.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/ibm-plex-mono-400.08949f728d.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/ibm-plex-mono-500.01d2854474.woff2") format("woff2");
}

/* ============================================================
   RESET + BASE
   ============================================================ */
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font: 400 var(--text-md)/22px var(--font-sans);
  font-feature-settings: "cv11" 0, "ss01" 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* A long unbroken token — a URL, a git ref, a file path — must never be
     the thing that pushes the page body wider than the viewport. Anything
     that wants its own horizontal scroll (tables, the diff, code blocks)
     opts into it explicitly via its own overflow-x: auto. */
  overflow-wrap: break-word;
}
a { color: var(--color-accent); text-decoration: none; }
a:hover { text-decoration: underline; }
/* A link in running text carries an underline too: in dark mode the accent is
   only 1.97:1 against body text (WCAG 1.4.1 needs 3:1 or a non-colour cue).
   Navigation, chips, badges and buttons keep their own look. */
:where(p, li, dd, td, .field-hint, .markdown-body) a:not(.btn):not(.tab):not(.badge):not(.nav-link):not(.brand):not(.home-row-title):not(.row-title):not(.type-card):not(.queue-chip):not(.home-filter) {
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px;
}
.settings-nav a, .crumbs a, .home-row-title, .row-title, .nav-desktop a, .chip-row a, .review-tabs a, .repo-view-links a { text-decoration: none; }
code, pre, kbd, samp { font-family: var(--font-mono); font-size: 0.9em; }
pre code { font-size: 1em; }
h1, h2, h3, h4, h5 { margin: 0; font-weight: 600; line-height: 1.3; letter-spacing: -0.005em; }
h1 { font-family: var(--font-display); font-size: var(--text-2xl); line-height: 32px; letter-spacing: -0.025em; overflow-wrap: anywhere; }
h2 { font-size: var(--text-lg); line-height: 24px; }
h3, h4, h5 { font-size: var(--text-md); line-height: 20px; }
p { margin: 0 0 var(--space-3); }
strong, b { font-weight: 600; }
p:last-child { margin-bottom: 0; }

.num, .date, time { font-variant-numeric: tabular-nums; }

/* ============================================================
   SHELL — persistent sidebar + main column
   ============================================================ */
.shell {
  display: grid;
  grid-template-columns: var(--sidebar-width) 1fr;
  min-height: 100vh;
}
.sidebar {
  min-width: 0;
  background: var(--color-sidebar);
  border-right: 1px solid var(--color-border);
  padding: var(--space-4) var(--space-3);
  padding-left: calc(var(--space-3) + env(safe-area-inset-left, 0px));
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 32px;
  padding: var(--space-1) var(--space-2);
  color: var(--color-text);
}
.brand:hover { text-decoration: none; }
.brand svg { flex: none; }
/* The website's mark (2026-10-06): an ink tile with three bars, the middle
   one in the accent. */
.brand-mark-bg { fill: var(--color-text); }
.brand-mark { fill: var(--color-bg); }
.brand-mark-accent { fill: var(--color-accent); }
.brand-name { font-family: var(--font-display); font-weight: 600; font-size: 18px; letter-spacing: -0.02em; }
/* J2.7: on a page taller than the viewport the sidebar keeps its account
   block in view: sticky with its own scroll. Desktop only — the ≤860px rule
   below makes the sidebar a sticky top bar of its own. */
@media (min-width: 861px) {
  /* border-box at the dynamic viewport height: the padding no longer
     makes it taller than the screen, so it sits flush at the top (VD-24). */
  .sidebar { position: sticky; top: 0; box-sizing: border-box; height: 100dvh; overflow-y: auto; }
}
.nav-group { display: flex; flex-direction: column; gap: 2px; }

/* Small keys and labels: sentence case, small and quiet. */
.meta-label,
dl.kv dt {
  font-size: var(--text-xs);
  line-height: 16px;
  font-weight: 500;
  color: var(--color-text-tertiary);
}
.nav-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 30px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  font-size: var(--text-md);
  line-height: 20px;
  font-weight: 500;
}
.nav-icon { flex: none; width: 16px; height: 16px; color: var(--color-text-tertiary); }
/* Sidebar icons in their area hue (visual theme §1, plan R10) — an item
   with no area (account, sign out) keeps the plain tertiary color above. */
.nav-icon.area-runs { color: var(--area-runs); }
.nav-icon.area-agents { color: var(--area-agents); }
.nav-icon.area-reviews { color: var(--area-reviews); }
.nav-icon.area-commits { color: var(--area-commits); }
.nav-icon.area-integrations { color: var(--area-integrations); }
.nav-icon.area-models { color: var(--area-models); }
.nav-icon.area-people { color: var(--area-people); }
.nav-icon.area-settings { color: var(--area-settings); }
.nav-link:hover { background: color-mix(in srgb, var(--color-text) 5%, transparent); text-decoration: none; color: var(--color-text); }
/* TR-12 (whole-branch review): scoped like the active rule below, or this
   (two classes plus :hover, specificity 0,3,0) outranks .nav-icon.area-*
   (0,2,0) and turns any hovered area icon the plain secondary grey. */
.nav-link:hover .nav-icon:not([class*="area-"]) { color: var(--color-text-secondary); }
/* The section a page belongs to is set server-side (<body data-nav="...">):
   a neutral fill and a 2px teal tick, not a teal block. */
body[data-nav="home"] .nav-home,
body[data-nav="agents"] .nav-agents,
body[data-nav="reviews"] .nav-reviews,
body[data-nav="account"] .nav-account-link,
body[data-nav="prds"] .nav-prds,
body[data-nav="integrations"] .nav-settings,
body[data-nav="models"] .nav-settings,
body[data-nav="people"] .nav-settings,
body[data-nav="settings"] .nav-settings {
  background: color-mix(in srgb, var(--color-text) 7%, transparent);
  color: var(--color-text);
}
/* An active item's icon keeps its area hue (plan R10) — only an icon with
   no area (account, sign out) turns accent teal when active. */
body[data-nav="home"] .nav-home .nav-icon:not([class*="area-"]),
body[data-nav="agents"] .nav-agents .nav-icon:not([class*="area-"]),
body[data-nav="reviews"] .nav-reviews .nav-icon:not([class*="area-"]),
body[data-nav="account"] .nav-account-link .nav-icon:not([class*="area-"]),
body[data-nav="prds"] .nav-prds .nav-icon:not([class*="area-"]),
body[data-nav="integrations"] .nav-settings .nav-icon:not([class*="area-"]),
body[data-nav="models"] .nav-settings .nav-icon:not([class*="area-"]),
body[data-nav="people"] .nav-settings .nav-icon:not([class*="area-"]),
body[data-nav="settings"] .nav-settings .nav-icon:not([class*="area-"]) { color: var(--color-accent); }
body[data-nav="home"] .nav-home::before,
body[data-nav="agents"] .nav-agents::before,
body[data-nav="reviews"] .nav-reviews::before,
body[data-nav="account"] .nav-account-link::before,
body[data-nav="prds"] .nav-prds::before,
body[data-nav="integrations"] .nav-settings::before,
body[data-nav="models"] .nav-settings::before,
body[data-nav="people"] .nav-settings::before,
body[data-nav="settings"] .nav-settings::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 2px;
  border-radius: 1px;
  background: var(--color-accent);
}
.nav-account { margin-top: auto; border-top: 1px solid var(--color-border); padding-top: var(--space-3); }
.nav-person { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-2) var(--space-2); min-width: 0; }
/* The sidebar's own avatar size (the shared .avatar rule, Task 3, is 24px). */
.nav-person .avatar { width: 28px; height: 28px; font-size: var(--text-2xs); }
.nav-person-text { display: flex; flex-direction: column; min-width: 0; line-height: 16px; }
.nav-account-name { font-size: var(--text-sm); font-weight: 500; color: var(--color-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-org-name { font-size: var(--text-xs); color: var(--color-text-tertiary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-account .nav-link { font-size: var(--text-sm); min-height: 28px; }
.nav-signout { width: 100%; text-align: left; border: none; background: none; cursor: pointer; font: inherit; font-size: var(--text-sm); font-weight: 500; }
.narrow-form, form.stack { max-width: 40rem; }
.inline-form { display: flex; gap: var(--space-3); align-items: flex-start; flex-wrap: wrap; }
.inline-form .field { margin-bottom: 0; flex: 1; min-width: 12rem; }
/* A field with a hint below it must not push its neighbour button down:
   the row aligns to flex-start and the button takes the label's height
   (20px line + 4px gap) as its top margin, lining up with the input. */
.inline-form .btn { margin-top: 24px; }
/* Three short fields on one row (a model's caps). */
.field-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); }
.field-row .field { margin-bottom: 0; }
/* Two paired fields on one row (a connection's header name and value). */
.field-row-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* The New agent page's type cards: three across from 900px, one column
   below (VD-11). */
.type-cards { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
@media (min-width: 900px) {
  .type-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.type-card { display: block; text-decoration: none; color: inherit; transition: border-color 0.15s ease; }
.type-card:hover, .type-card:focus-visible { border-color: var(--color-border-strong, var(--color-text-tertiary)); }
.type-card .type-card-next { font-size: var(--text-sm); font-weight: 500; margin-top: var(--space-2); }
.type-card-disabled { opacity: 0.6; }
dl.kv { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-2) var(--space-5); margin: 0 0 var(--space-3); font-size: var(--text-md); }
dl.kv dt { align-self: baseline; font-size: var(--text-sm); color: var(--color-text-secondary); font-weight: 400; }
dl.kv dd { margin: 0; }
.kv dd code { overflow-wrap: anywhere; }
.token-reveal { border-color: var(--color-accent); }
/* J1.6: a freshly minted token and its connect command must never wrap
   mid-token — pre-wrap (the general output-block default) breaks a
   47-character token across lines. */
.token-reveal pre, .token-reveal .output-block { white-space: pre; overflow-x: auto; }
/* The People page nests each person's tokens in their row. */
table.data table.data { margin: 0; font-size: var(--text-sm); }
table.data table.data td, table.data table.data th { padding: 0.3rem 0.5rem; }
/* Room for the floating chat launcher at every width (design-fixes:23) — it
   is 44px tall wherever it sits (bottom-right on a page, bottom-right as
   a 44px circle on a phone), not only below 767px. */
.main { min-width: 0; padding-bottom: calc(44px + var(--space-4) + var(--space-10) + env(safe-area-inset-bottom, 0px)); padding-right: env(safe-area-inset-right, 0px); }
/* Two widths: 72rem for tables and dashboards; .content-narrow (48rem) for
   settings, forms and documents (layout.html sets it from the page's
   Narrow flag). */
.content {
  max-width: 72rem;
  margin: 0 auto;
  padding: var(--space-8) var(--space-10) var(--space-12);
}
.content.content-narrow { max-width: 48rem; }
/* The run and review pages carry a map and a rail side by side: they take
   the wider frame. */


/* ============================================================
   PAGE HEADER — breadcrumbs, title, primary action
   ============================================================ */
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--space-6);
  margin-bottom: var(--space-8);
  padding-bottom: var(--space-6);
  border-bottom: 1px solid var(--color-border);
}
.page-header-main { min-width: 0; }
/* Crumbs, table heads, badges and chips set in Plex Mono, like the
   website's labels. */
.crumbs {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: 16px;
  color: var(--color-text-tertiary);
  margin-bottom: var(--space-2);
}
.crumbs a { color: var(--color-text-tertiary); }
.crumbs a:hover { color: var(--color-accent); text-decoration: none; }
.crumbs [aria-current="page"] { color: var(--color-text-secondary); }
/* The organisation line (RT-24): under the crumbs on a page whose forms
   write to the organisation, so two tabs on two organisations never mix. */
.page-org { margin: 0 0 var(--space-1); font-size: var(--text-xs); line-height: 16px; color: var(--color-text-tertiary); }
/* A head's status badge that links (an agent being set up → Set up). */
.page-status-link { display: inline-flex; }
.page-status-link:hover { text-decoration: none; }
.crumb-sep { margin: 0 var(--space-2); color: var(--color-border-strong); }
.page-title-row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2) var(--space-3); }
.page-header h1 { font-family: var(--font-display); font-size: var(--text-3xl); line-height: 36px; font-weight: 600; letter-spacing: -0.03em; }
.header-actions { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; flex: none; }
.header-actions form { display: inline-flex; margin: 0; }
.page-subtitle { font-size: var(--text-md); line-height: 22px; color: var(--color-text-secondary); margin: var(--space-1) 0 0; max-width: 65ch; }
.page-tags { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }
/* A status line under the header — never a row of buttons. */
.page-header-meta { color: var(--color-text-secondary); font-size: var(--text-md); margin: 0 0 var(--space-6); }

/* ============================================================
   PANEL — the bordered container everything lives in. A panel's
   title lives in its header; .section-label groups several panels
   and is a real 16px heading, not an uppercase eyebrow.
   ============================================================ */
.panel {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
  margin-bottom: var(--space-6);
}
.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  min-height: 48px;
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--color-border);
}
.panel-header h2, .panel-header h3 { font-size: var(--text-md); line-height: 20px; font-weight: 600; letter-spacing: 0; }
.panel-header .header-actions { gap: var(--space-2); }
details.panel-fold > summary.panel-header { cursor: pointer; list-style: none; border-bottom: 0; }
details.panel-fold > summary.panel-header::-webkit-details-marker { display: none; }
details.panel-fold > summary.panel-header h2::before { content: "▸ "; color: var(--color-text-secondary); }
details.panel-fold[open] > summary.panel-header { border-bottom: 1px solid var(--color-border); }
details.panel-fold[open] > summary.panel-header h2::before { content: "▾ "; }
.panel-title { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2) var(--space-3); min-width: 0; }
.panel-subtitle { display: block; margin-top: 2px; font-size: var(--text-sm); line-height: 20px; font-weight: 400; color: var(--color-text-tertiary); }
.panel-body { padding: var(--space-5); }
.panel-body > *:last-child { margin-bottom: 0; }
/* Sub-sections inside one panel: a rule between, an h3 at 14/600. */
.panel-body + .panel-body { border-top: 1px solid var(--color-border); }
.section-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  font-family: var(--font-display);
  font-size: 20px;
  line-height: 28px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--color-text);
  margin: var(--space-10) 0 var(--space-4);
}
.section-label:first-child { margin-top: 0; }
/* VD-15: a heading inside a panel is a panel heading, never a page
   section — Plex Sans 600 14px, whatever its tag. Page sections keep the
   20px display face above. */
.panel > .section-label, .panel-body > .section-label, .panel-body > h3 {
  font-family: var(--font-sans);
  font-size: var(--text-md);
  line-height: 20px;
  font-weight: 600;
  letter-spacing: 0;
}
.panel-body > .section-label, .panel-body > h3 { margin: var(--space-5) 0 var(--space-2); }
.panel-body > .section-label:first-child, .panel-body > h3:first-child { margin-top: 0; }
.section-label .meta-aside { font-size: var(--text-sm); }
/* The danger zone: destructive controls at the foot of a page, one row
   each — what it does on the left, the button on the right. */
.danger-zone { border-color: var(--color-negative-border); }
.danger-zone .panel-header h2, .danger-zone .panel-header h3 { color: var(--state-failing); }
.danger-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; }
.danger-row + .danger-row { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--color-border); }
.danger-row p { margin: 0; color: var(--color-text-secondary); font-size: var(--text-sm); max-width: 56ch; }
.danger-row .danger-title { color: var(--color-text); font-size: var(--text-md); font-weight: 500; }
.danger-row form { margin: 0; }
.danger-confirm > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; }
.danger-confirm > summary::-webkit-details-marker { display: none; }
.danger-confirm[open] > summary { display: none; }
.danger-confirm form { display: grid; gap: var(--space-3); justify-items: start; }
.danger-confirm-tick { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--color-text); }

/* ============================================================
   METADATA LABEL — small uppercase letter-spaced key
   ============================================================ */
.muted { color: var(--color-text-secondary); }
.text-tertiary { color: var(--color-text-tertiary); }
.mt-section { margin-top: 1.25rem; }
.meta-aside { text-transform: none; font-weight: 400; color: var(--color-text-tertiary); }
.m-0 { margin: 0; }
/* A block of plain text that should wrap, not scroll (job agents J7's
   fixed contract text). */
.pre-wrap { white-space: pre-wrap; word-wrap: break-word; }

/* Spacing and small utilities — the classes the templates use instead of
   inline style attributes (the CSP forbids those). */
.mt-2 { margin-top: 0.5rem; }
.mt-3 { margin-top: 0.75rem; }
.mt-4 { margin-top: 1rem; }
.mb-3 { margin-bottom: 0.75rem; }
.label-plain { text-transform: none; letter-spacing: 0; font-weight: 400; }
.field-10 { max-width: 10rem; }
.field-12 { max-width: 12rem; }
.border-top { border-top: 1px solid var(--color-border); }

/* Screen-reader-only text — visually hidden, still announced. */
.sr-only, .visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   BADGES — tags: a fact about a thing ("default", a kind, a count, a
   severity). Pills in Plex Mono, sentence case. A state is never a
   .badge: it is the statusBadge partial below (a dot and a word).
   ============================================================ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 20px;
  padding: 0 var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: 20px;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  vertical-align: 1px;
}
a.badge:hover { text-decoration: none; filter: brightness(0.97); }
.badge-outline, .badge-neutral {
  background: var(--color-neutral-bg);
  border-color: transparent;
  color: var(--color-text-secondary);
}
/* tones — coloured word on its soft surface (each AA, see the tokens) */
.badge-attention { background: var(--state-needs-soft); color: var(--state-needs); }
.badge-positive { background: var(--state-done-soft); color: var(--state-done); }
.badge-negative { background: var(--state-failing-soft); color: var(--state-failing); }
.badge-active { background: var(--state-working-soft); color: var(--state-working); }

/* a finding's severity as a legend pill (design-fixes:49, Task 1): a 1px
   border and 8px dot carry the severity hue, the word stays plain text —
   so a severity's own contrast is never text's, only the dot's. */

/* ============================================================
   STATUS — statusBadge (status.html, statusbadge.go): the one rendering
   of a state on every page. A dot and a mono word; the dot carries the
   hue, the word the meaning (never colour alone). Five tones: done
   (green), needs a person (amber), working (blue), failing (red), idle
   (grey) — teal is never a state.
   ============================================================ */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: 16px;
  font-weight: 500;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  white-space: nowrap;
  vertical-align: 1px;
}
/* the glyph drawn as a 6px dot in the state's colour */
.chip .chip-glyph {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  font-size: 0;
  line-height: 0;
  overflow: hidden;
}
.chip-tone-done { color: var(--state-done); }
.chip-tone-working { color: var(--state-working); }
.chip-tone-needs { color: var(--state-needs); }
.chip-tone-failing { color: var(--state-failing); }
.chip-tone-idle { color: var(--state-idle); }

/* The Activity tab (agent memory Task 13): one row per recorded activity,
   with a delivery mark per memory it is given, coloured by the state
   tokens above. */
.activity-filters { display: flex; flex-wrap: wrap; gap: 0.35rem 1rem; margin: 0.75rem 0 1rem; font-size: var(--text-md); }
.activity-filters a[aria-current="true"] { font-weight: 600; color: var(--color-text); text-decoration: underline; text-underline-offset: 0.25em; }
.activity-row { list-style: none; border-bottom: 1px solid var(--color-border); padding: 0.75rem 0; }
.activity-row:last-child { border-bottom: none; }
.activity-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }

/* A status sentence (home, integrations, the run and review heads): the
   sentence in the text colour, the state as the dot before it. */
.status-line {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  background: none;
  color: var(--color-text);
  font-size: var(--text-md);
  line-height: 20px;
  font-weight: 500;
}
.status-line::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--state-idle);
  transform: translateY(-1px);
}
.status-line.tone-needs::before { background: var(--state-needs); }
.status-line.tone-working::before { background: var(--state-working); }
.status-line.tone-done::before { background: var(--state-done); }
.status-line.tone-failing::before { background: var(--state-failing); }
.status-line.tone-idle::before { background: var(--state-idle); }
.status-line + .status-line, .status-line + p { margin-top: var(--space-2); }
/* beats the generic .tone-* fill below: the sentence is never coloured */
.status-line[class*="tone-"] { color: var(--color-text); background: none; }

/* ============================================================
   BUTTONS
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: var(--control-height);
  padding: 0 var(--space-4);
  font: inherit;
  font-size: var(--text-sm);
  line-height: 20px;
  font-weight: 600;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border-control);
  background: var(--color-surface);
  color: var(--color-text);
  box-shadow: var(--shadow-control);
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  vertical-align: middle;
}
.btn:hover { background: var(--color-surface-sunken); text-decoration: none; }
.btn:active { transform: translateY(0.5px); }
/* One primary per page, in the header, right. */
.btn-primary {
  background: var(--color-accent-solid);
  border-color: var(--color-accent-solid);
  color: var(--color-on-accent-solid);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 1px 0 rgba(14, 16, 21, 0.08);
}
.btn-primary:hover { background: var(--color-accent-solid-hover); border-color: var(--color-accent-solid-hover); }
/* Secondary: a real button, not a disabled-looking ghost. */
.btn-secondary { background: var(--color-surface); border-color: var(--color-border-control); color: var(--color-text); }
.btn-secondary:hover { background: var(--color-surface-sunken); }
/* Ghost: toolbars, panel headers, row actions. */
.btn-ghost { background: transparent; border-color: transparent; color: var(--color-text-secondary); box-shadow: none; }
.btn-ghost:hover { background: var(--color-surface-sunken); color: var(--color-text); }
/* Danger: quiet until hovered; lives in the danger zone. */
.btn-danger { background: var(--color-surface); border-color: var(--color-border-control); color: var(--color-negative-fg); }
.btn-danger:hover { background: var(--color-negative-bg); border-color: var(--color-negative-fg); }
/* Approve is the page's one primary decision: the same look as every other primary. */
.btn-approve { background: var(--color-accent-solid); border-color: var(--color-accent-solid); color: var(--color-on-accent-solid); }
.btn-approve:hover { background: var(--color-accent-solid-hover); border-color: var(--color-accent-solid-hover); filter: none; }
/* Request changes reads needs-amber (visual theme Task 11): a person must
   act on it, which is not the same signal as a failure (--state-failing,
   .btn-danger's own color). */
.btn-reject { background: var(--color-surface); border-color: var(--color-border-control); color: var(--color-text); }
.btn-reject:hover { background: var(--color-surface-sunken); }
.btn-sm { height: 30px; padding: 0 var(--space-3); font-size: var(--text-xs); }
/* J3.4: a disabled button reads as inactive, not as a faded colour. */
.btn[disabled], .btn[disabled]:hover {
  opacity: 1;
  cursor: not-allowed;
  background: var(--color-surface-sunken);
  color: var(--color-text-tertiary);
  border-color: var(--color-border);
  box-shadow: none;
  filter: none;
}
.refusal-note { margin: var(--space-2) 0 0; color: var(--color-text-secondary); font-size: var(--text-sm); }
/* Unused since portal jobs were replaced by agents (task A5) — kept until a
   template guard's dead-CSS sweep removes it (Task A6's own guard checks
   wording, not unused selectors). */
.job-instructions { white-space: pre-wrap; font-family: var(--font-mono); }
/* J3.4: the reason a disabled control can't be used, inline beside it
   rather than in a paragraph below the button row. */
.refusal-inline { color: var(--color-text-secondary); font-size: var(--text-sm); }
.btn-block-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; }
.btn-block-actions form { display: inline-flex; gap: var(--space-2); align-items: center; margin: 0; }
.btn:focus-visible, a:focus-visible, summary:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* ============================================================
   FORMS
   ============================================================ */
label { font-size: var(--text-sm); line-height: 20px; font-weight: 500; color: var(--color-text); display: block; margin-bottom: var(--space-1); }
/* "(optional)" inside a label: quiet. */
.label-note { text-transform: none; font-weight: 400; color: var(--color-text-tertiary); }
.field { margin-bottom: var(--space-4); }
.field:last-child { margin-bottom: 0; }
.field-hint { font-size: var(--text-xs); line-height: 16px; color: var(--color-text-tertiary); margin: var(--space-1) 0 0; }
/* A hint standing between blocks (not closing a field) keeps its distance
   from what follows. */
.field-hint:not(:last-child) { margin-bottom: var(--space-3); }
/* "Saved" beside a Settings save button (RT-16). */
.saved-note { margin-left: var(--space-2); color: var(--color-text-secondary); font-size: var(--text-sm); font-weight: 600; }
/* A group of radios or checkboxes: no box of its own, its legend a label. */
fieldset.field { border: 0; padding: 0; margin-inline: 0; min-width: 0; }
fieldset.field legend { font-size: var(--text-sm); line-height: 20px; font-weight: 500; color: var(--color-text); padding: 0; margin-bottom: var(--space-1); }
/* A list of links with no bullets. */
.plain-list { list-style: none; margin: 0; padding: 0; }
.plain-list li + li { margin-top: var(--space-2); }
/* upload-preview: files chosen in a skill upload's file/folder inputs,
   filled by portal.js; empty and invisible until then. */
.upload-preview { list-style: none; margin: var(--space-2) 0 0; padding: 0; font-size: var(--text-xs); color: var(--color-text-tertiary); }
.upload-preview:empty { display: none; }
.upload-preview li + li { margin-top: var(--space-1); }
.check-row { display: flex; gap: var(--space-2); align-items: baseline; margin-bottom: var(--space-2); }
.check-row label, label.check-row { font-weight: 400; margin: 0; }
input[type="checkbox"], input[type="radio"] { accent-color: var(--color-accent); width: 14px; height: 14px; margin: 0; transform: translateY(2px); }
input[type="text"], input[type="password"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input:not([type]), textarea, select {
  font: inherit;
  font-size: var(--text-md);
  line-height: 20px;
  width: 100%;
  height: var(--control-height);
  padding: 0 var(--space-3);
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  box-shadow: 0 1px 0 rgba(14, 16, 21, 0.03);
}
input:hover, select:hover, textarea:hover { border-color: var(--color-border-control-hover); }
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 22%, transparent);
}
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible, input[type="file"]:focus-visible {
  outline: 2px solid var(--color-accent); outline-offset: 2px;
}
input[disabled], select[disabled], textarea[disabled] { background: var(--color-surface-sunken); color: var(--color-text-tertiary); cursor: not-allowed; }
/* A chevron drawn with two gradients — no data: URI, no CSP change. */
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 28px;
  background-image: linear-gradient(45deg, transparent 50%, var(--color-text-secondary) 50%),
                    linear-gradient(135deg, var(--color-text-secondary) 50%, transparent 50%);
  background-position: calc(100% - 15px) 13px, calc(100% - 11px) 13px;
  background-size: 4px 4px, 4px 4px;
  background-repeat: no-repeat;
}
select[multiple], select[size] { height: auto; padding: var(--space-1); background-image: none; }
textarea { height: auto; min-height: 80px; padding: var(--space-2) var(--space-3); resize: vertical; font-family: var(--font-sans); }
textarea.mono { font-family: var(--font-mono); font-size: var(--text-sm); line-height: 20px; }
::placeholder { color: var(--color-text-tertiary); opacity: 1; }
/* The native file picker's button drawn as a secondary pill. */
input[type="file"] { font: inherit; font-size: var(--text-sm); color: var(--color-text-secondary); }
input[type="file"]::file-selector-button { height: var(--control-height); margin-right: var(--space-3); padding: 0 var(--space-4); border: 1px solid var(--color-border-control); border-radius: var(--radius-pill); background: var(--color-surface); color: var(--color-text); font: inherit; font-size: var(--text-sm); font-weight: 600; cursor: pointer; }
input[type="file"]::file-selector-button:hover { background: var(--color-surface-sunken); }
/* A one-control form in a table row: the control and its button side by
   side (Settings' background jobs). */
.job-form { display: flex; gap: var(--space-2); align-items: center; margin: 0; }
.job-form select { flex: 1; min-width: 0; }

/* ============================================================
   TABLES
   ============================================================ */
.table-scroll { overflow-x: auto; }
table.data { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--text-md); line-height: 20px; }
table.data th {
  text-align: left;
  height: 36px;
  padding: var(--space-2) var(--space-5);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  line-height: 16px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-secondary);
  background: var(--color-surface-sunken);
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}
table.data td {
  height: 48px;
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
}
table.data tr:last-child td { border-bottom: none; }
table.data tbody tr:hover { background: color-mix(in srgb, var(--color-surface-sunken) 60%, transparent); }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.data .row-title { font-weight: 500; color: var(--color-text); }
table.data .row-title a { color: var(--color-text); }
table.data .row-title a:hover { color: var(--color-accent); text-decoration: none; }
table.data .row-sub { color: var(--color-text-tertiary); font-size: var(--text-sm); line-height: 20px; margin-top: 2px; font-weight: 400; }
/* A table that opens a panel keeps the panel's rounded corners. */
.panel > .table-scroll:first-child table.data th:first-child,
.panel > table.data:first-child th:first-child { border-top-left-radius: var(--radius-lg); }
.panel > .table-scroll:first-child table.data th:last-child,
.panel > table.data:first-child th:last-child { border-top-right-radius: var(--radius-lg); }
/* A cell that holds only a row's action(s) — shrink it to its content. */
.cell-action { width: 1%; white-space: nowrap; text-align: right; }
/* A date/timestamp never wraps ("2026- / 09-12 / 09:45"). */
.date { white-space: nowrap; font-variant-numeric: tabular-nums; }

/* ============================================================
   EMPTY STATE — emptyState (partials.html), the one recipe: the
   area's illustration, a title, at most one line and an optional
   secondary pill, centred. .small is a board column's size.
   ============================================================ */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-10) var(--space-6);
  text-align: center;
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  line-height: 20px;
}
.empty-state p { margin: 0; max-width: 32rem; }
.empty-state .empty-title { color: var(--color-text); font-weight: 500; font-size: var(--text-md); }
.empty-state .empty-art { margin-bottom: var(--space-3); }
.empty-state > .btn, .empty-state > form { margin-top: var(--space-3); }
.empty-state.small { padding: var(--space-5) var(--space-3); }
.empty-state.small .empty-art { width: 96px; height: 64px; margin-bottom: var(--space-2); }

/* ============================================================
   SETTINGS FRAME (settings.go, settings.html, people.html; design-fixes
   Task 3): the index's whole-row links, one shared frame (crumb, width)
   for every page under it, and People's inline role control.
   ============================================================ */
.settings-list { list-style: none; margin: 0; padding: 0; }
.settings-row { display: grid; grid-template-columns: auto minmax(0,1fr) auto auto; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-5); border-top: 1px solid var(--color-border); color: var(--color-text); text-decoration: none; min-height: 44px; }
.panel > .settings-list:first-child li:first-child .settings-row { border-top: 0; }
.settings-row:hover { background: var(--color-surface-sunken); text-decoration: none; }
.settings-row-main { display: flex; flex-direction: column; min-width: 0; }
.settings-row-title { font-weight: 500; }
.settings-row-status { color: var(--color-text-secondary); font-size: var(--text-sm); }
.settings-row-chevron { color: var(--color-text-tertiary); }
.row-menu > summary { list-style: none; cursor: pointer; min-width: 32px; text-align: center; }
.row-menu > summary::-webkit-details-marker { display: none; }
.inline-list { display: flex; flex-wrap: wrap; gap: 0.3rem 1rem; list-style: none; margin: 0; padding: 0; }
@media (max-width: 767px) {
  .people-table thead { display: none; }
  .people-table tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.4rem var(--space-3); padding: var(--space-3) 0; border-top: 1px solid var(--color-border); }
  .people-table td { border: 0; padding: 0; grid-column: 1 / -1; }
  /* VD-5: the state badge sits beside the name; the role select and Save
     stack in one column with a gap. */
  .people-table td:nth-child(1) { grid-column: 1; grid-row: 1; }
  .people-table td:nth-child(3) { grid-column: 2; grid-row: 1; }
  .people-table td:nth-child(2) .inline-form { flex-direction: column; align-items: stretch; gap: var(--space-2); }
  .people-table td:nth-child(2) .inline-form .btn { margin-top: 0; align-self: flex-start; }
}

/* Models: each endpoint's check line under its name, amber when it needs
   a look (tools not working, or a small window). */
.model-line { margin: var(--space-1) 0 0; font-size: var(--text-sm); font-weight: 400; color: var(--color-text-secondary); }
.model-line-needs { margin: var(--space-1) 0 0; font-size: var(--text-sm); font-weight: 400; color: var(--color-attention-fg); }
tr.model-row-needs td { background: var(--state-needs-soft); }

/* ============================================================
   HOME (home.go, home.html; visual theme Tasks 6-7) — the greeting and KPI
   band, the two-column grid with its side column (this month's runs, the
   activity heatmap, the decisions feed), and the three run lists (Needs
   you, Awaiting someone else's decision, Being worked) plus Knowledge to
   review, each a list of cards rather than a table row; the illustrated
   "No runs yet" panel is EMPTY STATE above with an area's emptyArt as its
   first child, in emptyState's one recipe.
   ============================================================ */

/* BP-4 (browser check, a theme bug already on main): the empty "No
   decisions yet." line carries none of the row's 3 columns (avatar | text
   | time), so it landed alone in the 24px avatar column and wrapped a few
   letters per line. home.html has only this one .home-feed, and only this
   one empty line. */

.home-cards { display: flex; flex-direction: column; gap: var(--space-3); list-style: none; margin: 0; padding: 0; }
.home-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
/* A tone class also colors text/background wherever it appears (chips,
   bands, activity-actor) — pinned back here so a card's own surface and text
   stay plain regardless of tone; only its border picks up tone-needs. */
.home-card.tone-needs { border-color: var(--state-needs-soft); background: var(--color-surface); color: var(--color-text); }
.home-card.tone-working { background: var(--color-surface); color: var(--color-text); }
.home-card > .btn { white-space: nowrap; flex-shrink: 0; }
.home-card-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* BP-2/BP-5 (browser check): overflow-wrap: anywhere lets the browser treat
   every character as a break opportunity for min-content sizing, so a
   title's grid track could collapse well below its longest word's width —
   one letter per line on the Features board (BP-2) and an occasional
   mid-word break here at medium widths ("Maintenanc e windows", BP-5).
   break-word keeps the same safety net (a single token longer than the
   line still breaks) but only after ordinary word-boundary wrapping no
   longer fits. */
.home-card-title { font-weight: 500; color: var(--color-text); overflow-wrap: break-word; }
.home-card-title:hover { color: var(--color-accent); text-decoration: none; }
.home-card-sub { margin: 0; font-size: var(--text-sm); color: var(--color-text-secondary); overflow-wrap: anywhere; }
/* BP-5 (browser check, ~800px viewport): above 640px the row's trailing
   action cluster (an avatar or the portal's glyph, the age chip, the
   status chip, Decide/Open) still shared one row with the title, with no
   room at medium widths. Below 900px they wrap under the text exactly as
   they already did on a phone. */
@media (max-width: 900px) {
  .home-card { grid-template-columns: minmax(0, 1fr) auto; }
  .home-card > .btn { grid-column: 1 / -1; }
  /* A chip keeps its own width in the narrow grid, never the column's. */
  .home-card > .badge, .home-card > .chip { justify-self: start; }
}


/* ============================================================
   DECISIONS — the record's highest-value part
   ============================================================ */
ul.decisions { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }

/* ============================================================
   STAGE ATTEMPT PANEL
   ============================================================ */

pre.output-block {
  white-space: pre-wrap; word-wrap: break-word;
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border);
  padding: 0.75rem 0.9rem;
  border-radius: var(--radius-sm);
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-md);
  line-height: 1.55;
}

details.disclosure { margin-top: 0.9rem; border-top: 1px solid var(--color-border); padding-top: 0.7rem; }
details.disclosure summary {
  cursor: pointer; color: var(--color-text-secondary); font-size: var(--text-sm); font-weight: 600;
  list-style: none; overflow-wrap: anywhere; white-space: normal;
}
details.disclosure summary::-webkit-details-marker { display: none; }
details.disclosure summary::before { content: "▸ "; color: var(--color-text-tertiary); }
details.disclosure[open] summary::before { content: "▾ "; }
details.disclosure > pre { margin-top: 0.6rem; }

/* ============================================================
   SLACK STEP — Settings › Slack's four-step checklist
   (agent memory task 16). Each step is its own <details>, styled
   like a panel; only the current one opens by default.
   ============================================================ */
.slack-step {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
  margin-bottom: var(--space-4);
  padding: var(--space-4) var(--space-5);
}
.slack-step > summary {
  cursor: pointer;
  font-weight: 600;
  font-size: var(--text-md);
  list-style: none;
}
.slack-step > summary::-webkit-details-marker { display: none; }
.slack-step > :not(summary) { margin-top: var(--space-4); }
.slack-step.state-done > summary { color: var(--state-done); }
.slack-step.state-later > summary { color: var(--color-text-tertiary); }

/* ============================================================
   CALLOUT — at most one per place, only when there is something to
   do or know. The body is always --color-text; only the title
   carries the tone. Never two in a row (merge them).
   ============================================================ */
/* R16: a callout stacked right after the tab bar, or right after another
   callout (a job agent's page can carry several), used to touch it —
   give it its own top margin. */
.tabs + .callout, .callout + .callout { margin-top: var(--space-3); }
.callout, .callout-neutral, .critique-block, .worker-error-block, .import-warning {
  display: block;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-sunken);
  color: var(--color-text);
  font-size: var(--text-md);
  line-height: 22px;
}
.callout > :last-child { margin-bottom: 0; }
.callout-title { display: block; font-weight: 600; margin: 0 0 2px; color: var(--color-text); }
.callout-body { margin: 0; }
.callout-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-3); }
.callout-actions form { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: 0; }
.callout-actions select { width: 16rem; max-width: 100%; }
.callout-neutral { color: var(--color-text); }
/* a person is needed */
.callout-needs, .critique-block, .import-warning { background: var(--state-needs-soft); border-color: var(--color-attention-border); }
.callout-needs .callout-title, .critique-block .callout-title { color: var(--state-needs); }
/* something failed that you must fix */
.callout-failing, .worker-error-block { background: var(--state-failing-soft); border-color: var(--color-negative-border); }
.callout-failing .callout-title, .worker-error-block .callout-title { color: var(--state-failing); }
/* in progress / for information */
.callout-working { background: var(--state-working-soft); border-color: color-mix(in srgb, var(--state-working) 30%, transparent); }
.callout-working .callout-title { color: var(--state-working); }
.callout-done { background: var(--state-done-soft); border-color: var(--color-positive-border); }
.callout-done .callout-title { color: var(--state-done); }
.critique-block, .worker-error-block { margin-top: var(--space-3); }
.critique-block pre, .worker-error-block pre { background: transparent; border: none; padding: var(--space-1) 0 0; color: var(--color-text); white-space: pre-wrap; }
.worker-error-block pre { font-family: var(--font-mono); font-size: var(--text-sm); }
.worker-error { margin-top: 0; }
.worker-error p { margin: 0; }
.worker-error-sentence { font-weight: 600; }
.worker-error-fix, .worker-error-hint { margin-top: var(--space-1); color: var(--color-text-secondary); }
.worker-error-details { margin-top: var(--space-2); }
.worker-error-details summary { cursor: pointer; font-size: var(--text-sm); color: var(--color-text-secondary); }
.worker-error-details pre { margin: 0; max-height: 14rem; overflow: auto; overflow-wrap: anywhere; }
/* Critique is agent-generated prose, rendered through the markdown
   pipeline (markdown.go). */
.critique-block .markdown-body { color: var(--color-text); margin-top: var(--space-1); font-size: var(--text-md); line-height: 22px; max-width: none; }
.critique-block .markdown-body > *:last-child { margin-bottom: 0; }
.import-warning { margin: var(--space-2) 0; padding: var(--space-2) var(--space-3); }

/* A severity label the judge opens a point with (severity.go): an inline
   badge that sits on the text's baseline instead of the panel header's. */
.markdown-body .badge.severity { vertical-align: 0.1em; margin-right: 0.3rem; }

/* Portal authoring: a portal-executed stage still being drafted. */
.drafting-box { border-color: var(--color-border); background: var(--color-surface-sunken); }
.drafting-box .approval-heading { color: var(--color-text); }

/* A form sent back with what was wrong with it. */
.form-error {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-negative-border);
  border-radius: var(--radius-md);
  background: var(--state-failing-soft);
  color: var(--color-text);
  margin-bottom: var(--space-4);
}

ul.files { list-style: none; margin: 0.4rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.2rem; }
ul.files li code { font-size: var(--text-sm); background: var(--color-surface-sunken); padding: 0.1rem 0.4rem; border-radius: 3px; }

/* diff — no syntax highlighting, no library: coloured by leading +/- */
.diff-panel { margin-top: 0.6rem; }
.diff {
  overflow-x: auto;
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0;
  font: var(--text-xs)/1.5 var(--font-mono);
}
.diff .line { padding: 0 1rem; white-space: pre; }
.diff .add { background: var(--color-diff-add-bg); color: var(--color-diff-add-fg); }
.diff .del { background: var(--color-diff-del-bg); color: var(--color-diff-del-fg); }
.diff .hunk { color: var(--color-text-tertiary); }
.diff .meta { color: var(--color-text-tertiary); font-weight: 500; }
.diff .line:target { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.diff-file { margin-top: 0.8rem; font-size: var(--text-sm); }
/* J5.10-style navigation: one file's diff behind a <details>, its summary
   showing the path and a +N/−M tally so a reviewer can scan the file list
   without opening every diff. */
.diff-file-box { margin-top: 0.8rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); }
.diff-file-box summary {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.8rem;
  font-size: var(--text-sm);
  font-family: var(--font-mono);
  list-style: none;
}
.diff-file-box summary::-webkit-details-marker { display: none; }
.diff-file-box[open] summary { border-bottom: 1px solid var(--color-border); }
.diff-file-box .diff-add-count { color: var(--color-diff-add-fg); }
.diff-file-box .diff-del-count { color: var(--color-diff-del-fg); }
.diff-file-box .diff { border: none; border-radius: 0; margin: 0; }
/* The raw `diff --git`/`index`/`---`/`+++` lines — closed by default, small,
   folded away from the +/- lines a reviewer actually reads. */
.diff-meta { margin-top: 0.4rem; font-size: var(--text-2xs); }
.diff-meta summary { cursor: pointer; color: var(--color-text-tertiary); list-style: none; }
.diff-meta summary::-webkit-details-marker { display: none; }
.diff-meta pre { margin-top: 0.3rem; }

/* linediff: a rescanned reference or skill against the approved text (the
   agent page's review panel). Colours are the run page's diff tokens. */
.diff-heading { margin: 0.8rem 0 0.3rem; font-size: var(--text-sm); }
.diff-counts { margin: 0 0 0.25rem; font-size: var(--text-sm); }
.diff-table { width: 100%; border-collapse: collapse; font-family: var(--font-mono); font-size: var(--text-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); }
.diff-table td { padding: 0 0.5rem; vertical-align: top; }
.diff-num { width: 3.5rem; text-align: right; color: var(--color-text-tertiary); user-select: none; }
.diff-text { white-space: pre-wrap; overflow-wrap: anywhere; }
.diff-hunk td { color: var(--color-text-tertiary); padding-top: 0.4rem; }
.diff-line.diff-add { background: var(--color-diff-add-bg); color: var(--color-diff-add-fg); }
.diff-line.diff-del { background: var(--color-diff-del-bg); color: var(--color-diff-del-fg); }

/* review — numbered output, comment forms and threads; no script */
.review-lines { border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface-sunken); padding: 0.4rem 0; font: var(--text-sm)/1.55 var(--font-mono); }
.review-line { display: flex; padding: 0 0.8rem; white-space: pre-wrap; }
.review-line:target { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.review-line .text { flex: 1; min-width: 0; }
/* J3.7: nothing said a line number was clickable — a "+" appears on hover,
   absolutely positioned inside the number cell so it never shifts the
   digits or the line it sits on. */
/* The rendered review: a stage output as blocks (blocks.go), the "At a
   glance" ones in a card at the top. Each block carries a Comment link at its
   right — shown on hover, when the block is the one linked to, and whenever
   it has keyboard focus (it is only ever transparent, never removed, so it
   stays reachable). */

.output-block { position: relative; padding: 0.1rem 4.5rem 0.1rem 0.4rem; border-radius: var(--radius-sm); }
.output-block:target { outline: 2px solid var(--color-accent); outline-offset: -2px; }

.comment-link { margin-left: 0.6rem; font-size: var(--text-sm); font-weight: 400; text-transform: none; }
.diff .diff-aside { white-space: normal; font: var(--text-md)/1.5 var(--font-sans); padding: 0.2rem 0; }
.comment, .comment-form { margin: 0.4rem 0.8rem 0.6rem 3.4rem; padding: 0.6rem 0.8rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); font: var(--text-md)/1.5 var(--font-sans); white-space: normal; }
.comment.is-resolved > summary { cursor: pointer; color: var(--color-text-secondary); }
/* A comment's colour is its state — open is attention (amber), resolved is
   positive (green) — as its left edge and a pill. An accent (blue) pill marks
   one raised on an earlier attempt; a neutral pill says why a carried comment
   is not on this attempt's lines. */
.comment.is-resolved { border-left: 3px solid var(--color-positive-fg); background: var(--color-surface-sunken); }
.comment-state, .comment-from, .comment-unplaced {
  display: inline-block; margin-right: 0.35rem; padding: 0.05rem 0.5rem;
  border: 1px solid transparent; border-radius: 999px;
  font-size: var(--text-xs); font-weight: 500;
  line-height: 1.5; white-space: nowrap; vertical-align: 0.05rem;
}
.comment.is-resolved .comment-state { background: var(--color-positive-bg); color: var(--color-positive-fg); border-color: var(--color-positive-border); }
.comment-from { background: var(--color-neutral-bg); color: var(--color-text-secondary); border-color: var(--color-neutral-border); }
.comment-unplaced { background: var(--color-neutral-bg); color: var(--color-neutral-fg); border-color: var(--color-neutral-border); }

.comment-body { margin: 0.3rem 0; white-space: pre-wrap; }
.comment-quote { margin: 0.3rem 0; padding: 0.3rem 0.6rem; background: var(--color-surface-sunken); border-radius: var(--radius-sm); font: var(--text-sm)/1.5 var(--font-mono); white-space: pre-wrap; }
/* J3.3: a suggestion diff inside a comment holds prose, not code — it must
   wrap at the panel edge instead of forcing a horizontal scrollbar. The
   plain .diff (code, in the Changes panel) keeps white-space: pre above. */
.comment .diff .line { white-space: pre-wrap; overflow-wrap: anywhere; }
.comment-event { margin-top: 0.25rem; font-size: var(--text-sm); }
.comment-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.comment-actions form { display: flex; gap: 0.3rem; margin: 0; }
.comment-actions input { min-width: 0; }
.comment-tally { margin: 0 0 0.8rem; font-size: var(--text-md); }

/* ============================================================
   APPROVAL FORM — the most important control in the product
   ============================================================ */
.approval-box {
  border: 1px solid var(--color-attention-border);
  background: var(--state-needs-soft);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  margin-top: var(--space-4);
  color: var(--color-text);
}
.approval-box .approval-heading {
  display: flex; align-items: center; gap: var(--space-2);
  font-weight: 600; font-size: var(--text-md); color: var(--state-needs);
  margin-bottom: var(--space-3);
}
.approval-box textarea {
  background: var(--color-surface);
}
.approval-box .btn-block-actions { margin-top: 0.75rem; }

/* An outline button, no fill (visual theme Task 11): sending back is a
   routing choice, not a danger — .btn's own base already gives it
   --color-surface. */

kbd { display: inline-block; padding: 0 0.3rem; border: 1px solid var(--color-border-strong); border-bottom-width: 2px; border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text-secondary); font-size: 0.7rem; line-height: 1.4; }

/* The marks on a finding card: three segmented radios (the input hidden,
   its label the control) and a note, both on the decision form. The note is
   a textarea: Enter there is a new line, never a submit of Send back. */
.marks-seg { display: inline-flex; margin: 0.7rem 0 0; padding: 0; border: 1px solid var(--color-border-control); border-radius: var(--radius-md); overflow: hidden; }
.marks-seg input { position: absolute; opacity: 0; pointer-events: none; }
.marks-seg label { margin: 0; padding: 0.25rem 0.75rem; border-right: 1px solid var(--color-border); color: var(--color-text-secondary); font-size: var(--text-sm); font-weight: 500; cursor: pointer; }
.marks-seg label:last-of-type { border-right: 0; }
.marks-seg input:checked + label { color: var(--color-surface); }
.marks-seg input[value="fix"]:checked + label { background: var(--color-negative-fg); }
.marks-seg input[value="accept"]:checked + label { background: var(--color-positive-fg); }
.marks-seg input[value="ignore"]:checked + label { background: var(--color-neutral-fg); }
.marks-seg input:focus-visible + label { outline: 2px solid var(--color-accent); outline-offset: -2px; }
/* reviews:157 — a mark segment is a real touch target on a phone. */
@media (max-width: 767px) { .marks-seg label { min-height: 40px; display: inline-flex; align-items: center; } }
.finding-note { display: block; width: 100%; margin-top: 0.5rem; font-size: var(--text-sm); }

/* run:15 — a scroll cue for the map's own box: two edge fades that scroll
   with the content (so they only show where there is more to see) over two
   shadows fixed to the viewport (so they only peek through once something
   is actually scrolled past) — the standard background-attachment:
   local/scroll pair, tokens only, no script. */
.chain-scroll {
  overflow-x: auto;
  margin: 0 0 1rem;
  background:
    linear-gradient(to right, var(--color-surface) 30%, transparent) left / 24px 100% no-repeat local,
    linear-gradient(to left, var(--color-surface) 30%, transparent) right / 24px 100% no-repeat local,
    linear-gradient(to right, color-mix(in srgb, var(--color-text) 16%, transparent), transparent) left / 8px 100% no-repeat scroll,
    linear-gradient(to left, color-mix(in srgb, var(--color-text) 16%, transparent), transparent) right / 8px 100% no-repeat scroll;
}

/* The map is the chain's accessible form: a box reached with Tab shows a
   ring of its own, thicker than a selected box's, and dashed so it reads as
   focus, not selection, on a box that is both. */

.detail header { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.5rem; }
.detail header h4 { margin: 0; font-size: var(--text-lg); }
.detail .kind { font-size: var(--text-xs); font-weight: 500; color: var(--color-text-tertiary); }
.detail .src { margin-left: auto; font-size: var(--text-sm); }
.detail .lead { font-size: var(--text-md); margin: 0 0 0.75rem; line-height: 1.5; }
.detail .facts { display: grid; grid-template-columns: max-content 1fr; gap: 0.35rem 1rem; margin: 0 0 0.75rem; font-size: var(--text-sm); }
.detail .facts dt { color: var(--color-text-tertiary); }
.detail .facts dd { margin: 0; }
.detail .arrow { color: var(--color-text-tertiary); }
.why { border: 1px solid; border-left-width: 4px; border-radius: var(--radius-sm); padding: 0.75rem 1rem; font-size: var(--text-sm); }

.why > p { margin: 0.6rem 0 0; }
.why .deploy { margin-top: 0.25rem; color: var(--color-text-secondary); }

.finding { border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 0.6rem 0.8rem; background: var(--color-surface); }
.finding p { margin: 0.35rem 0 0; }
.finding .fix { color: var(--color-text-secondary); }

/* The stage bands over the column heads (chainbands.go): the stage's label
   alone, centred in its band — its state shows once, on the band row above
   the map, never here too. */

.mark { margin-top: 0.5rem; font-size: var(--text-sm); }
.mark blockquote { margin: 0.3rem 0 0; padding: 0.3rem 0.7rem; border-left: 3px solid var(--color-border-strong); color: var(--color-text-secondary); }
/* reviews:145 — a bare <blockquote> (a rule's quote, a suggestion's source
   words, an ignore note) takes the same quiet left accent as everywhere
   else a quote sits, rather than the browser default. */
.panel-body blockquote { border-left: 3px solid var(--color-border-strong); margin: 0.4rem 0 0; padding: 0 0 0 var(--space-3); color: var(--color-text-secondary); }
.why .overall { margin: 0.75rem 0 0; }

/* ============================================================
   SKILL MARKDOWN BODY
   ============================================================ */
/* A long document (a main skill, stage instructions): 15/26, at most 72
   characters a line. Inside a rail, a card or a critique it takes the
   container's width (the rules at those places set max-width: none). */
.markdown-body { font-size: var(--text-prose); line-height: 26px; max-width: 72ch; color: var(--color-text); }
.markdown-body h1 { font-size: var(--text-xl); line-height: 28px; letter-spacing: -0.01em; border-bottom: 0; padding-bottom: 0; margin: 0 0 var(--space-3); }
.markdown-body h2 { font-size: var(--text-lg); line-height: 24px; font-weight: 600; margin: var(--space-8) 0 var(--space-2); }
.markdown-body h3 { font-size: var(--text-prose); line-height: 24px; font-weight: 600; margin: var(--space-6) 0 var(--space-2); }
.markdown-body h4, .markdown-body h5 { font-size: var(--text-md); font-weight: 600; margin: var(--space-4) 0 var(--space-1); }
.markdown-body > :first-child { margin-top: 0; }
.markdown-body p { margin: 0 0 var(--space-4); }
.markdown-body ul, .markdown-body ol { margin: 0 0 var(--space-4); padding-left: 1.4rem; }
.markdown-body li { margin-bottom: var(--space-1); }
.markdown-body li::marker { color: var(--color-text-tertiary); }
.markdown-body strong { font-weight: 600; }
.markdown-body hr { border: 0; border-top: 1px solid var(--color-border); margin: var(--space-6) 0; }
.markdown-body code {
  font-family: var(--font-mono); font-size: 0.88em;
  background: var(--color-surface-sunken); padding: 1px 4px; border-radius: 4px; border: 0;
}
.markdown-body pre {
  background: var(--color-surface-sunken); border: 1px solid var(--color-border);
  border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); overflow-x: auto; margin: 0 0 var(--space-4);
  font-size: var(--text-sm); line-height: 20px;
}
.markdown-body pre code { background: none; padding: 0; font-size: var(--text-sm); }
.markdown-body blockquote {
  margin: 0 0 var(--space-4); padding: var(--space-1) var(--space-4); border-left: 2px solid var(--color-border-strong);
  color: var(--color-text-secondary);
}
.markdown-body a { color: var(--color-accent); }
.comment .markdown-body { max-width: none; }
.comment .markdown-body { font-size: var(--text-md); line-height: 22px; }
/* display:block turns the table itself into the scrollable container — its
   rows/cells keep their normal table layout, but a table wider than the
   panel scrolls horizontally in place instead of widening the page. */
.markdown-body table { display: block; overflow-x: auto; border-collapse: collapse; margin: 0 0 0.9rem; font-size: 0.85em; }
.markdown-body table th, .markdown-body table td { border: 1px solid var(--color-border); padding: 0.4rem 0.6rem; }

/* ============================================================
   MISC
   ============================================================ */
.stack { display: flex; flex-direction: column; gap: var(--space-4); }
.stack > .field, .stack > .field-row, .stack > fieldset.field { margin-bottom: 0; }
/* A form's button keeps its natural width, left-aligned (VD-16). */
.stack > .btn { align-self: flex-start; }
kbd { font-family: var(--font-mono); }

/* VD-6: signed out (login, signup, the link pages) there is no sidebar and
   no phone bar: the brand mark centred over one card. */
.auth-shell { min-height: 100vh; }
.auth-shell .auth-brand { justify-content: center; height: auto; margin: 96px auto 0; padding: 0; width: max-content; }
.auth-shell .content { max-width: 420px; margin: var(--space-6) auto 0; padding: 0 var(--space-4) var(--space-12); }
.auth-shell .narrow-form { max-width: none; }
@media (max-width: 767px) {
  .auth-shell .auth-brand { margin-top: var(--space-10); }
}

/* ============================================================
   RESPONSIVE — sidebar becomes a top bar; nothing scrolls the
   page body sideways; wide content scrolls in its own box.
   ============================================================ */
@media (max-width: 860px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    border-right: none;
    border-bottom: 1px solid var(--color-border);
    padding: 0.75rem 1rem;
    padding-left: calc(1rem + env(safe-area-inset-left, 0px));
    padding-right: calc(1rem + env(safe-area-inset-right, 0px));
    gap: 0.75rem;
    position: sticky;
    top: 0;
    z-index: 5;
  }
  .brand { padding: 0; }
  .nav-group { flex-direction: row; flex-wrap: wrap; }
  /* shell:58: a tap target of at least 44px on the phone menu's own
     links and its disclosure. */
  .nav-link { min-height: 44px; }
  .nav-menu > summary { min-height: 44px; display: inline-flex; align-items: center; gap: var(--space-2); }

  /* Compact "Signed in" row: keep the person's name and Sign out, drop the
     "Signed in" label (above) and the org name — one row instead of three. */
  .nav-account { margin-top: 0; border-top: 0; padding-top: 0; flex-direction: row; align-items: center; flex-wrap: wrap; }
  .nav-person { padding: 0 var(--space-2); }
  .nav-org-name { display: none; }
  .content { padding: var(--space-5) var(--space-4) var(--space-12); }
  .page-header { flex-direction: column; align-items: flex-start; }
  .field-row { grid-template-columns: minmax(0, 1fr); }
  .danger-row { align-items: flex-start; }
  /* J3.3/responsiveness: a suggestion diff's margin-left leaves little room
     at this width for the comment/suggestion text itself. */
  .comment-form, .comment { margin-left: 1.2rem; }
}

/* portal.js: screen-reader-only live region and the top bar */
.poll-bar { position: sticky; top: 0; z-index: 30; display: flex; gap: 0.75rem; align-items: center; padding: 0.45rem 1.25rem; background: var(--color-accent-solid); color: var(--color-on-accent-solid); font-size: var(--text-md); }
.poll-bar.is-error { background: var(--color-negative-fg); }
.poll-bar button { margin-left: auto; background: var(--color-surface); color: var(--color-accent); border: 0; border-radius: 6px; padding: 0.2rem 0.75rem; font-weight: 600; cursor: pointer; }
.poll-bar .poll-bar-close { margin-left: 0; background: transparent; color: inherit; }

/* tag-chip: a plain outlined label ("auto" beside a portal-written line)
   — not a status, so its own class, never statusBadge's ".chip" base
   (final review I1: the two once shared a name and this one silently
   overrode every tone). */
.tag-chip { display: inline-flex; align-items: center; gap: 0.35rem; border: 1px solid var(--color-border); background: var(--color-surface); border-radius: 999px; padding: 0.05rem 0.6rem; font-size: var(--text-xs); color: var(--color-text-secondary); }

/* tag / tag-builtin: the Agents list's built-in tag (task 14, spec
   2026-09-27) — a small label beside an agent's name, distinct from
   statusChip's tone-driven ".chip" base and from tag-chip's own run-page
   role. */
.tag { display: inline-flex; align-items: center; border-radius: 999px; padding: 0.05rem 0.6rem; font-size: var(--text-xs); font-weight: 600; }

/* The Agents list as a card grid (visual theme Task 12): every card the
   same width band, wrapping to fit; buttons inside stay teal — an agent
   is not an area of its own, so the card carries the agents area chip,
   never a hue on anything that carries state. */
/* TR-13 (whole-branch review): padded on three sides so a card's own border
   does not abut the panel's — the top keeps the margin above instead, for
   the gap under .agent-list-filters. */
.agent-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: var(--space-3); margin: 0.7rem 0 0; padding: 0 var(--space-5) var(--space-5); }
.agent-card { display: flex; flex-direction: column; gap: 0.5rem; padding: var(--space-4); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); }
.agent-card-head { display: flex; align-items: flex-start; gap: 0.6rem; }
.agent-card-name { min-width: 0; overflow-wrap: anywhere; font-weight: 500; }
.agent-card-name a { color: var(--color-text); }
.agent-card-desc { margin: 0; font-size: var(--text-sm); }
/* VD-23: three mono count chips, then the one usage line (PS-14). */
.agent-card-stats { margin: 0; display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-2); }
.agent-card-usage { margin: 0; font-size: var(--text-sm); color: var(--color-text-secondary); }
.agent-card-review { margin: 0; font-size: var(--text-sm); }
.agent-card > form { align-self: flex-start; }
/* The add card: a dashed placeholder, the same illustration and words the
   empty state uses elsewhere — never a table row, so it sits at the grid's
   own end. */

.tabs { display: flex; gap: 2px; margin: 1.1rem 0 0; border-bottom: 1px solid var(--color-border); overflow-x: auto; }
.tab { padding: 0.5rem 0.75rem; margin-bottom: -1px; border-bottom: 2px solid transparent; color: var(--color-text-secondary); white-space: nowrap; font-size: var(--text-md); text-decoration: none; }
.tab:hover { color: var(--color-text); text-decoration: none; }
.tab[aria-current="page"] { color: var(--color-text); border-bottom-color: var(--color-text); font-weight: 600; }
/* A tab's waiting decisions, in words (UX-19): the ● is decoration. */
.tab-need { color: var(--color-attention-fg); font-size: var(--text-sm); font-weight: 400; }
/* Under 768px the tabs wrap onto a second line: no tab is ever hidden off
   the edge, and nothing needs a script to reach it. The agent page's own
   tabs stay one row and scroll sideways (VD-4). */
@media (max-width: 767px) {
  .tabs:not(.agent-tabs) { flex-wrap: wrap; overflow-x: visible; }
}

.finding-card { margin-bottom: 0.75rem; padding: 0.9rem 1rem; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); outline: none; }
.finding-card.is-current, .finding-card:focus-visible { box-shadow: 0 0 0 2px var(--color-accent); }
/* A row already marked away from "to fix" (settled — accepted or ignored)
   reads decided, not dimmed to under-contrast (reviews:134/151: opacity
   0.6 read 2.36:1) — a left accent and a filled mark glyph (reviews:146)
   say "dealt with" without losing the text. */

.finding-top { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.finding-where { color: var(--color-text-tertiary); font-size: var(--text-sm); }
.finding-where a { color: var(--color-text-secondary); }
.finding-issue { margin: 0.5rem 0 0; }
.finding-fix { margin: 0.6rem 0 0; color: var(--color-text-secondary); }
.finding-disposition { margin: 0.35rem 0 0; color: var(--color-text-secondary); font-size: var(--text-sm); }

/* ============================================================
   REVIEW PAGE (review.html, reviews.go) — design-fixes Task 6
   ============================================================ */
/* reviews:115 — the trust line: quiet by default, attention tone only for
   a thin (diff-only) review. */
.review-trust { margin: 0.2rem 0 0; color: var(--color-text-secondary); font-size: var(--text-sm); }
.review-trust.tone-attention { color: var(--state-needs); }
.finding-evidence { margin-top: 0.5rem; }
.finding-evidence summary { color: var(--color-text-secondary); font-size: var(--text-sm); cursor: pointer; }
.finding-place { margin: 0.4rem 0; color: var(--color-text-secondary); font-size: var(--text-sm); }
.snippet { margin-top: 0.6rem; overflow-x: auto; border: 1px solid var(--color-border); border-radius: var(--radius-sm); font-family: var(--font-mono); font-size: var(--text-xs); }
.snippet-row { display: grid; grid-template-columns: 2.4rem 2.4rem 1fr; white-space: pre; line-height: 1.55; }
.snippet-row span { padding: 0 0.4rem; }
.snippet-row.add { background: var(--color-diff-add-bg); }
.snippet-row.del { background: var(--color-diff-del-bg); }
/* reviews:161 — a long line in a finding's snippet wraps rather than
   forcing the whole card to scroll sideways. */
.snippet-row .text { white-space: pre-wrap; overflow-wrap: anywhere; }

/* The review page rebuilt around the mockup (wave 1b, task 9, and its
   2026-09-29 controller layout fix): its own page grid, the verdict head,
   the trust line, the seven-angle strip, the criteria table and the angle
   sections — new classes only, every color still a token. */

/* .review-page is scoped to this page, not the shared .run-top/.run-rail
   grid (380px, run/agent/prd pages): minmax(0,1fr) 320px, matching the
   mockup exactly; .review-span crosses both columns (the head and the
   strip); the rail sticks at the same 16px every sticky rail in the app
   uses, and is never its own scroll container. */
.review-page { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); align-items: start; }
@media (min-width: 1000px) {
  .review-page { grid-template-columns: minmax(0, 1fr) 320px; }
  .review-page > .review-span { grid-column: 1 / -1; }
  .review-page > .review-rail-col { position: sticky; top: 16px; }
  /* Data flow drops the rail: its drawings need the width. */
  .review-page.review-page-wide { grid-template-columns: minmax(0, 1fr); }
}
.review-head-block { display: grid; gap: var(--space-3); }
.review-main { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
.review-rail-col { display: grid; gap: var(--space-4); min-width: 0; }
.review-rail-col > * { min-width: 0; max-width: 100%; }

.review-verdict-head .panel-body { display: grid; gap: var(--space-3); }
.review-head-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }
.review-head-verdict { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
/* The verdict badge is the largest thing in the head (controller fix):
   15px/600, a padded pill with its own icon — bigger than the ordinary
   .badge it still is one (same tone classes, same tokens). */
.review-verdict-badge { font-size: 15px; font-weight: 600; padding: 6px 14px; gap: var(--space-2); }
.review-verdict-icon { flex: none; }
.review-one-line { margin: 0; max-width: 78ch; font-size: 15px; }
.review-chips { margin: 0; }

/* .status-row (mockup gap e): "Marked" and "N of M" are two sibling
   elements with no text between them — with no rule at all they rendered
   glued together ("Marked0 of 4"); space-between is the mockup's own fix,
   not a text-node space, since the row also carries a link and a pill
   side by side elsewhere (the PRD-changes list). */

/* A running review's last step, under "Reviewing…". */
.review-progress { margin-top: 0.35rem; color: var(--color-text-secondary); font-size: var(--text-sm); }


.commit { margin-bottom: 0.5rem; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); }
.commit > summary { padding: 0.55rem 0.8rem; cursor: pointer; font-size: var(--text-md); }
.commit[open] > summary { border-bottom: 1px solid var(--color-border); }

.context-fold { margin-bottom: 0.75rem; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); font-size: var(--text-sm); }
.context-fold > summary { padding: 0.6rem 0.9rem; cursor: pointer; font-weight: 600; }
.context-body { padding: 0 0.9rem 0.9rem; }

/* The re-review callout (task 6): why an attempt came back — a send-back or
   changes requested — accent-soft, matching .badge-active's accent family
   rather than the negative tone .worker-error-block uses (this is context,
   not a fault). */
.callout-back {
  border: 1px solid var(--color-attention-border);
  background: var(--state-needs-soft);
  color: var(--color-text);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
  font-size: var(--text-md);
}
.callout-back p { margin: 0.4rem 0 0; }
.callout-back p:first-child { margin-top: 0; }
.callout-back .meta-label { margin-top: 0.6rem; }
.callout-findings { margin: 0.3rem 0 0; padding-left: 1.2rem; }
.callout-findings li { margin-bottom: 0.2rem; }

/* Settings: an SSH public key, one long word that must wrap. */
code.public-key { display: block; overflow-wrap: anywhere; font-size: var(--text-xs); max-width: 28rem; }

/* The agent page (agent.html) and a skill's pages: the main skill and a
   reference file shown as the file itself, and "Repositories as a list". */
.main-skill-file, .skill-file, .repo-list-text { white-space: pre-wrap; overflow-wrap: anywhere; font-family: var(--font-mono); font-size: var(--text-sm); }
.repo-list-text { width: 100%; }
.row-form { display: inline; margin-left: 0.5rem; }
.typed-decision { padding: 0.75rem 1rem; border: 1px dashed var(--color-border); border-radius: var(--radius-md); }
.typed-text { white-space: pre-wrap; overflow-wrap: anywhere; font-family: var(--font-mono); font-size: var(--text-sm); }
.approve-ready { margin-bottom: 1rem; }

/* Import from Git: the proposal page's items (agent_import.html). */
.import-change { border-top: 1px solid var(--color-border); padding: 0.75rem 0; }
.import-change-head { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: baseline; }
.import-file { margin: 0.5rem 0 0 1.5rem; }
.import-notes ul { margin: 0.25rem 0 0; }
.import-warning {
  border-left: 3px solid var(--color-attention-fg);
  background: var(--color-attention-bg);
  color: var(--color-attention-fg);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 0.4rem 0.9rem;
  margin: 0.4rem 0;
}

/* ============================================================
   RUN PAGE — THE TO-DO LIST (2026-09-18 design, "The look"): the
   run-page rebuild's own regions — a right-hand rail holding the to-do
   list beside the map (§1, §4), the to-do list and stage notes, the
   requirement story, the stage band row, and the activity feed. §5:
   fewer boxes — only the map and the decision box are cards; everything
   below is a plain list on the page background.
   ============================================================ */

/* State tone: colour and background from the state tokens above, nothing
   else — the to-do tag, a story row's highlight, a band's progress fill
   and the feed all read one of these five. */
.tone-needs { color: var(--state-needs); background: var(--state-needs-soft); }
.tone-working { color: var(--state-working); background: var(--state-working-soft); }
.tone-done { color: var(--state-done); background: var(--state-done-soft); }
.tone-failing { color: var(--state-failing); background: var(--state-failing-soft); }
.tone-idle { color: var(--state-idle); background: var(--state-idle-soft); }

/* U1 — the action must be on the first screen: a right-hand rail on wide
   screens keeps the to-do list beside the map and the decision pinned to
   the rail's bottom, so a long-lived run's Approve button never falls
   below the fold; below 1100px there is one column with the action before
   the picture. The head, the map and the rail sit in .run-top; the
   selected stage's document (#doc) comes after it — never in the rail. */

/* The document: below 1100px it follows the map (order 0, after the map in
   the markup, before the feed's 1); from 1100px it is the row under
   .run-top, the page's full width, so a diff or the numbered output reads
   at that width and the rail — sticky only within .run-top — never slides
   over it. With nothing to show it takes no room at all. */

/* No decision to make (a finished run, a stage no one has submitted): the
   empty aside draws no box, no rule and no gap. */

/* Nothing in the rail is wider than the rail: its words wrap anywhere, its
   lists indent inside it, and a preformatted block or a table scrolls in
   its own box. (Inherited through the rail's display: contents below
   1100px as well.) */

/* U3, U10: the stage band row replaces the stage tabs on a run with no
   chain too — drawn as a pipeline stepper (visual theme Task 9): a
   connected node per band (stepArt, viz.go's stepperOf), the same link,
   title and word every band always carried, centred underneath it. */

/* U12: the activity feed — grouped by attempt, newest 15, "Show all". */
.activity { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }

/* A band's state in its own tone (the .band rule above sets the base). */

.status-line a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.status-line a:hover { text-decoration: underline; }



/* The decisions in the notes: the title and the person's answer, the
   rejected alternatives folded. */

.doc-fold > summary { cursor: pointer; font-weight: 600; padding: 0.5rem 0; }
.doc-fold[open] > summary { margin-bottom: 0.5rem; }
.activity h2 { font-size: var(--text-lg); line-height: 24px; margin: 0 0 var(--space-3); }
.activity-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }

/* run page rules */
/* A finding's rule chip (spec §9): the rule number only, linked to its own
   page — the same chip on the to-do list and the Findings pane. */
.rule-chip {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  padding: 0 6px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong);
  color: var(--color-text-secondary);
  text-decoration: none;
  white-space: nowrap;
}
.rule-chip:hover, .rule-chip:focus-visible { color: var(--color-accent); border-color: var(--color-accent); }
.finding-top .rule-chip { margin-left: 0.4rem; }
/* Retired: still linked to its record, marked so, in a quieter tone. */
.rule-chip-retired { border-style: dashed; color: var(--color-text-tertiary); }
.rule-chip-retired:hover, .rule-chip-retired:focus-visible { color: var(--color-accent); border-color: var(--color-accent); }
/* Unknown: a citation naming a number the organisation has never used —
   never a link, and toned like the negative badges so it reads as a
   problem with the citation, not an ordinary chip. */
.rule-chip-unknown { cursor: help; background: var(--color-negative-bg); color: var(--color-negative-fg); border-color: var(--color-negative-border); }

/* A branch review's finding marks (/reviews/{id}, learning-reviewer slice 2):
   who marked a finding how, their note, the no-code notice above the
   findings, and the one Save marks form under them. */
.review-no-code { margin: 0 0 0.6rem; }
.review-mark { margin: 0.6rem 0 0; font-size: var(--text-sm); font-weight: 500; color: var(--color-text-secondary); }
.review-mark-note { margin: 0.35rem 0 0; padding-left: 0.75rem; border-left: 2px solid var(--color-border-strong); color: var(--color-text-secondary); font-size: var(--text-sm); white-space: pre-wrap; }
/* The review page's one decision block (p2 D10, review.html): the checklist,
   the comment and the verdict buttons in one rail card, whose form the
   finding cards' marks join. The buttons wrap, never overflow the rail. */
.review-decision .panel-body { display: grid; gap: var(--space-3); }
.review-decision-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.review-details-h { margin: var(--space-4) 0 var(--space-2); font-size: var(--text-sm); }
/* "Review a branch" on Reviews: a link, not a primary button (p2 D12). */
/* Drawn as a secondary pill button (portal-site-theme review): it opens a
   form, so it reads as an action, not a stray link under the lists. */
.review-new > summary.review-new-link { display: inline-flex; align-items: center; height: var(--control-height); padding: 0 var(--space-4); list-style: none; cursor: pointer; border: 1px solid var(--color-border-control); border-radius: var(--radius-pill); background: var(--color-surface); color: var(--color-text); font-size: var(--text-sm); font-weight: 600; }
.review-new > summary.review-new-link::-webkit-details-marker { display: none; }
.review-new > summary.review-new-link:hover { background: var(--color-surface-sunken); }

/* "Make this a rule" (learning-reviewer slice 2, task E7): a receipt of a
   rule already suggested from a finding's mark note or a comment, or the
   link that drafts one — shown after the item's note, on the to-do list, a
   comment and a branch review's finding card alike. */
.rule-receipt, .make-rule { display: inline-block; margin-top: 0.2rem; font-size: var(--text-xs); }
.rule-receipt { color: var(--color-text-tertiary); }
.make-rule { color: var(--color-accent); }
.make-rule:hover, .make-rule:focus-visible { text-decoration: underline; }
.make-rule-heading { font-weight: 600; margin: 0 0 0.3rem; }

/* An agent's and a skill's history (learning-reviewer slice 3): each
   version's line with its revert form at the end of it, and what changed
   besides the text on its own lines above the diff. */
.history-version .history-revert { margin-left: auto; }
.history-change { margin: 0.35rem 0 0; color: var(--color-text-secondary); }

/* Impact preview (F3): a rule's or a suggestion's one line, how often its
   globs applied to the owner's recent changes. */
.impact { margin: 0.2rem 0 0; color: var(--color-text-tertiary); font-size: var(--text-sm); }

/* Settings › Integrations (task A4): the watch and mode forms are compact
   inline rows, not the stacked .field layout the rest of Settings uses —
   several sit one after another per installation. */
.watch-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.6rem;
  margin: 0 0 0.75rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: 6px;
}
.watch-form .field { margin: 0; }
/* The GitLab token form sits flush in its panel, a hairline above (VD-17). */
.watch-form-flush { border-width: 1px 0 0; border-radius: 0; padding: var(--space-3) 0 0; }
.watch-form .row-title { font-weight: 600; margin-right: 0.4rem; align-self: center; }
.mode-form { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.mode-form select { width: auto; }
/* First-run model onboarding (task A8): a model endpoint's test result, and the
   provider preset list on the add form. */
.check-ok { color: var(--color-positive-fg); }
.check-warn { color: var(--color-attention-fg); }
.check-fail { color: var(--color-negative-fg); }
.preset-link {
  display: inline-block; padding: 0.2rem 0.6rem; border: 1px solid var(--color-border);
  border-radius: var(--radius-md); font-size: var(--text-sm); color: var(--color-text-secondary);
  text-decoration: none;
}
.preset-link:hover, .preset-link:focus-visible { background: var(--color-surface-sunken); color: var(--color-text); }

/* A Critical finding's badge (task R1, finding 2): Critical and Major both
   take severityTone's "negative" tone, so without this they render pixel
   for pixel identical apart from the word. This adds weight, not a new
   colour — no new badge tone. */

/* The review page (the 2026-09-23 design bar, §1.7) borrows the run page's
   .run-top / .run-rail grid so the facts, the way back to the change and
   Save marks sit on the first screen. Its left column is the findings, not
   a map: one class, the same two placements .run-map takes. */

/* A bare <h3> in a .panel-body used to render larger and heavier than the
   .panel-header <h2> above it, because the size rule only applies inside
   .panel-header — the hierarchy was inverted on the most-visited screen of
   the reviewer (the 2026-09-23 design bar, §1.3). This makes the mistake
   unrepeatable; a section inside a panel is a .section-label. */
.panel-body h3 { font-size: var(--text-md); }

/* A panel's own inset block: what a step has just found, set apart from the
   form that found it without being an error or a critique. Settings ›
   Integrations uses it for the checked GitLab token's group, handle, scopes
   and expiry — shown before anything is stored. */
.panel-inset {
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.75rem 0.9rem;
  margin: 0.9rem 0;
}
.panel-inset > :first-child { margin-top: 0; }
.panel-inset > :last-child { margin-bottom: 0; }

/* MCP connections — Settings › Connections and the agent page's Tools. */
.conn-meta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; margin: 0 0 var(--space-6); }
.conn-meta form { margin: 0; }
.meta-sep { color: var(--color-text-tertiary); margin: 0 var(--space-1); }
.test-result { display: flex; align-items: center; gap: var(--space-2); font-weight: 500; }
.tool-mark { color: var(--color-text-secondary); white-space: nowrap; }
.tool-desc { max-width: 60ch; }
.tool-names { color: var(--color-text-secondary); font-size: var(--text-sm); }
.tool-builtin { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; padding: 0 0 var(--space-3); margin-bottom: var(--space-3); border-bottom: 1px solid var(--color-border); }
.tool-builtin .tool-names { margin-left: auto; font-family: var(--font-mono); font-size: var(--text-xs); }
.tool-tick { margin-bottom: var(--space-2); }
.tool-tick .field-hint { margin: 0 0 0 1.5rem; }
.tool-ticks { padding: var(--space-3) 0 0; }
/* A ticked tool (Add tools): a filled surface with the agents area's
   hairline, so the ticked set reads at a glance. */
.tool-tick-on { background: var(--color-surface-sunken); border: 1px solid var(--area-agents); border-radius: var(--radius-sm); padding: var(--space-1) var(--space-2); }
.tool-tick-all { margin: 0 0 var(--space-2); font-size: var(--text-sm); }
.change-tools-row details { margin: 0; }
/* The agent setup flow (/agents/{id}/setup): its stepper and actions. */
.setup-stepper { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); list-style: none; margin: 0 0 var(--space-4); padding: 0; font-size: var(--text-sm); color: var(--color-text-secondary); }
.setup-stepper .setup-step-now, .setup-stepper .setup-step-now a { color: var(--color-accent); font-weight: 600; }
.setup-stepper .setup-step-done, .setup-stepper .setup-step-done a { color: var(--color-positive-fg); }
.setup-stepper .setup-step-next, .setup-stepper .setup-step-next a { color: var(--color-text-tertiary); }
.setup-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-2); margin: 0 0 var(--space-3); }
.setup-choices { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin: 0 0 var(--space-3); }
.setup-model-options { border: 0; margin: 0 0 var(--space-3); padding: 0; min-width: 0; }
.setup-model-options legend { padding: 0; margin-bottom: var(--space-2); font-size: var(--text-sm); font-weight: 500; color: var(--color-text-secondary); }
.setup-model-options .field-check { display: flex; align-items: center; gap: var(--space-2); }
.setup-choices .setup-choice-now { color: var(--color-accent); font-weight: 600; }
.setup-cards { display: grid; gap: var(--space-3); margin: 0; }
.setup-card { border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-3); }
.setup-card.is-done { border-color: var(--color-positive-border); }
.setup-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; margin-top: var(--space-3); }
.nowrap { white-space: nowrap; }

/* ============================================================
   CHAT (portal.js's chatPanel; spec 2026-09-26-chat-design, redrawn as
   a popup in chat T8): a pill launcher bottom-right on every page, a
   380px floating card that overlays the page (never pushes it), and
   /chat's own two-column page drawing the same fragment. An 8px grid:
   12px panel padding, 12px between messages. Every colour is a shared
   token above, defined for light and redefined for dark.
   ============================================================ */

/* ---- the launcher ---- */
.chat-launcher {
  position: fixed;
  right: var(--space-4);
  bottom: var(--space-4);
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 44px;
  padding: 0 var(--space-5) 0 var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--color-accent-solid);
  color: var(--color-on-accent-solid);
  font-size: var(--text-md);
  font-weight: 500;
  box-shadow: var(--shadow-float);
}
.chat-launcher:hover { background: var(--color-accent-solid-hover); text-decoration: none; }
.chat-launcher:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }
.chat-launcher .chat-icon { width: 18px; height: 18px; }
.chat-launcher-dot {
  position: absolute;
  top: 2px;
  right: 4px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--state-needs);
  border: 2px solid var(--color-surface);
}
.chat-launcher-dot[hidden] { display: none; }
body.chat-open .chat-launcher { display: none; }
/* /chat is the chat already: no launcher over its own composer. */
body:has(.chat-page) .chat-launcher { display: none; }

/* ---- the popup: a floating card over the page ---- */
.chat-dock {
  position: fixed;
  right: var(--space-4);
  bottom: var(--space-4);
  z-index: 40;
  width: 380px;
  height: min(560px, calc(100vh - 96px));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-float);
}
.chat-dock[hidden] { display: none; }
/* VD-14: from 1280px an open popup docks as a 400px right rail and the
   page makes room for it, so it never covers the page it came from. */
@media (min-width: 1280px) {
  .chat-dock { top: 0; right: 0; bottom: 0; width: 400px; height: auto; border-width: 0 0 0 1px; border-radius: 0; box-shadow: none; }
  /* body.chat-open is set by portal.js; the :has rule is the same thing
     for a browser that has no script running yet. */
  body.chat-open .main { padding-right: 400px; }
  body:has(.chat-dock:not([hidden])) .main { padding-right: 400px; }
}
/* UX review H4: below 1280px the launcher is the 44px icon circle (its words
   stay for a screen reader), so it covers as little of the page as it can. */
@media (min-width: 768px) and (max-width: 1279px) {
  .chat-launcher { width: 44px; padding: 0; justify-content: center; }
  .chat-launcher .chat-icon { width: 22px; height: 22px; }
  .chat-launcher-text { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
/* UX-15: the popup's frame and a skeleton are in the page's own markup, so
   opening it never shows an empty card while the first fragment loads. */
.chat-skeleton { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4); flex: 1 1 auto; }
.chat-skel-line { display: block; height: 14px; border-radius: var(--radius-sm); background: var(--color-surface-sunken); animation: chat-skel-pulse 1.4s ease-in-out infinite; }
.chat-skel-short { width: 55%; }
@keyframes chat-skel-pulse { 50% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) { .chat-skel-line { animation: none; } }
/* Under 768px the popup is a full-screen sheet. */
@media (max-width: 767px) {
  .chat-dock { inset: 0; width: auto; height: auto; border: 0; border-radius: 0; padding-bottom: env(safe-area-inset-bottom, 0px); }
  /* On a phone the launcher is a 44px icon-only circle (its words stay for
     a screen reader), lifted clear of the home bar. */
  .chat-launcher { right: var(--space-3); bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0px)); width: 44px; height: 44px; padding: 0; justify-content: center; }
  .chat-launcher .chat-icon { width: 22px; height: 22px; }
  .chat-launcher-text { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
/* The open sheet holds the page still behind it (portal.js makes the page
   inert too). */
html.chat-sheet-open, html.chat-sheet-open body { overflow: hidden; }

.chat-icon { width: 16px; height: 16px; flex: none; }

/* ---- the fragment ---- */
.chat {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  background: var(--color-surface);
}
.chat:focus { outline: none; }
/* The header is a grid so the cluster chip, on its own row under the
   agent's name, can run under the actions too — the popup is only 380px:
   [back] [avatar] [name ............] [ring … – ×]
                   [chip ...................................] */
.chat-head {
  position: relative;
  z-index: 2;
  flex: none;
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  align-items: center;
  min-height: 60px;
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border);
}
.chat-head > .chat-back { grid-column: 1; grid-row: 1 / span 2; margin: 0 2px 0 calc(-1 * var(--space-1)); }
.chat-head > .chat-avatar { grid-column: 2; grid-row: 1 / span 2; margin-right: var(--space-2); }
.chat-head-main { display: contents; }
.chat-head-main > .chat-title { grid-column: 3; grid-row: 1; }
.chat-head-main > .chat-subtitle, .chat-head-main > .chat-cluster { grid-column: 3 / 5; grid-row: 2; justify-self: start; min-width: 0; max-width: 100%; }
.chat-head-main > .chat-cluster { margin-left: -6px; }
.chat-head-actions { grid-column: 4; grid-row: 1; }
/* A header with no second row (the start screen, the history list): the
   title and the actions centre on the avatar. */
.chat-head:not(:has(.chat-cluster, .chat-subtitle)) .chat-head-main > .chat-title,
.chat-head:not(:has(.chat-cluster, .chat-subtitle)) > .chat-head-actions { grid-row: 1 / span 2; align-self: center; }
.chat-title {
  max-width: 100%;
  font-size: var(--text-md);
  line-height: 20px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-subtitle {
  max-width: 100%;
  font-size: var(--text-xs);
  line-height: 16px;
  color: var(--color-text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-head-actions { display: flex; align-items: center; gap: 0; margin-left: var(--space-2); }

.chat-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text-secondary);
  cursor: pointer;
  list-style: none;
}
.chat-icon-btn::-webkit-details-marker { display: none; }
.chat-icon-btn:hover { background: var(--color-surface-sunken); color: var(--color-text); text-decoration: none; }
.chat-icon-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.chat-icon-btn .chat-icon { width: 18px; height: 18px; }

.chat-avatar {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-accent-soft);
  color: var(--color-accent);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
}
.chat-avatar .chat-icon { width: 18px; height: 18px; }
.chat-avatar-lg { width: 48px; height: 48px; font-size: var(--text-lg); }

/* ---- popovers: the "…" menu and the cluster chip's menu ---- */
.chat-menu, .chat-cluster { position: relative; }
.chat-menu > summary, .chat-cluster > summary { list-style: none; }
.chat-menu > summary::-webkit-details-marker, .chat-cluster > summary::-webkit-details-marker { display: none; }
.chat-menu[open] > summary { background: var(--color-surface-sunken); color: var(--color-text); }
.chat-pop {
  position: absolute;
  top: calc(100% + 6px);
  z-index: 5;
  min-width: 220px;
  max-width: 300px;
  padding: 6px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
}
.chat-menu-pop { right: 0; }
.chat-cluster-pop { left: -4px; }
.chat-pop form { margin: 0; }
.chat-pop-head { margin: 0; padding: 6px 8px 4px; font-size: var(--text-xs); line-height: 16px; font-weight: 500; color: var(--color-text-tertiary); }
.chat-pop-list { list-style: none; margin: 0; padding: 0; }
.chat-pop-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2);
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: var(--text-sm);
  line-height: 20px;
  text-align: left;
  cursor: pointer;
}
.chat-pop-item:hover { background: var(--color-surface-sunken); text-decoration: none; }
.chat-pop-item:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.chat-pop-item .chat-icon { color: var(--color-text-secondary); }
.chat-pop-item[aria-current] { font-weight: 500; }
.chat-pop-item[aria-current] .chat-icon { color: var(--color-accent); margin-left: auto; }
.chat-pop-item[disabled] { color: var(--color-text-tertiary); cursor: default; }
.chat-pop-item[disabled]:hover { background: transparent; }
.chat-pop-text { display: flex; flex-direction: column; min-width: 0; }
.chat-pop-sub { font-size: var(--text-xs); line-height: 16px; font-weight: 400; color: var(--color-text-tertiary); }

/* The cluster chip: the chat's one cluster, under the agent's name. */
.chat-cluster-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  min-height: 24px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  font-size: var(--text-xs);
  line-height: 16px;
  cursor: pointer;
}
.chat-cluster-chip:hover, .chat-cluster[open] > .chat-cluster-chip { background: var(--color-surface-sunken); color: var(--color-text); }
.chat-cluster-chip:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 0; }
.chat-cluster-chip .chat-icon { width: 13px; height: 13px; flex: none; }
/* The chip's dot: Production red, as its badge, another environment
   grey, Any cluster an empty ring. */
.chat-cluster-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--state-idle); }
.chat-cluster-dot[data-env="production"] { background: var(--state-failing); }
.chat-cluster-dot[data-env=""] { background: transparent; box-shadow: inset 0 0 0 1.5px var(--state-idle); }
.chat-cluster-label { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-cluster-env { color: var(--color-text-tertiary); white-space: nowrap; }
.chat-cluster-static .chat-cluster-chip { cursor: default; }
.chat-cluster-static .chat-cluster-chip:hover { background: transparent; color: var(--color-text-secondary); }
/* Production, said in words and the danger colour wherever a cluster is
   named: the chip, its menu and the change card's target. */
.env-badge {
  display: inline-flex;
  align-items: center;
  flex: none;
  margin-left: var(--space-1);
  padding: 0 var(--space-1);
  border: 1px solid color-mix(in srgb, var(--state-failing) 40%, transparent);
  border-radius: var(--radius-sm);
  background: var(--state-failing-soft);
  color: var(--state-failing);
  font-size: var(--text-2xs);
  line-height: 16px;
  font-weight: 600;
  white-space: nowrap;
}
.chat-pop-item .chat-cluster-dot { margin: 0 2px; }
.chat-pop-item .chat-pop-text .env-badge { align-self: flex-start; margin: 2px 0 0; }

/* ---- the context ring (R4): tenths by class, tone by data-tone ---- */
/* The ring's hover hangs from the header's own bottom edge (the ring is
   not positioned), so it never covers the cluster chip under the name. */
.ctx-ring {
  position: static;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 32px;
  padding: 0 3px;
  border-radius: var(--radius-md);
  color: var(--color-text-secondary);
  font-size: var(--text-xs);
}
.ctx-ring:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.ctx-ring-svg { display: block; width: 26px; height: 26px; flex: none; }
.ctx-ring-track, .ctx-ring-fill { fill: none; stroke-width: 3; }
.ctx-ring-track { stroke: var(--color-border); }
.ctx-ring-fill { stroke: var(--color-accent); stroke-dasharray: 0 100; }
.ctx-ring-num { fill: var(--color-text-secondary); font-size: var(--text-xs); font-weight: 600; font-variant-numeric: tabular-nums; }
.ctx-ring[data-tone="amber"] .ctx-ring-num { fill: var(--state-needs); }
.ctx-ring[data-tone="red"] .ctx-ring-num { fill: var(--state-failing); }
.ctx-ring[data-tone="amber"] .ctx-ring-fill { stroke: var(--state-needs); }
.ctx-ring[data-tone="red"] .ctx-ring-fill { stroke: var(--state-failing); }
.ctx-ring-fill.ctx-p0 { stroke-dasharray: 0 100; }
.ctx-ring-fill.ctx-p1 { stroke-dasharray: 10 100; }
.ctx-ring-fill.ctx-p2 { stroke-dasharray: 20 100; }
.ctx-ring-fill.ctx-p3 { stroke-dasharray: 30 100; }
.ctx-ring-fill.ctx-p4 { stroke-dasharray: 40 100; }
.ctx-ring-fill.ctx-p5 { stroke-dasharray: 50 100; }
.ctx-ring-fill.ctx-p6 { stroke-dasharray: 60 100; }
.ctx-ring-fill.ctx-p7 { stroke-dasharray: 70 100; }
.ctx-ring-fill.ctx-p8 { stroke-dasharray: 80 100; }
.ctx-ring-fill.ctx-p9 { stroke-dasharray: 90 100; }
.ctx-ring-fill.ctx-p10 { stroke-dasharray: 100 100; }
.ctx-hover {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: var(--space-2);
  z-index: 5;
  width: 260px;
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  box-shadow: var(--shadow-pop);
  font-size: var(--text-xs);
  line-height: 18px;
  white-space: normal;
  pointer-events: none;
}
.ctx-ring:hover .ctx-hover, .ctx-ring:focus-within .ctx-hover { display: block; }
/* Escape dismisses the breakdown and keeps focus on the ring. */
.ctx-ring[data-dismissed] .ctx-hover { display: none; }
.ctx-hover-title { margin: 0 0 var(--space-1); font-size: var(--text-sm); font-weight: 500; color: var(--color-text); }
.ctx-hover-line { margin: 0; }

/* ---- a body that scrolls: start screen, empty chat, history ---- */
.chat-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-4) var(--space-3);
}
.chat-start-title { margin: 0 var(--space-1) var(--space-3); font-size: var(--text-lg); line-height: 24px; font-weight: 600; }
.chat-agents { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.chat-agent-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  color: var(--color-text);
}
.chat-agent-card:hover { border-color: var(--color-border-strong); background: var(--color-surface-sunken); text-decoration: none; }
.chat-agent-card:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }
.chat-agent-card > .chat-icon { color: var(--color-text-tertiary); }
.chat-agent-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.chat-agent-name { font-size: var(--text-md); line-height: 20px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-agent-line { font-size: var(--text-xs); line-height: 16px; color: var(--color-text-secondary); }
.chat-start-sub { margin: var(--space-5) var(--space-1) var(--space-1); font-size: var(--text-xs); line-height: 16px; font-weight: 600; color: var(--color-text-secondary); }
.chat-recent { list-style: none; margin: 0; padding: 0; }
.chat-recent-item {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  color: var(--color-text);
  font-size: var(--text-sm);
  line-height: 20px;
}
.chat-recent-item:hover { background: var(--color-surface-sunken); text-decoration: none; }
.chat-recent-title { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-recent-age { flex: none; font-size: var(--text-xs); color: var(--color-text-tertiary); }
.chat-see-all { margin: var(--space-2) var(--space-2) 0; font-size: var(--text-sm); }

.chat-empty { display: flex; flex-direction: column; align-items: center; text-align: center; padding-top: var(--space-8); }
.chat-empty-name { margin: var(--space-3) 0 var(--space-1); font-size: var(--text-lg); line-height: 24px; font-weight: 600; }
.chat-empty-hint { max-width: 32ch; margin: 0 0 var(--space-5); font-size: var(--text-sm); line-height: 20px; color: var(--color-text-secondary); }
.chat-suggestions { list-style: none; margin: 0; padding: 0; width: 100%; display: flex; flex-direction: column; gap: var(--space-2); }
.chat-suggestion {
  display: block;
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  color: var(--color-text);
  font-size: var(--text-sm);
  line-height: 20px;
  text-align: left;
}
.chat-suggestion:hover { border-color: var(--color-accent); background: var(--color-accent-soft); text-decoration: none; }

/* ---- the thread ---- */
.chat-thread {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-4) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  overscroll-behavior: contain;
}
/* A short thread sits at the bottom, by the composer, as a chat does. */
.chat-thread > :first-child { margin-top: auto; }
.chat-group { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.chat-group-person { align-items: flex-end; }
.chat-group-agent { align-items: flex-start; }
.chat-msg {
  max-width: 88%;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--color-text);
  overflow-wrap: anywhere;
}
.chat-person { max-width: 80%; background: var(--color-accent-soft); border-radius: var(--radius-lg) var(--radius-lg) var(--radius-sm) var(--radius-lg); }
.chat-agent { background: var(--color-surface-sunken); border-radius: var(--radius-lg) var(--radius-lg) var(--radius-lg) var(--radius-sm); }
.chat-failed { background: var(--state-failing-soft); }
.chat-text { margin: 0; white-space: pre-wrap; }
.chat-meta { margin: 0; padding: 0 var(--space-1); font-size: var(--text-2xs); line-height: 16px; color: var(--color-text-tertiary); }
.chat-retry { margin: 0; }
.chat-stopped { margin: 0; padding: 0 var(--space-1); font-size: var(--text-xs); color: var(--state-needs); }

/* ---- a goal's card in a chat (agent sessions): head, plan, budget, the
   question it waits on; its live parts sit in .chat-live ---- */
.goal-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
.chat-live .goal-card { margin: var(--space-2) 0 0; }
.goal-card[data-state="waiting"] { border-color: var(--color-attention-border); }
.goal-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: 0; }
.goal-title { overflow-wrap: anywhere; }
.goal-now { margin: 0; font-size: var(--text-sm); color: var(--color-text); }
.goal-plan { margin: 0; padding-left: var(--space-5); font-size: var(--text-sm); color: var(--color-text-secondary); }
.goal-plan li[data-status="doing"] { color: var(--color-text); font-weight: 600; }
.goal-plan li[data-status="done"] { color: var(--color-text-tertiary); }
.goal-plan li[data-status="dropped"] { color: var(--color-text-tertiary); text-decoration: line-through; }
.goal-helpers { margin: 0; padding-left: var(--space-5); font-size: var(--text-sm); color: var(--color-text-secondary); }
.goal-helpers .goal-helpers { margin-top: var(--space-1); }
.goal-helpers details { margin-top: var(--space-1); }
.goal-helper-n { color: var(--color-text-tertiary); }
.goal-budget { margin: 0; font-size: var(--text-xs); line-height: 16px; color: var(--color-text-tertiary); }
.goal-question { margin: 0; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); background: var(--color-attention-bg); color: var(--color-text); overflow-wrap: anywhere; }
/* the approval card inside a goal's card, and the decided actions' lines */
.action-card { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3); border: 1px solid var(--color-attention-border); border-radius: var(--radius-sm); background: var(--color-surface); min-width: 0; }
.action-args { margin: 0; max-height: 240px; overflow: auto; padding: var(--space-2); border-radius: var(--radius-sm); background: var(--color-bg); font-size: var(--text-xs); white-space: pre; }
.action-meta { margin: 0; font-size: var(--text-xs); line-height: 16px; color: var(--color-text-tertiary); }
.action-form { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; margin: 0; }
.action-form input[type="text"] { flex: 1 1 160px; min-width: 0; }
.action-line { font-size: var(--text-sm); color: var(--color-text-secondary); overflow-wrap: anywhere; }
.goal-actions { display: flex; gap: var(--space-2); }
.goal-actions form { margin: 0; }
.chat-compose .chat-goal-start { margin-top: var(--space-2); }
.chat-unchecked {
  margin: 0 0 var(--space-2);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--color-attention-bg);
  color: var(--color-attention-fg);
  font-size: var(--text-xs);
}

/* A reply's markdown, sized for a bubble. */
.markdown-body.chat-md { max-width: none; font-size: var(--text-md); line-height: 1.5; }
.markdown-body.chat-md > :first-child { margin-top: 0; }
.markdown-body.chat-md > :last-child { margin-bottom: 0; }
.markdown-body.chat-md p { margin: 0 0 var(--space-2); }
.markdown-body.chat-md h1, .markdown-body.chat-md h2, .markdown-body.chat-md h3, .markdown-body.chat-md h4 {
  margin: var(--space-3) 0 var(--space-1);
  font-size: var(--text-md);
  line-height: 20px;
  font-weight: 600;
}
.markdown-body.chat-md ul, .markdown-body.chat-md ol { margin: 0 0 var(--space-2); padding-left: 20px; }
.markdown-body.chat-md li { margin: 2px 0; }
.markdown-body.chat-md li > p { margin: 0; }
.markdown-body.chat-md code {
  padding: 1px 5px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  font-size: 0.86em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
.markdown-body.chat-md pre {
  margin: 0 0 var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  overflow-x: auto;
  font-size: var(--text-xs);
  line-height: 1.5;
}
.markdown-body.chat-md pre code { padding: 0; border: 0; background: none; font-size: inherit; }
.chat-section { margin: var(--space-2) 0 var(--space-1); font-size: var(--text-xs); line-height: 16px; font-weight: 600; color: var(--color-text-secondary); }
.chat-checked { margin-top: var(--space-2); padding-top: var(--space-1); border-top: 1px solid var(--color-border); }
.chat-checked .markdown-body.chat-md { font-size: var(--text-sm); color: var(--color-text-secondary); }

/* The change card: the target, each field before → after, the command to
   run (Copy) and the patch folded — as wide as the reply it belongs to. */
.chat-card {
  align-self: flex-start;
  width: 100%;
  max-width: 88%;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}
.chat-main-pane .chat-card { max-width: min(88%, 720px); }
.chat-card-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--text-sm);
  line-height: 20px;
}
.chat-card-head > .chat-icon:first-child { color: var(--color-accent); }
.chat-card-title { font-weight: 500; }
.chat-card-sub { font-size: var(--text-xs); color: var(--color-text-tertiary); }
.chat-card-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
}
.chat-card-target { margin: 0; font-size: var(--text-sm); line-height: 20px; overflow-wrap: anywhere; }
.chat-card-k { margin-right: var(--space-1); font-size: var(--text-xs); font-weight: 600; color: var(--color-text-secondary); }
.chat-card-rows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--text-sm); line-height: 20px; }
.chat-card-rows li { overflow-wrap: anywhere; }
.chat-card-field { font-size: var(--text-xs); }
.chat-card-before { color: var(--color-text-secondary); text-decoration: line-through; }
.chat-card-arrow { color: var(--color-text-tertiary); }
.chat-card-after { font-weight: 600; }
.kh-reason { margin: 0; font-size: var(--text-sm); line-height: 20px; overflow-wrap: anywhere; }
.kh-note { margin: 0; font-size: var(--text-xs); color: var(--color-text-tertiary); }
.kh-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.kh-card .diff-table { font-size: var(--text-xs); }
.chat-card-warn, .chat-card-missing {
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background: var(--state-needs-soft);
  color: var(--state-needs);
  font-size: var(--text-xs);
  line-height: 18px;
}
.chat-card-cmd .chat-section { margin-top: 0; }
/* The command is read before it is run: it wraps rather than hides. */
.chat-card-cmd pre { white-space: pre-wrap; overflow-wrap: anywhere; }
.chat-card-patch > summary { display: inline-flex; align-items: center; gap: var(--space-1); cursor: pointer; list-style: none; font-size: var(--text-xs); font-weight: 600; color: var(--color-text-secondary); }
.chat-card-patch > summary::-webkit-details-marker { display: none; }
.chat-card-patch > summary .chat-icon { width: 14px; height: 14px; transition: transform 120ms ease; }
.chat-card-patch[open] > summary .chat-icon { transform: rotate(90deg); }
.chat-card-hint { margin: var(--space-1) 0 0; font-size: var(--text-xs); line-height: 16px; color: var(--color-text-tertiary); }
.chat-card-patch > .chat-code { margin-top: var(--space-2); }
.chat-risks-label { color: var(--state-needs); }
.chat-code { position: relative; }
.chat-code pre {
  margin: 0;
  padding: var(--space-3);
  padding-right: 64px;
  border-radius: var(--radius-md);
  background: var(--color-surface-sunken);
  overflow-x: auto;
  font-size: var(--text-xs);
  line-height: 1.5;
}
.chat-copy {
  position: absolute;
  top: 6px;
  right: 6px;
  height: 24px;
  padding: 0 var(--space-2);
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  font-size: var(--text-xs);
  font-weight: 500;
  cursor: pointer;
}
.chat-copy:hover { background: var(--color-surface-sunken); }
.chat-card-body .typed-text { margin: 0; font-family: var(--font-sans); font-size: var(--text-sm); line-height: 20px; }
.chat-risks .markdown-body.chat-md { font-size: var(--text-sm); }

/* What it read: one quiet folded line under a reply. */
/* An answer's attachments (agent tools §7.3) */
.chat-files { list-style: none; margin: var(--space-2) 0 0; padding: 0; max-width: 88%; display: flex; flex-direction: column; gap: 2px; font-size: var(--text-xs); }
.chat-file { overflow-wrap: anywhere; }
.chat-file-label { font-weight: 600; color: var(--color-text-secondary); }
.chat-file-meta { color: var(--color-text-tertiary); }
/* make_chart charts (agent tools spec §7.3): inline SVG drawn from
   classes only; the --chart-* and colour tokens carry light and dark */
.chat-file-chart { margin: var(--space-2) 0; }
.chat-chart { margin: 0; }
.chat-chart svg { display: block; width: 100%; max-width: 720px; height: auto; }
.chat-chart .ch-s1 { fill: var(--chart-1); } .chat-chart .ch-s2 { fill: var(--chart-2); } .chat-chart .ch-s3 { fill: var(--chart-3); }
.chat-chart .ch-s4 { fill: var(--chart-4); } .chat-chart .ch-s5 { fill: var(--chart-5); } .chat-chart .ch-s6 { fill: var(--chart-6); }
.chat-chart .ch-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chat-chart .ch-line.ch-s1 { stroke: var(--chart-1); } .chat-chart .ch-line.ch-s2 { stroke: var(--chart-2); } .chat-chart .ch-line.ch-s3 { stroke: var(--chart-3); }
.chat-chart .ch-line.ch-s4 { stroke: var(--chart-4); } .chat-chart .ch-line.ch-s5 { stroke: var(--chart-5); } .chat-chart .ch-line.ch-s6 { stroke: var(--chart-6); }
.chat-chart .ch-grid { fill: none; stroke: var(--color-border); stroke-width: 1; }
.chat-chart .ch-axis { fill: none; stroke: var(--color-border-strong); stroke-width: 1; }
.chat-chart .ch-text { fill: var(--color-text-secondary); font-family: var(--font-sans); font-size: 12px; }
.chat-chart .ch-title { fill: var(--color-text); font-size: 14px; font-weight: 600; }
.chat-chart-cap { margin-top: var(--space-1); }
.chat-chart-data { margin-top: var(--space-1); }
.chat-chart-data summary { cursor: pointer; color: var(--color-text-secondary); }
.chat-chart-data table.data { margin-top: var(--space-1); font-size: var(--text-sm); }
.chat-reads { max-width: 88%; font-size: var(--text-xs); line-height: 16px; color: var(--color-text-tertiary); }
.chat-reads > summary {
  display: inline-flex;
  align-items: flex-start;
  gap: 6px;
  padding: 2px var(--space-1);
  border-radius: var(--radius-sm);
  cursor: pointer;
  list-style: none;
}
.chat-reads > summary::-webkit-details-marker { display: none; }
.chat-reads > summary:hover { color: var(--color-text-secondary); background: var(--color-surface-sunken); }
.chat-reads > summary .chat-icon { width: 14px; height: 14px; margin-top: 1px; }
.chat-reads-list {
  margin: var(--space-1) 0 0;
  padding: var(--space-2) var(--space-3) var(--space-2) 28px;
  border-radius: var(--radius-md);
  background: var(--color-surface-sunken);
  color: var(--color-text-secondary);
  overflow-wrap: anywhere;
}
.chat-reads-list code { font-size: var(--text-2xs); }

/* The quiet lines across the thread: a cluster change, a summary. */
.chat-note-line, .chat-divider > summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-1) 0;
  font-size: var(--text-xs);
  line-height: 16px;
  color: var(--color-text-tertiary);
  text-align: center;
}
.chat-note-line::before, .chat-note-line::after,
.chat-divider > summary::before, .chat-divider > summary::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--color-border);
}
.chat-divider { align-self: stretch; }
.chat-divider > summary { cursor: pointer; list-style: none; }
.chat-divider > summary::-webkit-details-marker { display: none; }
.chat-divider > summary:hover { color: var(--color-text-secondary); }
/* The summary is the portal's, not the agent's: a left rule on no fill,
   labelled, never a bubble. */
.chat-summary {
  margin: var(--space-2) 0 0;
  padding: var(--space-1) 0 var(--space-1) var(--space-3);
  border-left: 2px solid var(--color-border-strong);
}
.chat-summary-label { margin: 0 0 var(--space-1); font-size: var(--text-2xs); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-text-tertiary); }
.chat-summary .markdown-body { font-size: var(--text-sm); color: var(--color-text-secondary); }
.chat-divider-opened { display: none; }
.chat-divider[open] .chat-divider-closed { display: none; }
.chat-divider[open] .chat-divider-opened { display: inline; }
/* A failed summary is history here, a quiet line; its outcome is said
   by the composer when a person asked for it. */
.chat-divider-failed {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin: var(--space-1) 0;
  color: var(--color-text-tertiary);
  font-size: var(--text-xs);
  line-height: 16px;
  text-align: center;
}
.chat-divider-failed form { margin: 0; }

/* ---- live: one muted line with a spinner while it works ---- */
.chat-live { flex: none; padding: 0 var(--space-3); }
.chat-progress {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: 6px 0;
  font-size: var(--text-xs);
  line-height: 16px;
  color: var(--color-text-secondary);
}
.chat-compacting { flex: none; padding: 6px var(--space-3) 0; }
.chat-spinner {
  flex: none;
  width: 12px;
  height: 12px;
  border: 2px solid var(--color-border-strong);
  border-top-color: var(--state-working);
  border-radius: 50%;
  animation: chat-spin 0.8s linear infinite;
}
@keyframes chat-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .chat-spinner { animation-duration: 2.4s; }
}
/* A failure notice stops the spinner: nothing is being followed. */
.chat[data-stalled] .chat-live .chat-progress { display: none; }
.ctx-note { margin: 0; padding: 6px 0 0; font-size: var(--text-xs); line-height: 16px; color: var(--color-text-secondary); }
.chat-live[data-tone="amber"] .ctx-note { color: var(--state-needs); }
.chat-live[data-tone="red"] .ctx-note { color: var(--state-failing); }

/* ---- the composer: a rounded box, a growing textarea, a round send ---- */
.chat-composer { flex: none; padding: var(--space-2) var(--space-3) var(--space-3); background: var(--color-surface); }
.chat-composer .form-error { margin: 0 0 var(--space-2); }
/* A failure, said by the composer: what happened and the one way on. */
.chat-notice {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background: var(--state-needs-soft);
  color: var(--state-needs);
  font-size: var(--text-xs);
  line-height: 18px;
}
.chat-notice[hidden] { display: none; }
.chat-notice form { margin: 0; }
.chat-notice-text { flex: 1 1 12rem; margin: 0; }
.chat-notice .btn[hidden] { display: none; }
.chat-visibility { margin: var(--space-4) var(--space-1) 0; font-size: var(--text-xs); line-height: 16px; color: var(--color-text-tertiary); }
.chat-composer .refusal-note { margin: 0; padding: var(--space-2) var(--space-1); }
.chat-compose { margin: 0; }
.chat-compose-box {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-1) var(--space-1) var(--space-4);
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
}
.chat-compose-box:hover { border-color: var(--color-border-control-hover); }
.chat-compose-box:focus-within {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 22%, transparent);
}
.chat-compose-box textarea {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 20px;
  max-height: 128px;
  margin: 0;
  padding: 6px 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--color-text);
  font: inherit;
  font-size: var(--text-md);
  line-height: 20px;
  resize: none;
  overflow-y: auto;
  field-sizing: content;
}
.chat-compose-box textarea:focus, .chat-compose-box textarea:hover { border: 0; box-shadow: none; outline: none; }
.chat-compose-box textarea::placeholder { color: var(--color-text-tertiary); }
.chat-compose-box textarea[disabled] { background: transparent; }
.chat-send {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--color-accent-solid);
  color: var(--color-on-accent-solid);
  cursor: pointer;
}
.chat-send:hover { background: var(--color-accent-solid-hover); }
.chat-send:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
/* One resting state everywhere: dim until there is something to send. */
.chat-send[disabled],
.chat-compose-box:has(textarea:placeholder-shown) .chat-send { background: var(--color-border-strong); color: var(--color-surface); cursor: default; }
.chat-send .chat-icon { width: 18px; height: 18px; }

/* ---- the chat list: /chat's left column, and the popup's history ---- */
.chat-list { display: flex; flex-direction: column; gap: var(--space-3); }
.chat-list-top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.chat-seg { display: inline-flex; margin: 0; padding: 2px; border-radius: var(--radius-md); background: var(--color-surface-sunken); }
.chat-seg > a, .chat-seg > span { padding: 2px var(--space-3); border-radius: var(--radius-sm); font-size: var(--text-xs); line-height: 18px; font-weight: 500; color: var(--color-text-secondary); }
.chat-seg > a:hover { color: var(--color-text); text-decoration: none; }
.chat-seg-on { background: var(--color-surface); color: var(--color-text); box-shadow: var(--shadow-control); }
.chat-rows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.chat-row {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
}
.chat-row:hover { background: var(--color-surface-sunken); }
.chat-row-current, .chat-row-current:hover { background: var(--color-accent-soft); }
.chat-row > a { color: var(--color-text); font-size: var(--text-sm); line-height: 20px; font-weight: 500; overflow-wrap: anywhere; }
.chat-row > a::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius-md); }
.chat-row > a:hover { text-decoration: none; }
.chat-row > a:focus-visible { outline: none; }
.chat-row > a:focus-visible::after { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.chat-row-meta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); font-size: var(--text-xs); line-height: 16px; color: var(--color-text-tertiary); }
.chat-row-meta > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- /chat: two columns, the list left and the chat right ---- */
.chat-page { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: var(--space-5); align-items: start; }
.chat-list-pane { position: sticky; top: var(--space-4); max-height: calc(100vh - 140px); overflow-y: auto; }
.chat-main-pane { min-width: 0; }
.chat-main-pane > .chat {
  height: calc(100vh - 150px);
  min-height: 480px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.chat-main-pane .chat-thread, .chat-main-pane .chat-live, .chat-main-pane .chat-composer, .chat-main-pane .chat-body, .chat-main-pane .chat-notice-line {
  padding-left: var(--space-5);
  padding-right: var(--space-5);
}
.chat-main-pane .chat-msg { max-width: 100%; }
.chat-main-pane .chat-person { max-width: min(80%, 760px); }
.chat-main-pane .chat-card { max-width: 100%; }
/* The chat page takes the whole width: answers carry tables. */
.content:has(.chat-page) { max-width: none; }
@media (max-width: 960px) {
  .chat-page { grid-template-columns: minmax(0, 1fr); }
  .chat-list-pane { position: static; max-height: none; }
  .chat-main-pane { order: -1; }
  .chat-main-pane > .chat { height: 75vh; min-height: 420px; }
}

/* Never wider than the viewport at phone width (375px). */
@media (max-width: 767px) {
  .chat, .chat-thread, .chat-composer { max-width: 100vw; }
  /* 16px stops iOS zooming on focus; every control a 44px target. */
  .chat-compose-box textarea { font-size: 16px; line-height: 22px; }
  .chat-icon-btn, .chat-send { width: 44px; height: 44px; }
  /* The chip keeps its small look; its hit area is 44px tall. */
  .chat-cluster-chip { position: relative; min-height: 28px; }
  .chat-cluster-chip::after { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 44px; transform: translateY(-50%); }
  .chat-compose-box textarea { padding: 10px 0; }
  .chat-pop-item { min-height: 44px; }
  .chat-main-pane .chat-thread, .chat-main-pane .chat-live, .chat-main-pane .chat-composer, .chat-main-pane .chat-body, .chat-main-pane .chat-notice-line {
    padding-left: var(--space-3);
    padding-right: var(--space-3);
  }
}

/* ==== agent page: head and tabs (T1) ==== */
.agent-tabs { overflow-x: auto; overflow-y: hidden; margin-bottom: var(--space-4); }
/* B6: at phone width the four tabs fit on one row (no tab clipped). */
@media (max-width: 420px) {
  .agent-tabs .tab { padding-left: 0.45rem; padding-right: 0.45rem; }
}

/* ==== agent page: map (T5) ==== */
.agent-map-scroll { overflow-x: auto; margin: 0 0 1rem; }
svg.agent-map { display: block; width: 100%; min-width: 760px; height: auto; font-family: var(--font-sans); }
svg.agent-map rect { stroke-width: 1.2; }
svg.agent-map text { fill: var(--color-text); font-size: var(--text-xs); }
svg.agent-map .map-name { font-weight: 600; font-size: var(--text-sm); }
svg.agent-map .map-fact { fill: var(--color-text-secondary); }
svg.agent-map .map-lane-title { fill: var(--color-text-tertiary); font-size: var(--text-xs); font-weight: 500; }
svg.agent-map .map-legend { fill: var(--color-text-tertiary); font-size: var(--text-xs); font-style: italic; }
svg.agent-map .map-badge-text { fill: var(--color-text-tertiary); font-size: var(--text-xs); text-anchor: end; }
svg.agent-map .agent-node rect { fill: var(--color-surface); stroke: var(--color-border-control); stroke-width: 1.6; }
svg.agent-map .lane-block rect { fill: var(--state-idle-soft); stroke: var(--state-idle); }
svg.agent-map .lane-block.tone-needs rect { fill: var(--state-needs-soft); stroke: var(--state-needs); }
svg.agent-map .lane-block.tone-working rect { fill: var(--state-working-soft); stroke: var(--state-working); }
/* VD-18: a live block is the surface with a hairline and a 3px agents-area
   bar; green is only its "live" dot, since green means done elsewhere. */
svg.agent-map .lane-block.tone-done rect { fill: var(--color-surface); stroke: var(--color-border-control); }
svg.agent-map .lane-block.tone-done rect.map-bar { fill: var(--area-agents); stroke: none; }
svg.agent-map .map-live-dot { fill: var(--state-done); }
svg.agent-map .lane-block.tone-failing rect { fill: var(--state-failing-soft); stroke: var(--state-failing); }
svg.agent-map .lane-block.tone-idle rect { fill: var(--state-idle-soft); stroke: var(--state-idle); }
svg.agent-map .lane-block.is-dashed rect { stroke-dasharray: 5 4; }
svg.agent-map .lane-block.is-add rect { fill: none; }
svg.agent-map .lane-muted { opacity: 0.55; }
svg.agent-map .edge-live { fill: none; stroke: var(--color-border-control); stroke-width: 1.5; }
svg.agent-map .edge-pending { fill: none; stroke: var(--color-border-control); stroke-width: 1.2; stroke-dasharray: 5 4; }
svg.agent-map a { cursor: pointer; }
svg.agent-map a:hover .lane-block rect, svg.agent-map a:hover .agent-node rect { stroke-width: 2; }
svg.agent-map a:focus { outline: none; }
svg.agent-map a:focus-visible .lane-block rect, svg.agent-map a:focus-visible .agent-node rect {
  stroke-width: 3;
  stroke: var(--color-accent);
}
.agent-map-list { display: none; }
.agent-map-list summary { cursor: pointer; }
/* The disclosure triangle is the summary's own marker; its heading must
   stay inline content so the two sit on one line (a block h3 pushes the
   title to its own line below the marker — browser check, 375px). */
.agent-map-list h3 { display: inline; font-size: var(--text-sm); margin: 0; }
.agent-map-list ul { margin: var(--space-2) 0 var(--space-3); padding-left: var(--space-4); }
@media (max-width: 719.98px) {
  .agent-map-scroll { display: none; }
  .agent-map-list { display: block; }
}

/* ==== agent page: overview (T9) ==== */
/* A panel opening with its own label gets the body's inset, not the panel's edge. */
.agent-needs > .section-label, .agent-clusters > .section-label,
.agent-activity > .section-label, .agent-usage > .section-label, #to-decide > .section-label { padding: 20px 20px 0; margin: 0; }
.needs-list li,
.cluster-list li { margin: 0 0 var(--space-2); }
.agent-needs-waiting summary { cursor: pointer; color: var(--color-text-secondary); }
.needs-fix-form { display: inline; }
.needs-fix-form .btn { height: auto; padding: 0; border: none; background: none; box-shadow: none; color: var(--color-accent); text-decoration: underline; }
.needs-fix-form .btn:hover { background: none; color: var(--color-accent-hover); }

/* ==== agent page: know-how, settings (T10) ==== */
.nowrap-name { white-space: nowrap; }

/* ==== agent page: repositories (T11) ==== */
.repo-status-filters { display: flex; flex-wrap: wrap; gap: 0.3rem 1rem; margin: 0.7rem 0; font-size: var(--text-sm); }
.repo-status-filters a { color: var(--color-text-secondary); text-decoration: none; }
.repo-status-filters a:hover { color: var(--color-text); text-decoration: underline; }
.repo-status-filters a[aria-current="page"] { color: var(--color-text); font-weight: 600; }

/* ==== agent page: import from Git, its summary + action up top (T7,
   design-fixes agents:83) ==== */
.import-summary { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin: var(--space-3) 0; color: var(--color-text-secondary); }

/* ==== agent page: connectors (T12) ==== */
.conn-removed-flash { padding: var(--space-3); border-radius: var(--radius-md); background: var(--color-surface-sunken); color: var(--color-text-secondary); }
.conn-actions form { margin: 0; }
.conn-overflow summary, .change-tools summary { cursor: pointer; }
.conn-add-actions { display: flex; gap: var(--space-2); align-items: center; justify-content: flex-end; flex-wrap: wrap; }
.conn-add-actions form { margin: 0; }

/* ==== agent page: connection decision (T13) ==== */
.conn-stepper { color: var(--color-text-secondary); font-size: var(--text-sm); margin: 0 0 var(--space-3); }
.conn-stepper strong { color: var(--color-text); }
.conn-step-sep { color: var(--color-text-tertiary); }
.conn-give-form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.conn-give-form select { width: 16rem; max-width: 100%; }

/* ==== agent page: rules (T14) ==== */

/* ==== agent page: phone header (T15) ====
   The sidebar's nav renders twice (AP-R8): the desktop copy (.nav-desktop)
   generates no box of its own (display: contents), so it slots straight
   into .sidebar's own existing flex layout unchanged at every width down to
   768px, including the ≤860px top-bar rule above; the phone copy
   (.nav-menu, a native <details>) is hidden until then. display: none takes
   the hidden copy out of the accessibility tree, so each viewport keeps
   exactly one menu, and no JavaScript is needed either way. */
.nav-desktop { display: contents; }
.nav-menu { display: none; }
.nav-menu > summary { cursor: pointer; font-weight: 600; padding: var(--space-2); list-style: none; }
.nav-menu > summary::-webkit-details-marker { display: none; }
@media (max-width: 767px) {
  .nav-desktop { display: none; }
  .nav-menu { display: block; flex: 1 1 100%; }
  /* A phone's menu can grow tall when opened; sticking it to the top would
     crowd the page under it, so below 768px the sidebar scrolls with the
     page like any other header. */
  .sidebar { position: static; }
}
/* A jump link (an anchor such as #to-decide, #rules, #repositories) never
   lands its target flush under a sticky header, on any page, at any
   width. */
[id] { scroll-margin-top: var(--space-4); }

/* Add a cluster (K3-K7, K-R22): the recommended server/kubectl commands and
   the ClusterRole YAML are shown verbatim, unwrapped, for copying — a long
   line (the can-i check, the binding commands) must scroll inside its own
   box, never widen the page (browser check, 375px). */
.cmd-block { overflow-x: auto; max-width: 100%; }
.cmd-block pre { margin: 0; }

/* chatNotices: one line each above the composer, inside the chat card's
   own gutter like the composer under it (B5). */
.chat-notice-line { margin: 0 0 var(--space-2); padding: 0 var(--space-3); font-size: var(--text-sm); color: var(--color-text-secondary); overflow-wrap: anywhere; }
.chat-notice-line[data-tone="needs"] { color: var(--color-attention-fg); }
.setup-model-notice { padding: 0; }

/* ============================================================
   GRAPHICS (visual theme §3) — partials_viz.html's inline SVG, built
   from viz.go's views the same way the chain map already is: no
   script, no template.HTML, every decorative
   <svg> aria-hidden with the fact stated in words beside it. Colors
   are tokens only; a tone/kind/level/hue class is the dynamic part of
   an otherwise fixed class name, chosen by the view the partial
   renders.
   ============================================================ */

/* Severity bar: Critical/Major/Moderate/Minor stacked in one 8px bar
   — Home's stat tile, a review's header, the run page's review band. */
.viz-sev { display: block; width: 100%; }
.viz-sev svg { width: 100%; height: 8px; overflow: hidden; border-radius: 4px; display: block; }
.viz-sev-track { fill: var(--color-surface-sunken); }
.viz-sev-seg.sev-critical { fill: var(--sev-critical); }
.viz-sev-seg.sev-major { fill: var(--sev-major); }
.viz-sev-seg.sev-moderate { fill: var(--sev-moderate); }
.viz-sev-seg.sev-minor { fill: var(--sev-minor); }
/* a 1px surface gap between adjacent segments (design-fixes:118): the
   ramp's own contrast is monotonic, not adjacent-distinguishable, so the
   gap plus hue (and the visible legend, badge-sev) carry that job. */
.viz-sev-seg + .viz-sev-seg { stroke: var(--color-surface); stroke-width: 1; }

/* Avatars: a person's initials, white on a hue hashed from their
   account id (plan R13) — approvals log, activity feed, decision
   cards, comments, People, Home rows, the sidebar's account. */
.avatar { display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; font-size: 11px; font-weight: 600; color: var(--on-person); flex: none; }
.avatar.hue-1 { background: var(--person-1); }
.avatar.hue-2 { background: var(--person-2); }
.avatar.hue-3 { background: var(--person-3); }
.avatar.hue-4 { background: var(--person-4); }
.avatar.hue-5 { background: var(--person-5); }
.avatar.hue-6 { background: var(--person-6); }
.avatar.hue-7 { background: var(--person-7); }
.avatar.hue-8 { background: var(--person-8); }
.avatar.is-system { background: transparent; border: 1.5px dashed var(--color-border-strong); }

/* Agent glyph: a bot icon in the agents area hue — the same slot an
   avatar takes wherever the portal itself acted. */
.agent-glyph { display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: var(--radius-sm); background: var(--area-agents-soft); color: var(--area-agents); flex: none; }
.agent-glyph svg { width: 15px; height: 15px; }
.agent-glyph-eye { fill: currentColor; stroke: none; }

/* Area icon chip: a page header's or entity card's 34–44px rounded
   square, soft fill, hue icon — one --chip-hue/--chip-soft pair per
   area, shared with the illustrated empty states below. */
.area-chip { display: inline-grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; background: var(--chip-soft); color: var(--chip-hue); flex: none; }
.area-chip .nav-icon, .area-chip svg { width: 18px; height: 18px; color: inherit; }
.area-chip.area-runs, .empty-art.area-runs { --chip-hue: var(--area-runs); --chip-soft: var(--area-runs-soft); }
.area-chip.area-agents, .empty-art.area-agents { --chip-hue: var(--area-agents); --chip-soft: var(--area-agents-soft); }
.area-chip.area-reviews, .empty-art.area-reviews { --chip-hue: var(--area-reviews); --chip-soft: var(--area-reviews-soft); }
.area-chip.area-commits, .empty-art.area-commits { --chip-hue: var(--area-commits); --chip-soft: var(--area-commits-soft); }
.area-chip.area-integrations, .empty-art.area-integrations { --chip-hue: var(--area-integrations); --chip-soft: var(--area-integrations-soft); }
.area-chip.area-models, .empty-art.area-models { --chip-hue: var(--area-models); --chip-soft: var(--area-models-soft); }
.area-chip.area-people, .empty-art.area-people { --chip-hue: var(--area-people); --chip-soft: var(--area-people-soft); }
.area-chip.area-settings, .empty-art.area-settings { --chip-hue: var(--area-settings); --chip-soft: var(--area-settings-soft); }
/* Account is a person's own page: the people hue, its own glyph. */
.area-chip.area-account, .empty-art.area-account { --chip-hue: var(--area-people); --chip-soft: var(--area-people-soft); }

/* Illustrated empty states: one small geometric SVG per area, tinted
   by the same --chip-hue/--chip-soft pair as its icon chip, replacing
   bare lines like "Never looked yet." */
.empty-art { width: 140px; height: 96px; }
.empty-art-back { fill: var(--chip-soft); }
.empty-art-card { fill: var(--color-surface); stroke: var(--chip-hue); stroke-width: 1.5; }
.empty-art-dot { fill: var(--chip-hue); }

/* ============================================================
   THE PRD PAGE (PRD V1, spec 2026-09-29-prd-v1-design.md §8; plan
   Task 8; prd.html, prdv1.go): one read-only document in five tabs,
   review notes in a margin beside their anchors, the PRD's own chat
   right of it. Below 1100px the chat drops under the document and
   each note under its block. The look is the canvas's: serif
   headings, margin notes, flat cards. Prose stays --color-text;
   state hues only on badges and the stopped draft's edge.
   ============================================================ */
.content:has(.prd-page) { max-width: 90rem; }
.prd-page { min-width: 0; }

/* the head: the status sentence, the draft line, the merge requests */
.prd-head > .page-header { margin-bottom: var(--space-4); }
.prd-status { margin: 0 0 var(--space-2); font-size: var(--text-md); line-height: 22px; font-weight: 500; color: var(--color-text); }
.prd-draft-note, .prd-drafted, .prd-fallback { margin: 0 0 var(--space-2); font-size: var(--text-sm); line-height: 20px; color: var(--color-text-secondary); }
.prd-stopped {
  margin: 0 0 var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--state-failing);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
.prd-stopped .form-error { margin: 0 0 var(--space-2); }
.prd-stopped .worker-error-block { padding: 0; border: 0; background: transparent; }
.prd-draft-note .worker-error-block { padding: var(--space-2) var(--space-3); font-size: var(--text-sm); line-height: 20px; }
.prd-retry { margin: var(--space-2) 0 0; }
/* New PRD's Repositories: one list per agent, its agent named above it
   while every list shows (no script). */
.prd-repos { border: 0; margin: 0; padding: 0; min-width: 0; }
.prd-repos + .prd-repos { margin-top: var(--space-3); }
.prd-repos-agent { padding: 0; margin: 0 0 var(--space-1); font-size: var(--text-sm); font-weight: 500; color: var(--color-text-secondary); }
/* The PRD page's head: the repositories it changes, and the form that edits them. */
.prd-repos-block { margin: 0 0 var(--space-2); }
.prd-repos-form { margin: 0 0 var(--space-3); padding: var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); }
.prd-repos-title { padding: 0; margin-bottom: var(--space-2); font-size: var(--text-sm); font-weight: 500; color: var(--color-text); }
.prd-repos-line { margin: 0 0 var(--space-2); font-size: var(--text-sm); line-height: 20px; color: var(--color-text-secondary); }
.prd-mrs { list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0 0; padding: 0; }
.prd-mr {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-2);
  max-width: 100%;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  font-size: var(--text-sm);
  line-height: 20px;
  overflow-wrap: anywhere;
}
.prd-jump { margin: 0 0 var(--space-2); font-size: var(--text-sm); }
@media (min-width: 1100px) { .prd-jump { display: none; } }
.prd-mrs .chip { white-space: normal; height: auto; min-height: 22px; padding-top: 2px; padding-bottom: 2px; max-width: 100%; }
.prd-mr-note { font-size: var(--text-xs); color: var(--color-text-secondary); }
.prd-head { position: relative; margin-bottom: var(--space-5); }
/* the head's "⋯" menu sits at the top right of the head; opened, its
   confirm form drops below it as a small card instead of pushing the head
   lines down */
.prd-head > .row-menu { position: absolute; top: 0; right: 0; z-index: 2; }
.prd-head:has(> .row-menu) > .page-header { padding-right: 40px; }
.prd-head > .row-menu[open] > .prd-cancel-form {
  position: absolute;
  top: 100%;
  right: 0;
  width: 20rem;
  max-width: calc(100vw - 2 * var(--space-4));
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
.prd-banner {
  margin: 0 0 var(--space-5);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface-sunken);
  font-size: var(--text-sm);
  line-height: 20px;
}

/* the frame: the document, and the chat right of it at 1100px and up */
.prd-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6); align-items: start; }
.prd-doc { min-width: 0; }
.prd-tabs { margin-top: 0; }
.prd-tab { padding-top: var(--space-6); }
.prd-empty { margin: 0; padding: var(--space-6) 0; font-size: var(--text-md); color: var(--color-text-secondary); }

/* a block and its margin: a section, a part, a journey or an option on
   the left, its review notes in their own column on the right — on a tab
   that has any — or under it below 1100px */
.prd-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3) var(--space-5); margin: 0 0 var(--space-8); }
.prd-row.prd-part { margin-bottom: var(--space-6); }
.prd-row-main { min-width: 0; }
.prd-sec-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin: 0 0 var(--space-3);
  font-family: var(--font-serif);
  font-size: var(--text-xl);
  line-height: 28px;
  font-weight: 600;
  color: var(--color-text);
}
.prd-part-title { margin: 0 0 var(--space-2); font-family: var(--font-serif); font-size: var(--text-lg); line-height: 24px; font-weight: 600; color: var(--color-text); }
/* Summary: the serif lead */
.markdown-body.prd-lead { font-family: var(--font-serif); font-size: var(--text-xl); line-height: 30px; }
.prd-items { list-style: none; display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-3) 0 0; padding: 0; }
.prd-item { display: flex; align-items: baseline; gap: var(--space-2) var(--space-3); min-width: 0; }
.prd-item-text { flex: 1 1 auto; min-width: 0; }
.prd-item-text > :last-child { margin-bottom: 0; }
.prd-id {
  flex: none;
  padding: 0 var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-surface-sunken);
  font: 500 var(--text-xs)/18px var(--font-mono);
  color: var(--color-text-secondary);
  white-space: nowrap;
}

/* review notes: the margin's own small print, each under its anchor */
.prd-notes { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.prd-note { padding-left: var(--space-3); border-left: 2px solid var(--color-border-strong); }
.prd-note-label { margin: 0 0 var(--space-1); font-size: var(--text-xs); line-height: 16px; font-weight: 500; font-style: italic; color: var(--color-text-secondary); overflow-wrap: anywhere; }
.prd-note.is-resolved { border-left-style: dashed; }
.prd-note.is-resolved .prd-note-text { color: var(--color-text-secondary); }
.prd-not-stated { margin: 0; font-size: var(--text-sm); line-height: 20px; font-style: italic; color: var(--color-text-secondary); }
.prd-note-text { margin: 0; font-size: var(--text-sm); line-height: 20px; color: var(--color-text); overflow-wrap: anywhere; }
.prd-notes-top {
  margin: 0 0 var(--space-6);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-sunken);
}

/* cards: a journey with its requirements and criteria; an option */
.prd-card { padding: var(--space-4) var(--space-5); border: 1px solid var(--color-border); border-radius: var(--radius-lg); background: var(--color-surface); }
.prd-card-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin: 0 0 var(--space-3); }
.prd-card-title { margin: 0; font-family: var(--font-serif); font-size: var(--text-lg); line-height: 24px; font-weight: 600; color: var(--color-text); }
.prd-journey, .prd-option { margin-bottom: var(--space-5); }
.prd-story { margin-bottom: var(--space-3); }
.prd-reqs { list-style: none; display: flex; flex-direction: column; gap: var(--space-3); margin: 0; padding: 0; }
.prd-req { padding-top: var(--space-3); border-top: 1px solid var(--color-border); }
.prd-acs { margin: var(--space-2) 0 0 var(--space-6); }
.prd-acs .markdown-body { font-size: var(--text-md); line-height: 22px; }
.prd-option.is-chosen > .prd-card { border-color: var(--color-border-strong); }
.prd-why { margin-top: var(--space-4); padding-top: var(--space-3); border-top: 1px solid var(--color-border); }

/* Architecture's legend, the diagram's own marks in small */
.prd-legend { list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5); margin: 0 0 var(--space-6); padding: 0; font-size: var(--text-sm); color: var(--color-text-secondary); }
.prd-legend li { display: inline-flex; align-items: center; gap: var(--space-2); }
.prd-legend-box { width: 16px; height: 12px; border: 2px solid var(--line); border-radius: 3px; background: var(--surface); }
.prd-legend-new { border-color: var(--color-accent); }
.prd-legend-changed { border-color: var(--state-working); }
.prd-legend-removed { border-color: var(--state-failing); border-style: dashed; }

/* drafting: a quiet stand-in, no motion */
.prd-skeleton { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-2) 0; }
.prd-skel-line { display: block; height: 12px; border-radius: var(--radius-pill); background: var(--color-surface-sunken); }
.prd-skel-title { width: 40%; height: 20px; margin-top: var(--space-4); }
.prd-skel-short { width: 60%; }

/* History: the versions, the folds, Cancel */
.prd-hist { min-width: 0; }
.prd-versions { list-style: none; display: flex; flex-direction: column; gap: var(--space-2); margin: 0 0 var(--space-5); padding: 0; }
.prd-version {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
.prd-version.is-current { border-color: var(--color-border-strong); background: var(--color-surface-sunken); }
.prd-version-line { min-width: 0; padding-top: 2px; font-size: var(--text-sm); line-height: 20px; color: var(--color-text); overflow-wrap: anywhere; }
.prd-fold { margin: 0 0 var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); }
.prd-fold > summary { padding: var(--space-2) var(--space-3); font-size: var(--text-sm); line-height: 20px; font-weight: 500; cursor: pointer; }
.prd-fold[open] > summary { border-bottom: 1px solid var(--color-border); }
.prd-fold-note { margin: var(--space-3) var(--space-3) 0; font-size: var(--text-sm); color: var(--color-text-secondary); }
.prd-given { max-height: 24rem; overflow: auto; margin: var(--space-3); padding: var(--space-3); border-radius: var(--radius-sm); background: var(--color-surface-sunken); }
.prd-fold-title { margin: var(--space-3) var(--space-3) var(--space-1); font-size: var(--text-sm); line-height: 20px; font-weight: 600; }
.prd-read-list { margin: 0 var(--space-3) var(--space-3); padding-left: 1.2rem; font-size: var(--text-sm); line-height: 20px; overflow-wrap: anywhere; }
.prd-cancel-form { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); }
.prd-confirm { display: flex; align-items: flex-start; gap: var(--space-2); margin: 0; font-weight: 400; }

/* the chat panel: the chat's own fragment in a fixed frame */
.prd-chat { min-width: 0; }
.prd-chat-title { margin: 0 0 var(--space-2); font-size: var(--text-md); line-height: 20px; font-weight: 600; }
.prd-chat > .chat {
  height: 70vh;
  min-height: 420px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

@media (min-width: 1100px) {
  .prd-layout { grid-template-columns: minmax(0, 1fr) clamp(300px, 26vw, 380px); }
  .prd-chat { position: sticky; top: var(--space-4); }
  .prd-chat > .chat { height: calc(100vh - 96px); }
  .prd-tab:has(.prd-row > .prd-notes) .prd-row { grid-template-columns: minmax(0, 1fr) clamp(160px, 15vw, 220px); }
}
@media (max-width: 720px) {
  .prd-card { padding: var(--space-3) var(--space-4); }
  .prd-acs { margin-left: var(--space-3); }
}
/* end of the PRD page */

/* The PRD board (spec 2026-09-28-conversational-prd): its columns, each a
   .panel of .home-cards reused as-is. */
/* Task 5 (spec 2026-09-29-prd-v1-design.md §8.4; plan Task 5): the PRD's
   own "Today"/"With this change" diagrams — a pure layered layout
   (prdflow.go's flowViewOf) drawn as inline SVG, .chain's and .agent-map's
   own discipline: geometry lives in the Go view, only colour lives here,
   and every colour is a token — the 2026-09-15 design doc's own short
   aliases (--surface/--ink/--muted/--line) plus --color-accent for a new
   box, --state-working for a changed one and --state-failing for a removed
   one, no new tokens added. f.TooLarge falls back to .prd-flow-lines, a
   plain list, drawn with no <svg> at all. */
.prd-flow-figure { margin: 0 0 1rem; }
svg.prd-flow { display: block; width: 100%; min-width: 480px; height: auto; font-family: var(--font-sans); }
svg.prd-flow rect { fill: var(--surface); stroke: var(--line); stroke-width: 1.2; }
svg.prd-flow rect.prd-flow-new { stroke: var(--color-accent); }
svg.prd-flow rect.prd-flow-changed { stroke: var(--state-working); }
svg.prd-flow rect.prd-flow-removed { stroke: var(--state-failing); stroke-dasharray: 5 4; }
svg.prd-flow rect.prd-flow-removed ~ .prd-flow-name { text-decoration: line-through; }
svg.prd-flow text { fill: var(--ink); font-size: var(--text-xs); }
svg.prd-flow .prd-flow-name { font-weight: 600; font-size: var(--text-sm); }
svg.prd-flow .prd-flow-mark { fill: var(--muted); font-style: italic; font-size: var(--text-2xs); }
svg.prd-flow .prd-flow-arrow { fill: none; stroke: var(--line); stroke-width: 1.4; }
svg.prd-flow .prd-flow-arrow-dashed { stroke-dasharray: 5 4; }
svg.prd-flow .prd-flow-arrow-label { fill: var(--muted); font-size: var(--text-2xs); text-anchor: middle; }
svg.prd-flow .prd-flow-arrowhead { fill: var(--line); }
.prd-flow-lines { margin: 0; padding-left: 1.2rem; font-size: var(--text-sm); color: var(--ink); }
/* The drafting PRD's place in the model queue, and New PRD's actions row. */
.prd-queue { margin: var(--space-2) 0 0; font-size: var(--text-sm); }
.new-prd-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-3); }
/* w2f-mcp: the Connect panel and the token reveal — a code block with its Copy
   button beside it; the button starts hidden and portal.js shows it. */
.copy-block { display: flex; align-items: flex-start; gap: var(--space-2); margin: 0 0 var(--space-3); }
.copy-block pre { flex: 1 1 auto; min-width: 0; margin: 0; white-space: pre; overflow-x: auto; }
.copy-block .btn { flex: none; }
@media (max-width: 560px) {
  .copy-block { flex-direction: column; align-items: stretch; }
}
.revoke-confirm { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.revoke-confirm p { flex: 1 1 100%; margin: 0; }
/* w2f-security */
/* A refusal's reason is shown as the service wrote it, kind stripped; its
   first letter is capitalised here (wave2-fixes §7.5). */
.form-error::first-letter, .refusal-note::first-letter, .refusal-inline::first-letter, .problem-message::first-letter { text-transform: uppercase; }

/* w2f-admin */
/* FA-19: the agent overview's rail (its last card) must never sit under the
   floating chat launcher: clearance = the launcher's height + its offset + a gap. */
/* w2f-waiting */
/* The drafting panel's own Cancel this PRD, beside its line (wave-2 §5.1),
   and a failed check's points under their fold (§5.2). */
.prd-cancel-inline { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin: var(--space-3) 0 0; font-size: var(--text-sm); }
.worker-error-points { margin: var(--space-2) 0 0; padding-left: 1.2rem; font-size: var(--text-sm); }
.worker-error-points li + li { margin-top: var(--space-1); }
/* w2f-a11y */
/* AX-2: the skip link is the page's first stop; hidden until it has focus. */
.skip-link { position: absolute; left: var(--space-3); top: var(--space-3); z-index: 100; padding: var(--space-2) var(--space-3); background: var(--color-surface); color: var(--color-accent); border: 1px solid var(--color-accent); border-radius: 6px; font-weight: 600; transform: translateY(-200%); }
.skip-link:focus { transform: none; }
/* AX-17: at 200 % zoom the viewport is short; the chat shrinks to it and the
   composer stays reachable instead of being cut off by a fixed minimum. */
.chat-main-pane > .chat { min-height: min(420px, calc(100dvh - 120px)); }
.chat-main-pane .chat-composer { position: sticky; bottom: 0; }
/* AX-8, AX-11: a checkbox is 20px and its whole label is a row of at least
   24px, so a pointer or a finger lands on it. */
input[type="checkbox"], input[type="radio"] { width: 20px; height: 20px; transform: none; flex: none; }
label.field-check, .field-check > label, .check-row { min-height: 24px; align-items: center; }
.tool-tick > label { display: flex; align-items: center; gap: var(--space-2); min-height: 24px; padding: 2px 0; }
.tool-tick-all [data-tick][hidden] { display: none; }
/* AX-13, AX-20: links in small rows are never smaller than 24px tall. */
.crumbs a, .repo-status-filters a, .activity-filters a { display: inline-block; min-height: 24px; padding: 4px 0; line-height: 16px; }
.crumb-sep { color: var(--color-text-tertiary); }
/* AX-8: a list of type cards is a list with no bullets and no extra gaps. */
.type-cards.plain-list li + li { margin-top: 0; }
/* AX-19: motion stops for people who ask. */
@media (prefers-reduced-motion: reduce) {
  .chat-spinner { animation: none; border-top-color: var(--color-border-strong); border-style: dotted; }
  .type-card, .chat-card-patch > summary .chat-icon { transition: none; }
}
/* AX-16 / UX review P4: "written by" comes before the button in the page's
   order and on screen, so the choice is met before Create PRD. */

/* ============================================================
   REVIEW PAGE, review lifecycle (review.html, reviewpage.go): the
   at-a-glance strip, change impact, what we know, the decision
   rail, round 2's items, and the queue's chips and filters. Tokens
   only; no inline styles.
   ============================================================ */
.review-strip { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--space-2); }
@media (max-width: 1000px) { .review-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.strip-cell { display: grid; gap: 2px; align-content: start; padding: var(--space-3); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); min-width: 0; }
.strip-label { font-size: var(--text-xs); color: var(--color-text-secondary); font-weight: 500; }
.strip-value { font-size: var(--text-md); }
.strip-note { font-size: var(--text-xs); color: var(--color-text-secondary); overflow-wrap: anywhere; }
.strip-tone-done .strip-value { color: var(--state-done); }
.strip-tone-needs .strip-value { color: var(--state-needs); }
.strip-tone-failing .strip-value { color: var(--state-failing); }
/* Review panel §14: the panel strip (one chip per seat) and each
   finding's lens chip; the repository panel page's member cards. */
.lens-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); list-style: none; margin: 0; padding: 0; }
.lens-chip { display: grid; gap: 2px; padding: var(--space-3); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); min-width: 0; }
.lens-why, .lens-spend { font-size: var(--text-xs); color: var(--color-text-secondary); overflow-wrap: anywhere; }
/* Review panel §7, §14: a security finding's block and the Security section. */
.sec-pill { padding: 1px var(--space-2); border-radius: 999px; font-size: var(--text-xs); font-weight: 600; }
.sec-pill-critical, .sec-pill-high { color: var(--state-failing); background: var(--state-failing-soft); }
.sec-pill-medium { color: var(--state-needs); background: var(--state-needs-soft); }
.sec-pill-low { color: var(--state-idle); background: var(--state-idle-soft); }
.sec-block { display: grid; gap: var(--space-2); margin-block: var(--space-2); }
.sec-standards { font-size: var(--text-sm); color: var(--color-text-secondary); overflow-wrap: anywhere; }
.sec-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.sec-flow { display: grid; gap: var(--space-2); padding-left: var(--space-3); border-left: 3px solid var(--color-border-strong); }
.sec-evidence { display: grid; gap: var(--space-1); min-width: 0; overflow-wrap: anywhere; }
.sec-scenario { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.sec-detector, .lens-standards { font-size: var(--text-xs); }
.sec-panel { display: grid; gap: var(--space-2); }
.sec-sub { margin: var(--space-2) 0 0; font-size: var(--text-sm); }
.security-repo { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
.security-flash { color: var(--state-done); }
.security-off { display: grid; gap: var(--space-1); justify-items: start; margin-top: var(--space-4); }
.sec-list { margin: 0; padding-left: var(--space-4); overflow-wrap: anywhere; }
.panel-member { display: grid; gap: var(--space-2); padding-block: var(--space-3); border-bottom: 1px solid var(--color-border); }
.strip-tone-working .strip-value { color: var(--state-working); }
.strip-tone-idle .strip-value { color: var(--color-text); }

.review-says { display: grid; gap: var(--space-1); }
.review-says-text { margin: 0; padding: 0 0 0 var(--space-3); border-left: 3px solid var(--color-border-strong); color: var(--color-text-secondary); white-space: pre-wrap; overflow-wrap: anywhere; }

.round-steps { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.round-step { padding: 2px var(--space-3); border: 1px solid var(--color-border); border-radius: 999px; font-size: var(--text-sm); color: var(--color-text-secondary); background: var(--color-surface); }
.round-step-done { color: var(--state-done); background: var(--state-done-soft); border-color: transparent; }
.round-step-current { color: var(--state-needs); background: var(--state-needs-soft); border-color: transparent; font-weight: 600; }

.impact-layers { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }
.layer-chip { padding: 2px var(--space-3); border: 1px solid var(--color-border-strong); border-radius: 999px; font-size: var(--text-sm); background: var(--color-surface-sunken); }

.know-group + .know-group { margin-top: var(--space-3); }
.know-title { margin: 0 0 var(--space-1); font-size: var(--text-sm); letter-spacing: 0.02em; }
.know-proven .know-title { color: var(--state-done); }
.know-assumed .know-title { color: var(--state-needs); }
.know-unknown .know-title { color: var(--state-idle); }
.know-list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-1); }
.know-list li { overflow-wrap: anywhere; }
.know-proof { font-size: var(--text-xs); color: var(--color-text-secondary); }

.finding-severity { font: 600 var(--text-xs)/1.4 var(--font-mono); padding: 2px var(--space-2); border-radius: 999px; }
.finding-severity-word-break { color: var(--state-failing); background: var(--state-failing-soft); }
.finding-severity-word-fix { color: var(--state-needs); background: var(--state-needs-soft); }
.finding-severity-word-note { color: var(--state-idle); background: var(--state-idle-soft); }
.finding-severity-break { border-color: var(--state-failing); }
.finding-severity-fix, .finding-severity-note { border-color: var(--color-border); }
.finding-angle { color: var(--color-text-secondary); font-size: var(--text-sm); }
.finding-title { margin: var(--space-2) 0 0; }
.finding-code { margin: var(--space-2) 0 0; padding: var(--space-2) var(--space-3); overflow-x: auto; background: var(--color-surface-sunken); border: 1px solid var(--color-border); border-radius: var(--radius-sm); font: var(--text-xs)/1.55 var(--font-mono); }
.finding-basis { margin: var(--space-2) 0 0; color: var(--color-text-secondary); font-size: var(--text-sm); }
.decision-reason { margin-top: var(--space-2); }
.decision-reason label { display: block; font-size: var(--text-sm); color: var(--color-text-secondary); }
.decision-expiry { margin-top: var(--space-2); }
.decision-expiry label { display: block; font-size: var(--text-sm); color: var(--color-text-secondary); }
.sec-owners { color: var(--color-text-secondary); }
@supports selector(:has(a)) {
  .finding-card:not(:has(.decision-seg input[value="accept"]:checked, .decision-seg input[value="ignore"]:checked)) .decision-reason { display: none; }
  .finding-card:not(:has(.decision-seg input[value="accept"]:checked)) .decision-expiry { display: none; }
}

.decision-rail .panel-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
.decision-rail .panel-body > * { min-width: 0; }
.decision-rail pre, .decision-rail .output-block { max-width: 100%; overflow-x: auto; }
.rail-counts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-1) var(--space-3); }
.rail-count { font-size: var(--text-sm); color: var(--color-text-secondary); }
.rail-count b { color: var(--color-text); font-size: var(--text-md); }
.rail-form .btn { width: 100%; justify-content: center; }
.rail-form .btn[disabled] { cursor: not-allowed; }
.rail-rounds, .rail-read { padding-left: var(--space-4); display: grid; gap: var(--space-1); font-size: var(--text-sm); }

.items-table td { vertical-align: top; }

.queue-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.queue-chip { display: inline-flex; align-items: center; gap: var(--space-2); min-height: 40px; padding: 0 var(--space-3); border: 1px solid var(--color-border-control); border-radius: 999px; background: var(--color-surface); color: var(--color-text); text-decoration: none; font-size: var(--text-sm); font-weight: 500; }
.queue-chip:hover { text-decoration: none; border-color: var(--color-border-control-hover); }
.queue-chip[aria-current] { background: var(--color-text); border-color: var(--color-text); color: var(--color-surface); }
.queue-chip-count { font-family: var(--font-mono); opacity: 0.75; }
.queue-filters { display: flex; flex-wrap: wrap; align-items: end; gap: var(--space-3); }
.queue-filter { display: grid; gap: var(--space-1); font-size: var(--text-xs); color: var(--color-text-secondary); }
.queue-why { font-weight: 400; line-height: 1.45; overflow-wrap: anywhere; }
.queue-why-text { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.queue-chips + .queue-filters { margin-top: var(--space-4); margin-bottom: var(--space-4); }
.queue-change { min-width: 260px; }
.queue-change > a { display: block; }
.queue-change .text-tertiary, .queue-findings .text-tertiary { display: block; font-weight: 400; font-size: var(--text-sm); }
.queue-findings, .queue-wait { white-space: nowrap; }
.queue-table td { vertical-align: top; }
@media (max-width: 767px) {
  table.queue-table thead { display: none; }
  table.queue-table tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.4rem var(--space-3); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--color-border); }
  table.queue-table td { border: 0; padding: 0; height: auto; grid-column: 1 / -1; white-space: normal; min-width: 0; }
  table.queue-table td.queue-change { grid-column: 1; grid-row: 1; min-width: 0; }
  table.queue-table td.queue-state { grid-column: 2; grid-row: 1; }
}

.prds-table td { vertical-align: top; }
.prds-table td:nth-child(2) { min-width: 14rem; }
.prds-table td:nth-child(5) { min-width: 16rem; }
@media (max-width: 767px) {
  table.prds-table thead { display: none; }
  table.prds-table tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.4rem var(--space-3); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--color-border); }
  table.prds-table td { border: 0; padding: 0; height: auto; grid-column: 1 / -1; min-width: 0; }
  table.prds-table td:nth-child(2) { grid-column: 1; grid-row: 1; }
  table.prds-table td:nth-child(1) { grid-column: 2; grid-row: 1; }
}

.setup-skip { margin-top: var(--space-4); }

a.chat-title-link { color: inherit; text-decoration: none; }
a.chat-title-link:hover { text-decoration: underline; }

.type-fieldset { border: 0; padding: 0; margin: 0 0 var(--space-4); min-width: 0; }
.type-fieldset > legend { font-weight: 600; margin-bottom: var(--space-2); padding: 0; }
.type-options .type-option { display: block; cursor: pointer; position: relative; }
.type-options .type-option label::after { content: ""; position: absolute; inset: 0; cursor: pointer; }
.type-options .type-option:focus-within { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.type-options .type-option:has(input:checked) { border-color: var(--color-border-strong, var(--color-text-tertiary)); }
.seeded-list { margin: 0; padding: var(--space-3) var(--space-4); }
.seeded-row + .seeded-row { margin-top: var(--space-2); }

.agent-activity { margin-top: var(--space-4); }
.activity-list li { display: flex; flex-wrap: wrap; gap: 0 var(--space-3); justify-content: space-between; padding: var(--space-1) 0; }
.activity-panel { margin-top: var(--space-4); }
.activity-panel > .section-label { padding: var(--space-3) var(--space-4) 0; margin: 0; }
.activity-table td { vertical-align: top; }
@media (max-width: 767px) {
  .activity-table thead { display: none; }
  .activity-table tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.4rem var(--space-3); padding: var(--space-3) 0; border-top: 1px solid var(--color-border); }
  .activity-table td { border: 0; padding: 0; grid-column: 1 / -1; }
  .activity-table td.row-title { grid-column: 1; grid-row: 1; }
  .activity-table td:first-child { grid-column: 2; grid-row: 1; }
}

.prd-written-by { margin: 0 0 var(--space-2); font-size: 13px; color: var(--muted); }
.prd-build { display: flex; flex-direction: column; gap: var(--space-2); }
.prd-no-host { margin: var(--space-2) 0 0; }
.prd-doc-sections { display: flex; flex-direction: column; gap: var(--space-6); }
.prd-doc-section { scroll-margin-top: 64px; }
.prd-doc-title { margin: 0 0 var(--space-3); font-size: 20px; line-height: 26px; }
.prd-tabs { overflow-x: auto; }
@media (min-width: 768px) {
  .prd-tabs { position: sticky; top: 0; z-index: 2; background: var(--surface); }
}
@media (min-width: 1100px) {
  .prd-tabs { position: static; }
}

/* ==== phone head rules ==== */
@media (max-width: 767px) {
  .page-header { margin-bottom: var(--space-4); padding-bottom: var(--space-3); border-bottom: 0; }
  .page-header-main > .crumbs { display: inline; }
  .page-org { display: inline; margin-left: var(--space-2); }
  .page-header h1 { font-size: 24px; line-height: 30px; }
  .page-subtitle { font-size: 14px; line-height: 20px; }
  .agent-tabs { margin-bottom: var(--space-2); }
  .prd-tabs { margin-bottom: var(--space-2); }
}
/* ==== end phone head rules ==== */
/* The review page v2 (review-fixes spec §8.3): the thin-review warning bar,
   key change cards, the snippet fold, the external impact table and its
   "Not checked" box, the reviewer's effort chip and the finish comment
   preview. Tokens only; .snippet, .add/.del and .strip-cell are reused. */
.warn-bar { display: grid; gap: var(--space-1); padding: var(--space-3) var(--space-4); border: 1px solid var(--state-needs); border-radius: var(--radius-md); background: var(--state-needs-soft); }
.warn-bar h2 { margin: 0; font-size: var(--text-md); color: var(--state-needs); }
.warn-bar ul { margin: 0; padding-left: var(--space-4); display: grid; gap: var(--space-1); }
.warn-bar li { font-size: var(--text-sm); overflow-wrap: anywhere; }
.key-change { display: grid; gap: var(--space-1); min-width: 0; }
.key-change + .key-change { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--color-border); }
.key-change h3 { font-size: var(--text-sm); }
.snippet-fold { margin-top: var(--space-1); }
.snippet-fold > summary { cursor: pointer; color: var(--color-text-secondary); font-size: var(--text-sm); }
.notice-box.notice-needs { display: grid; gap: var(--space-2); justify-items: start; margin-top: var(--space-3); padding: var(--space-3); border: 1px solid var(--state-needs); border-radius: var(--radius-md); background: var(--state-needs-soft); }
.external-table td { vertical-align: top; overflow-wrap: anywhere; }
.external-table .chip { font-size: var(--text-xs); }
.effort-chip { font-weight: 500; }
.finish-preview { display: grid; gap: var(--space-1); padding: var(--space-2) var(--space-3); border-left: 3px solid var(--color-border-strong); background: var(--color-surface-sunken); font-size: var(--text-sm); overflow-wrap: anywhere; }
@media (max-width: 375px) { .review-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Home (portal review 2026-11-03 §4): Needs you as a strip, then Now and
   Activity on the left, the agents, the week and Also on the right; a new
   organisation's three flow cards lead. Tokens only; no inline styles. */
.home-cols { display: grid; grid-template-columns: minmax(0, 1fr) 20rem; gap: var(--space-4); align-items: start; margin-top: var(--space-4); }
.home-left, .home-rail { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.home-left > #home-now-slot:empty { display: none; }
#needs-you { margin-top: var(--space-4); }
.home-k { margin: 0; font-size: var(--text-sm); color: var(--color-text-secondary); overflow-wrap: anywhere; }
.home-rows { margin: 0; padding: 0; list-style: none; }
.home-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--color-border); }
.panel-header + .home-rows > .home-row:first-child, .home-filters + .home-rows > .home-row:first-child { border-top: 0; }
.home-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.home-row-title { margin: 0; font-weight: 500; color: var(--color-text); overflow-wrap: anywhere; }
a.home-row-title:hover { color: var(--color-accent); text-decoration: none; }
.home-when { flex: none; min-width: 5.5rem; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-text-tertiary); }
.home-where { flex: none; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-text-secondary); }
.home-filters { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: var(--space-3) var(--space-4); }
.home-filter { display: inline-flex; align-items: center; height: 26px; padding: 0 var(--space-3); border: 1px solid var(--color-border); border-radius: 999px;
  font-size: var(--text-sm); color: var(--color-text-secondary); background: var(--color-surface); }
.home-filter:hover { text-decoration: none; background: var(--color-surface-sunken); }
.home-filter.is-current { color: var(--color-text); border-color: var(--color-accent); font-weight: 600; }
.home-more { padding: var(--space-2) var(--space-4) var(--space-3); }
.home-bars { flex: none; display: flex; align-items: flex-end; gap: 2px; width: 3.5rem; height: 1.5rem; }
.home-bar { flex: 1; min-height: 2px; background: var(--color-accent); border-radius: 1px; opacity: 0.8; }
.home-bar.bar-h1 { height: 10%; }
.home-bar.bar-h2 { height: 20%; }
.home-bar.bar-h3 { height: 30%; }
.home-bar.bar-h4 { height: 40%; }
.home-bar.bar-h5 { height: 50%; }
.home-bar.bar-h6 { height: 60%; }
.home-bar.bar-h7 { height: 70%; }
.home-bar.bar-h8 { height: 80%; }
.home-bar.bar-h9 { height: 90%; }
.home-bar.bar-h10 { height: 100%; }
.home-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); padding: var(--space-4); }
.home-stat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.home-stat-value { font-size: var(--text-lg, 1.25rem); font-weight: 600; color: var(--color-text); }
.home-flows-section { margin-top: var(--space-4); }
.home-flows-title { margin: 0 0 var(--space-1); font-size: var(--text-md); }
.home-flows { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); margin-top: var(--space-3); }
.home-flow { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4); background: var(--color-surface);
  border: 1px solid var(--color-border); border-top: 4px solid var(--flow-accent); border-radius: var(--radius-md); }
.home-flow-agents { --flow-accent: var(--door-agents); }
.home-flow-reviews { --flow-accent: var(--door-reviews); }
.home-flow-prds { --flow-accent: var(--door-prds); }
.home-flow-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.home-flow-head h3 { margin: 0; color: var(--flow-accent); }
.home-steps { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--space-1); flex: 1; }
.home-step { display: flex; gap: var(--space-2); font-size: var(--text-sm); color: var(--color-text); }
.home-step.is-done { color: var(--color-text-tertiary); }
.home-tick { flex: none; width: 1rem; text-align: center; }
.home-flow-action:empty { display: none; }
@media (max-width: 960px) { .home-cols { grid-template-columns: minmax(0, 1fr); } .home-flows { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 480px) { .home-row { flex-wrap: wrap; } .home-when { min-width: 0; } .home-stats { grid-template-columns: minmax(0, 1fr); } }
.editor-disclosure { margin: var(--space-6) 0 0; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); }
.editor-disclosure > summary { cursor: pointer; padding: var(--space-2) var(--space-3); font-size: var(--text-sm); font-weight: 500; color: var(--color-text-secondary); }
.editor-disclosure > .editor-flow { margin: 0; border-radius: 0 0 var(--radius-md) var(--radius-md); }
.editor-disclosure[open] > summary { color: var(--color-text); }
.editor-flow-later { margin: var(--space-2) 0; }
.editor-flow { margin: var(--space-3) 0; padding: var(--space-2) var(--space-3); border-left: 3px solid var(--color-accent); background: var(--color-accent-soft); }
.editor-flow p { margin: 0; }
.editor-flow-label { font-size: 13px; color: var(--muted); }
.coding-tick { margin-bottom: var(--space-4); }
.coding-flow { margin: 0 0 var(--space-4); padding-left: var(--space-3); border-left: 3px solid var(--color-accent); }
.coding-flow .output-block { overflow-x: auto; max-width: 100%; }

/* Review v3, wave 1: the seven-angle summary row. One column under 768 px,
   two above, four above 1200 px; every tile names its state in words. */
.angle-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr)); gap: var(--space-2); margin-bottom: var(--space-2); }
.angle-tile { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: var(--space-2); row-gap: 2px; padding: var(--space-2) var(--space-3); min-width: 0; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); font-size: var(--text-sm); }
.angle-name { line-height: 1.25; overflow-wrap: anywhere; }
.angle-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--state-done); }
.angle-state { grid-column: 2; font-size: var(--text-xs); color: var(--color-text-secondary); }
.angle-tile-findings { border-color: var(--state-needs); background: var(--state-needs-soft); }
.angle-tile-findings .angle-dot, .angle-tile-caveat .angle-dot { background: var(--state-needs); }
.angle-tile-caveat { border-color: var(--state-needs); }
.angle-tile-caveat .angle-state { color: var(--state-needs); }
.angle-tile-unreported { border-style: dashed; }
.angle-tile-unreported .angle-dot { background: var(--state-idle); }
.angle-caveat { color: var(--state-needs); font-size: var(--text-sm); margin-bottom: var(--space-1); overflow-wrap: anywhere; }
.angle-notes { margin-bottom: var(--space-3); }
.angle-note-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); gap: var(--space-2); margin-top: var(--space-2); }
.angle-note { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; padding: var(--space-3); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); font-size: var(--text-sm); line-height: 1.45; overflow-wrap: anywhere; }
.angle-note-title { display: flex; align-items: center; gap: var(--space-2); margin: 0; font-size: var(--text-sm); font-weight: 600; }
.angle-note-read { color: var(--color-text-secondary); }
.angle-places { display: block; color: var(--color-text-secondary); font-size: var(--text-xs); }

/* The code fold and its per-place folds. */
.key-change > summary { cursor: pointer; padding: var(--space-1) 0; }
.key-change[open] > summary { font-weight: 600; }

/* Review v3, wave 1: the decision rail's quiet submit, the written-by chip. */
.btn-link { background: none; border: 0; padding: 0; min-height: 0; color: var(--color-accent); font: inherit; font-size: var(--text-sm); text-align: left; cursor: pointer; box-shadow: none; }
.btn-link:hover { text-decoration: underline; }
.decision-rail .btn { width: 100%; justify-content: center; }
.decision-rail .btn-link { width: auto; justify-content: flex-start; }
.rail-undecided a + a { margin-left: var(--space-2); }
.rail-round-line { font-size: var(--text-sm); }
.add-finding-link { font-size: var(--text-sm); margin-bottom: var(--space-3); }

/* "From your editor" boxes (editorcmds.go). */
.chat-editor { margin: var(--space-2) 0; font-size: var(--text-sm); }
.chat-editor > summary { cursor: pointer; color: var(--color-text-secondary); }
.editor-flow .copy-block { margin-bottom: var(--space-2); }

/* Review v3, wave 2: the reviewer's reading and the open questions. One
   column under 768 px (the arrow hides, After keeps its own heading); tone
   comes with a word, never colour alone. */
.reading-body { display: grid; gap: var(--space-5); }
.reading-change { font-size: var(--text-sm); color: var(--color-text-secondary); font-variant-numeric: tabular-nums; }
.reading-claims { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2); }
@media (min-width: 768px) { .reading-claims { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: stretch; } }
.reading-claim { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; padding: var(--space-3) var(--space-4); background: var(--color-surface-sunken); border-radius: var(--radius-md); border-left: 3px solid var(--color-border); overflow-wrap: anywhere; line-height: 1.5; }
.reading-claim-after { border-left-color: var(--state-done); }
.reading-arrow { align-self: center; color: var(--color-text-secondary); }
@media (max-width: 767px) { .reading-arrow { display: none; } }
.reading-label { margin: 0; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-secondary); }
.reading-label-inline { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-secondary); }
.reading-cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
@media (min-width: 900px) { .reading-cols { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); } }
.reading-row { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; overflow-wrap: anywhere; }
.reading-list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-3); }
.reading-list li { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: baseline; gap: var(--space-2); line-height: 1.45; }
.reading-item { display: grid; gap: 2px; min-width: 0; }
.reading-sub { font-size: var(--text-xs); }
.reading-pill { display: inline-block; min-width: 5.5rem; padding: 1px var(--space-2); border-radius: 999px; font-size: var(--text-xs); text-align: center; color: var(--state-idle); background: var(--state-idle-soft); white-space: nowrap; }
.reading-foot { font-size: var(--text-xs); }
.reading-cite { font-size: var(--text-xs); }
.reading-status-proven { color: var(--state-done); background: var(--state-done-soft); }
.reading-status-assumed { color: var(--state-needs); background: var(--state-needs-soft); }
.reading-confidence { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--color-border); }
.reading-inputs { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0; padding: 0; list-style: none; font-size: var(--text-xs); }
.reading-inputs li { padding: 2px var(--space-2); border: 1px solid var(--color-border); border-radius: 999px; color: var(--color-text-secondary); font-variant-numeric: tabular-nums; }
.reading-how { flex-basis: 100%; margin-top: 0; }
.reading-verdict { font-size: var(--text-sm); }
.conf { text-transform: uppercase; letter-spacing: 0.03em; }
.conf-high { color: var(--state-done); }
.conf-medium { color: var(--state-needs); }
.conf-low { color: var(--state-failing); }
.question-card { display: grid; gap: var(--space-1); min-width: 0; padding: var(--space-3); margin-bottom: var(--space-3); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow-wrap: anywhere; }
.question-title { margin: 0; font-size: var(--text-md); }
.question-place { font-size: var(--text-sm); }
.question-answer { padding-left: var(--space-2); border-left: 3px solid var(--color-border-strong); }
.question-form { display: grid; gap: var(--space-1); justify-items: start; }
.question-form textarea { width: 100%; max-width: 100%; box-sizing: border-box; }
.rail-questions { font-size: var(--text-sm); }

/* Review v3, wave 4: the Review / Data flow tabs. The drawing itself is the
   diagram kit (the dg- rules at the end of this file). */
.review-tabs { display: flex; gap: 2px; margin: var(--space-3) 0 0; border-bottom: 1px solid var(--color-border); }
.review-tabs a { padding: 0.5rem 0.75rem; margin-bottom: -1px; border-bottom: 2px solid transparent; color: var(--color-text-secondary); white-space: nowrap; font-size: var(--text-md); text-decoration: none; }
.review-tabs a:hover { color: var(--color-text); text-decoration: none; }
.review-tabs a[aria-current="page"] { color: var(--color-text); border-bottom-color: var(--color-text); font-weight: 600; }
.flow-panel { min-width: 0; }
.flow-seg { display: inline-flex; justify-self: start; border: 1px solid var(--color-border-strong); border-radius: 999px; overflow: hidden; font-size: var(--text-sm); }
.flow-seg a { padding: 0.25rem 0.85rem; color: var(--color-text-secondary); text-decoration: none; white-space: nowrap; }
.flow-seg a + a { border-left: 1px solid var(--color-border-strong); }
.flow-seg a:hover { color: var(--color-text); text-decoration: none; }
.flow-seg a[aria-current="page"] { background: var(--color-accent-soft); color: var(--color-text); font-weight: 600; }
.across-note { font-size: var(--text-sm); }
.flow-body { display: grid; gap: var(--space-3); min-width: 0; }

/* ==== diagram kit ====
   The portal's server-drawn SVG diagrams (internal/portal/diagram.go, the
   "diagram" partial). Boxes are rounded, a white surface with a hairline
   border; a changed box takes the accent colour (border, soft fill and a pill
   that says so in words); amber is for gaps only (question marks). Lines are
   orthogonal elbows; lit lines are accent. The svg keeps its own width and
   scrolls inside .dg-scroll, so the page never scrolls sideways. Every colour
   is a token, so dark mode follows. A cylinder (store) uses the agents violet
   pair. */
.flow-body { container-type: inline-size; }
.dg-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); min-width: 0; align-items: start; }
@container (min-width: 900px) {
  .dg-layout { grid-template-columns: minmax(0, 1fr) 240px; }
}
.dg-figure { display: grid; gap: var(--space-3); min-width: 0; }
.dg-scroll { max-width: 100%; overflow-x: auto; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); }
.dg-svg { display: block; max-width: 100%; height: auto; margin-inline: auto; }

.dg-frame { fill: none; stroke: var(--color-border-strong); stroke-width: 1.2; stroke-dasharray: 5 4; }
.dg-frame-label { fill: var(--color-text-tertiary); font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: 0.08em; stroke: var(--color-surface); stroke-width: 5; stroke-linejoin: round; paint-order: stroke; }

.dg-box { fill: var(--color-surface); stroke: var(--color-border-strong); stroke-width: 1; }
.dg-rim { fill: none; stroke: var(--color-border-strong); stroke-width: 1; }
.dg-title { fill: var(--color-text); font-family: var(--font-sans); font-size: 14px; font-weight: 600; }
.dg-sub { fill: var(--color-text-secondary); font-family: var(--font-mono); font-size: 11.5px; }
.dg-node a { cursor: pointer; }
.dg-node a:hover .dg-box { stroke-width: 2; }

.dg-k-system .dg-box { fill: var(--color-surface-sunken); }
.dg-k-group .dg-box { fill: var(--color-surface-sunken); stroke-dasharray: 2 3; }
.dg-k-store .dg-box { fill: var(--area-agents-soft); stroke: var(--area-agents); }
.dg-k-store .dg-rim { stroke: var(--area-agents); }
.dg-k-unread .dg-box { fill: var(--color-surface); stroke: var(--color-border-control); stroke-dasharray: 5 4; }
.dg-k-unread .dg-title, .dg-k-unread .dg-sub { fill: var(--color-text-tertiary); }

.dg-changed .dg-box, .dg-new .dg-box { fill: var(--color-accent-soft); stroke: var(--color-accent); stroke-width: 2; }
.dg-changed .dg-rim, .dg-new .dg-rim { stroke: var(--color-accent); stroke-width: 2; }
.dg-pill { fill: var(--color-accent-solid); }
.dg-pill-text { fill: var(--color-on-accent-solid); font-family: var(--font-mono); font-size: 11px; font-weight: 500; }

.dg-edge { fill: none; stroke: var(--color-border-control); stroke-width: 1.6; }
.dg-edge.dg-lit { stroke: var(--color-accent); stroke-width: 2.2; }
.dg-edge.dg-dashed { stroke-dasharray: 5 4; }
.dg-arrowhead { fill: var(--color-border-control); }
.dg-arrowhead-lit { fill: var(--color-accent); }
.dg-elabel { fill: var(--color-text-secondary); font-family: var(--font-sans); font-size: 11px; stroke: var(--color-surface); stroke-width: 4; stroke-linejoin: round; paint-order: stroke; }
.dg-elabel-sub { font-family: var(--font-mono); font-size: 10.5px; }

.dg-edge.dg-gapline { stroke: var(--state-needs); stroke-width: 1.8; }
.dg-elabel-gap { fill: var(--state-needs); }
.dg-edge.dg-muted { opacity: 0.45; }
.dg-elabel-muted { opacity: 0.55; }
.dg-edge.dg-tone-breaks { stroke: var(--state-failing); stroke-width: 2.2; }
.dg-edge.dg-tone-needs { stroke: var(--state-needs); stroke-width: 2.2; }
.dg-arrowhead-breaks { fill: var(--state-failing); }
.dg-arrowhead-needs { fill: var(--state-needs); }
.dg-elabel-breaks { fill: var(--state-failing); }
.dg-elabel-needs { fill: var(--state-needs); }
.dg-mark-box { fill: var(--state-needs-soft); stroke: var(--state-needs); stroke-width: 1.2; }
.dg-mark-text { fill: var(--state-needs); font-size: 10px; font-weight: 600; }

.dg-legend { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); margin: 0; padding: 0; list-style: none; font-size: var(--text-sm); color: var(--color-text-secondary); }
.dg-sw { display: inline-block; width: 14px; height: 10px; margin-right: var(--space-1); border: 1.5px solid var(--color-border-strong); border-radius: 3px; background: var(--color-surface); vertical-align: baseline; box-sizing: border-box; }
.dg-sw-program { background: var(--color-surface); }
.dg-sw-changed, .dg-sw-new { background: var(--color-accent-soft); border-color: var(--color-accent); }
.dg-sw-system { background: var(--color-surface-sunken); }
.dg-sw-store { background: var(--area-agents-soft); border-color: var(--area-agents); border-radius: 5px / 3px; }
.dg-sw-unread { border-style: dashed; border-color: var(--color-border-control); }
.dg-sw-dashed { height: 0; border-width: 1.5px 0 0; border-style: dashed; border-color: var(--color-border-control); border-radius: 0; background: none; vertical-align: middle; }
.dg-sw-litline { height: 0; border-width: 2.2px 0 0; border-style: solid; border-color: var(--color-accent); border-radius: 0; background: none; vertical-align: middle; }
.dg-sw-gapline { height: 0; border-width: 1.8px 0 0; border-style: dashed; border-color: var(--state-needs); border-radius: 0; background: none; vertical-align: middle; }
.dg-sw-breaksline { height: 0; border-width: 2.2px 0 0; border-style: solid; border-color: var(--state-failing); border-radius: 0; background: none; vertical-align: middle; }
.dg-sw-needsline { height: 0; border-width: 2.2px 0 0; border-style: solid; border-color: var(--state-needs); border-radius: 0; background: none; vertical-align: middle; }
.dg-sw-gap { background: var(--state-needs-soft); border-color: var(--state-needs); }

.dg-touches { display: grid; gap: var(--space-2); min-width: 0; padding: var(--space-3) var(--space-4); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); font-size: var(--text-sm); }
.dg-touches-h { margin: 0; font-size: var(--text-md); }
.dg-touch-list { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.dg-touch-list li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-2); min-width: 0; overflow-wrap: anywhere; }
.dg-touch-name { font-family: var(--font-mono); font-size: var(--text-xs); }
.dg-touch-list a { font-family: var(--font-mono); font-size: var(--text-xs); }
.dg-touch-files { color: var(--color-text-secondary); font-size: var(--text-xs); }
.dg-chip { display: inline-block; padding: 0 var(--space-2); border-radius: 999px; background: var(--color-accent-solid); color: var(--color-on-accent-solid); font-family: var(--font-mono); font-size: var(--text-2xs); line-height: 16px; font-weight: 500; }
.dg-gap { display: inline-block; padding: 0 var(--space-2); border-radius: 999px; background: var(--state-needs-soft); border: 1px solid var(--state-needs); color: var(--state-needs); font-size: var(--text-2xs); line-height: 14px; font-weight: 600; }
/* Data flow › Inside › Request path: a route, its callers, its calls. */
.rp-route { display: grid; gap: var(--space-2); padding: var(--space-3) 0; border-top: 1px solid var(--color-border); min-width: 0; }
.rp-route-h { margin: 0; font-size: var(--text-sm); overflow-wrap: anywhere; }
.rp-called { overflow-wrap: anywhere; }
.rp-steps { display: grid; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.rp-step { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-2); padding-left: var(--space-3); border-left: 2px solid var(--color-border); min-width: 0; overflow-wrap: anywhere; }
.rp-d1 { margin-left: var(--space-4); }
.rp-d2 { margin-left: calc(2 * var(--space-4)); }
.rp-d3 { margin-left: calc(3 * var(--space-4)); }
.rp-d4 { margin-left: calc(4 * var(--space-4)); }
.rp-muted { opacity: 0.6; }
.rp-src { font-size: 0.85em; }
.rp-changed { border-left-color: var(--color-accent-solid); background: var(--color-accent-soft); }
.rp-mark { color: var(--color-accent); font-weight: 600; }
.rp-out { font-family: var(--font-mono); font-size: var(--text-2xs); }
@media (max-width: 640px) { .rp-d1 { margin-left: var(--space-2); } .rp-d2 { margin-left: calc(2 * var(--space-2)); } .rp-d3 { margin-left: calc(3 * var(--space-2)); } .rp-d4 { margin-left: calc(4 * var(--space-2)); } }
.dg-gap-list { padding-top: var(--space-2); border-top: 1px solid var(--color-border); }

/* Data flow > the reviewer's diagram (spec reviewer-diagrams): the nested
   drawing's tinted container and legend swatches, the impact matrix, the code
   cards, the journeys and the table of every line. Colours are tokens, so
   dark mode follows; an effect is always also a word. */
.dg-frame.dg-frame-this { fill: var(--color-accent-soft); fill-opacity: 0.5; stroke: var(--color-accent); }
.dg-sw-expline { height: 0; border-width: 2.2px 0 0; border-style: dashed; border-color: var(--color-accent); border-radius: 0; background: none; vertical-align: middle; }
.dm-section .dg-svg { max-width: none; height: auto; }
.dm-section .dg-elabel, .dm-section .dg-sub, .dm-section .dg-elabel-sub, .dm-section .dg-frame-label { font-size: 12px; }
.dm-matrix thead th { text-transform: none; letter-spacing: normal; }
.dm-section { display: grid; gap: var(--space-2); min-width: 0; }
.dm-h { margin: 0; font-size: var(--text-md); }
.dm-sub { margin: 0; font-size: var(--text-sm); color: var(--color-text-secondary); }
.dm-matrix th, .dm-matrix td { vertical-align: top; overflow-wrap: anywhere; }
.dm-matrix thead th code { font-size: var(--text-xs); }
.dm-rel { display: block; font-size: var(--text-xs); font-weight: 400; }
.dm-cell { display: grid; gap: 2px; font-size: var(--text-sm); }
.dm-cell a { color: inherit; }
.dm-cell code, .dm-cite { font-size: var(--text-2xs); color: var(--color-text-secondary); overflow-wrap: anywhere; }
.dm-breaks { background: var(--state-failing-soft); color: var(--state-failing); }
.dm-changes { background: var(--state-needs-soft); color: var(--state-needs); }
.dm-new, .dm-expected { background: var(--color-accent-soft); color: var(--color-accent); }
.dm-ok { color: var(--color-text-secondary); }
table.data td.dm-cell { display: table-cell; }
.dm-fold { border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-2) var(--space-3); background: var(--color-surface); }
.dm-fold > summary { cursor: pointer; font-size: var(--text-sm); color: var(--color-text-secondary); }
.dm-fold[open] > summary { margin-bottom: var(--space-2); }
.dm-cards { display: grid; gap: var(--space-3); min-width: 0; }
.dm-card { display: grid; gap: var(--space-1); padding: var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); min-width: 0; scroll-margin-top: var(--space-6); }
.dm-card:target, .dm-journey:target { border-color: var(--color-accent); box-shadow: 0 0 0 2px var(--color-accent-soft); }
.dm-card-changed { border-left: 3px solid var(--color-accent-solid); }
.dm-card-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-2); }
.dm-card-head h4 { margin: 0; font-size: var(--text-md); overflow-wrap: anywhere; }
.dm-badge { display: inline-block; padding: 0 var(--space-2); border-radius: 999px; font-size: var(--text-2xs); line-height: 16px; font-weight: 600; }
.dm-badge-unverified { background: var(--state-needs-soft); color: var(--state-needs); border: 1px solid var(--state-needs); }
.dm-journeys { display: grid; gap: var(--space-4); min-width: 0; }
.dm-journey { display: grid; gap: var(--space-2); min-width: 0; padding: var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); scroll-margin-top: var(--space-6); }
.dm-journey h4 { margin: 0; font-size: var(--text-md); overflow-wrap: anywhere; }
.dm-edges td, .dm-edges th { vertical-align: top; overflow-wrap: anywhere; }
.dm-note { font-size: var(--text-sm); }

/* Add a requirement (add-requirement spec §5, board 18): the box between the
   reviewer's reading and the findings — add, progress or the criteria table —
   and the rail's quiet requirement line. The steps stack under 768 px. */
.requirement-add-body { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }
.requirement-add-text { display: grid; gap: var(--space-1); min-width: 0; flex: 1 1 280px; }
.requirement-add-text h2 { font-size: var(--text-md); }
.requirement-box.requirement-add { border-left: 3px solid var(--color-border-strong); }
.requirement-box.requirement-progress { border-left: 3px solid var(--state-working); }
.requirement-steps { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin: 0; list-style: none; }
.requirement-step { display: flex; align-items: baseline; gap: var(--space-2); min-width: 0; font-size: var(--text-sm); color: var(--color-text-secondary); }
.requirement-step-text { display: grid; gap: 2px; min-width: 0; overflow-wrap: anywhere; }
.requirement-step-n { flex: none; display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 999px; border: 1px solid var(--color-border); background: var(--color-surface); font-size: var(--text-xs); font-weight: 600; }
.requirement-step-done .requirement-step-n { color: var(--state-done); background: var(--state-done-soft); border-color: transparent; }
.requirement-step-current { color: var(--color-text); font-weight: 600; }
.requirement-step-current .requirement-step-n { color: var(--state-working); background: var(--state-working-soft); border-color: transparent; }
.requirement-step-pending { color: var(--color-text-tertiary); }
.requirement-step-failing { color: var(--state-failing); }
.requirement-step-failing .requirement-step-n { color: var(--state-failing); background: var(--state-failing-soft); border-color: transparent; }
.requirement-step .row-sub { font-weight: 400; }
.criteria-table .criteria-id { font-family: var(--font-mono); font-size: var(--text-xs); white-space: nowrap; }
.criteria-table td { vertical-align: top; overflow-wrap: anywhere; }
.rail-requirement { padding-top: var(--space-2); border-top: 1px solid var(--color-border); font-size: var(--text-sm); color: var(--color-text-secondary); }
@media (max-width: 767px) {
  .requirement-steps { flex-direction: column; }
  .requirement-add-body .btn { width: 100%; justify-content: center; }
}

/* Settings › Integrations (integrations-layout): a host card per Git host at
   the top, then one section per installation — watched repositories as
   read-only rows that fold open to edit, the rest of the list as one line
   each, the connection itself folded, Disconnect last. */
.host-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); margin-bottom: var(--space-5); }
.host-card { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); padding: var(--space-5);
  background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg, 12px); min-width: 0; }
.host-card-title { margin: 0; font-size: var(--text-lg); }
.host-card > p { margin: 0; }
.host-card-inst { display: grid; grid-template-columns: 1fr auto; gap: 4px var(--space-3); width: 100%; padding: var(--space-3);
  border: 1px solid var(--color-border); border-radius: var(--radius-md); color: inherit; }
.host-card-inst:hover { text-decoration: none; border-color: var(--color-accent); }
.host-card-account { font-weight: 600; }
.host-card-manage { grid-column: 2; grid-row: 1; color: var(--color-accent); font-size: var(--text-sm); }
.host-card-inst .status-line, .host-card-inst .chip { grid-column: 1 / -1; margin: 0; justify-self: start; }
.host-connect { width: 100%; }
.host-connect > summary { cursor: pointer; font-weight: 500; color: var(--color-accent); }
.host-connect[open] > summary { margin-bottom: var(--space-3); }
.host-connect .watch-form-flush { border-top: 0; padding-top: 0; }
.host-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.host-section { scroll-margin-top: var(--space-4); }
.repo-list { border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; }
.repo-row { display: grid; grid-template-columns: minmax(0, 2.2fr) minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 0.7fr) auto;
  gap: var(--space-3); align-items: center; padding: var(--space-2) var(--space-3); }
.repo-row-head { background: var(--color-surface-sunken, var(--color-bg)); font-size: var(--text-xs); text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--color-text-secondary); }
.repo-item { border-top: 1px solid var(--color-border); }
.repo-item > summary { cursor: pointer; list-style: none; }
.repo-item > summary::-webkit-details-marker { display: none; }
.repo-item > summary:hover { background: var(--color-surface-sunken, var(--color-bg)); }
.repo-name { display: flex; flex-direction: column; min-width: 0; overflow-wrap: anywhere; font-weight: 500; }
.repo-name .row-sub { font-weight: 400; }
.repo-edit-link { color: var(--color-accent); font-size: var(--text-sm); }
.repo-item[open] .repo-edit-link { color: var(--color-text-secondary); }
.repo-edit { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap;
  padding: var(--space-3) var(--space-3) var(--space-4); background: var(--color-surface-sunken, var(--color-bg)); }
.repo-edit .mode-form { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-3); flex: 1; }
.repo-edit .mode-form > .btn { align-self: flex-end; }
.repo-edit .mode-form .field { margin: 0; }
.repo-edit .mode-form .field-wide { flex: 1 1 280px; }
.repo-edit .mode-form textarea { width: 100%; }
.repo-unwatch { margin: 0; }
.list-toolbar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-3); }
.list-toolbar form { margin: 0; }
.list-toolbar .row-sub { margin-right: auto; }
.unwatched-list { list-style: none; margin: 0 0 var(--space-3); padding: 0; border: 1px solid var(--color-border); border-radius: var(--radius-md); }
.unwatched-list li { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-2) var(--space-3); }
.unwatched-list li + li { border-top: 1px solid var(--color-border); }
.unwatched-list li .repo-name { flex-direction: row; gap: var(--space-2); flex-wrap: wrap; }
.unwatched-list form { margin: 0; }
.host-fold { margin-top: var(--space-4); border-top: 1px solid var(--color-border); padding-top: var(--space-3); }
.host-fold > summary { cursor: pointer; font-weight: 600; }
.host-fold[open] > summary { margin-bottom: var(--space-3); }
.inline-action { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; margin: var(--space-2) 0 0; }
.secret-once { display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-3) 0; padding: var(--space-3);
  border: 1px solid var(--state-needs); border-radius: var(--radius-md); }
.secret-value { font-family: var(--font-mono); font-size: var(--text-sm); overflow-wrap: anywhere; user-select: all; }
.host-danger { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--color-border); }
@media (max-width: 767px) {
  .host-cards { grid-template-columns: 1fr; }
  .repo-row { grid-template-columns: minmax(0, 1fr) auto; gap: 2px var(--space-3); }
  .repo-row > :nth-child(2), .repo-row > :nth-child(3), .repo-row > :nth-child(4) { grid-column: 1; font-size: var(--text-sm); color: var(--color-text-secondary); }
  .repo-row-head { display: none; }
}

/* The agent coach (coach.html, coach_session.html). */
.coach-steps { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0 0 var(--space-3); padding: 0; list-style: none; font-size: var(--text-sm); color: var(--color-text-tertiary); }
.coach-steps li[aria-current="step"] { color: var(--color-text); font-weight: 600; }
.coach-profile, .coach-answer { margin: 0; max-height: 360px; overflow: auto; padding: var(--space-2); border-radius: var(--radius-sm); background: var(--color-bg); font-size: var(--text-xs); white-space: pre-wrap; }

/* Trace and audit pages (spec 2026-10-22-audit-trail-design.md §4). */
.how-made { margin-top: var(--space-4); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); font-size: var(--text-sm); }
.how-made > summary { cursor: pointer; padding: var(--space-2) var(--space-3); color: var(--color-text-secondary); font-weight: 500; }
.how-made[open] > summary { border-bottom: 1px solid var(--color-border); }
.how-made-body { display: grid; gap: var(--space-2); padding: var(--space-3); }
.how-made-steps { margin: 0; padding-left: var(--space-5); }
.how-made-steps li + li { margin-top: var(--space-1); }
.trace-detail { margin-top: var(--space-1); font-weight: 400; }
.trace-detail > summary { cursor: pointer; font-size: var(--text-sm); color: var(--color-text-secondary); }
.trace-label { margin: var(--space-2) 0 var(--space-1); font-size: var(--text-xs); color: var(--color-text-tertiary); }
.trace-pre { margin: 0; max-height: 24rem; overflow: auto; padding: var(--space-2) var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-sunken); font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 400; }
.trace-error { margin-left: var(--space-2); }
.trace-error-text { color: var(--color-text-secondary); font-weight: 400; font-size: var(--text-sm); overflow-wrap: anywhere; }
.trace-steps td:nth-child(2) { min-width: 16rem; overflow-wrap: anywhere; }
.pager { display: flex; gap: var(--space-4); align-items: center; padding: var(--space-3) var(--space-4); border-top: 1px solid var(--color-border); font-size: var(--text-sm); }
.usage-kinds { margin-top: var(--space-3); font-size: var(--text-sm); }
.panel-sublabel { margin: var(--space-4) 0 var(--space-2); }
.audit-table td { vertical-align: top; }
.audit-panel, .trace-list-panel { margin-top: var(--space-4); }

/* Usage charts (usagechart.go): server-rendered SVG; axis labels are HTML so
   they stay 11px. The SVG is stretched to the plot's width and drawn 170px
   high, so a unit of its viewBox is a pixel high. */
.usage { margin: 0 0 var(--space-3); max-width: 680px; }
.usage-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }
.usage-total { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.usage-total .n { font-size: var(--text-2xl); font-weight: 600; line-height: 1.1; letter-spacing: -0.01em; }
.usage-total .unit { color: var(--color-text-secondary); font-size: var(--text-sm); }
.usage-delta { font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 500; line-height: 1; padding: 3px 8px; border-radius: var(--radius-pill); border: 1px solid var(--color-border); color: var(--color-text-secondary); white-space: nowrap; }
.usage-delta.up { border-color: transparent; background: var(--color-surface-sunken); }
.usage-range { color: var(--color-text-tertiary); font-size: var(--text-sm); }
.window { display: inline-flex; gap: var(--space-1); padding: 2px; border: 1px solid var(--color-border); border-radius: var(--radius-pill); background: var(--color-surface-sunken); }
.window a { font-size: var(--text-xs); font-weight: 500; line-height: 1; padding: 6px 10px; border-radius: var(--radius-pill); color: var(--color-text-secondary); text-decoration: none; }
.window a[aria-current] { background: var(--color-surface); color: var(--color-text); box-shadow: 0 1px 0 rgba(14, 16, 21, 0.06); }
.panel-body > .window { margin-bottom: var(--space-3); }
.usage-facts { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin: 0 0 var(--space-3); padding: 0; list-style: none; font-size: var(--text-sm); color: var(--color-text-secondary); }
.usage-facts b { font-weight: 500; color: var(--color-text); font-variant-numeric: tabular-nums; }
.usage-plot { position: relative; display: grid; grid-template-columns: 3rem 1fr; }
.uc-y { display: flex; flex-direction: column; justify-content: space-between; height: 170px; padding: 1px 0; }
.uc-yl { height: 0; display: flex; align-items: center; justify-content: flex-end; padding-right: var(--space-2); }
.uc-yl span, .uc-x b { font-size: 11px; line-height: 1; font-weight: 400; color: var(--color-text-tertiary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.usage-plot > .uc { width: 100%; height: 170px; display: block; overflow: visible; }
.uc-x { grid-column: 2; display: grid; }
.uc-days-7 { grid-template-columns: repeat(7, 1fr); }
.uc-days-30 { grid-template-columns: repeat(30, 1fr); }
.uc-days-90 { grid-template-columns: repeat(90, 1fr); }
.uc-x span { position: relative; height: 20px; }
.uc-x b { position: absolute; top: 6px; left: 50%; transform: translateX(-50%); }
.uc-x .end b { left: auto; right: 0; transform: none; color: var(--color-text); font-weight: 600; }
.uc-grid { stroke: var(--color-border); stroke-width: 1; }
.uc-base { stroke: var(--color-border-strong); }
.uc-weekend { fill: var(--chart-weekend); }
.uc-hit { fill: transparent; }
.uc-none { fill: var(--color-text-tertiary); }
.uc-bar { outline: none; }
.uc-bar:hover .uc-hit, .uc-bar:focus-visible .uc-hit, .uc-bar.is-active .uc-hit { fill: var(--color-accent-soft); }
.uc-bar:focus-visible .uc-hit { stroke: var(--color-accent); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.uc-in { fill: var(--chart-1); }
.uc-cached { fill: color-mix(in srgb, var(--chart-1) 38%, var(--color-surface)); }
.uc-out { fill: var(--chart-2); }
.uc-s0 { fill: var(--chart-1); } .uc-s1 { fill: var(--chart-2); } .uc-s2 { fill: var(--chart-3); }
.uc-s3 { fill: var(--chart-4); } .uc-s4 { fill: var(--chart-5); } .uc-s5 { fill: var(--chart-6); }
.uc-others { fill: var(--chart-others); }
.uc-unattr { fill: var(--chart-unattributed); }
/* legend: one row; the 10px swatches are <i>, never the stretched chart SVG */
.uc-legend { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin: var(--space-3) 0 0; padding: 0; list-style: none; font-size: var(--text-sm); color: var(--color-text-secondary); }
.uc-legend li { display: inline-flex; align-items: center; gap: 6px; }
.uc-legend a { color: inherit; text-decoration: none; border-bottom: 1px solid transparent; }
.uc-legend a:hover { border-bottom-color: currentColor; }
.uc-legend .v { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-text-tertiary); }
.sw { display: inline-block; width: 10px; height: 10px; border-radius: 2px; flex: none; background: currentColor; }
.sw.uc-in, .sw.uc-s0 { color: var(--chart-1); }
.sw.uc-cached { color: color-mix(in srgb, var(--chart-1) 38%, var(--color-surface)); }
.sw.uc-out, .sw.uc-s1 { color: var(--chart-2); }
.sw.uc-s2 { color: var(--chart-3); } .sw.uc-s3 { color: var(--chart-4); } .sw.uc-s4 { color: var(--chart-5); } .sw.uc-s5 { color: var(--chart-6); }
.sw.uc-others { color: var(--chart-others); }
.sw.uc-unattr { color: var(--chart-unattributed); }
/* tooltip: portal.js fills it from the bar's data-*; without script it stays
   hidden and each bar's <title> carries the same words */
.uc-tip { position: absolute; z-index: 2; top: 4px; min-width: 200px; max-width: 260px; padding: var(--space-2) var(--space-3); background: var(--color-surface); border: 1px solid var(--color-border-strong); border-radius: var(--radius-sm); box-shadow: var(--shadow-pop); font-size: var(--text-xs); }
.uc-tip[hidden] { display: none; }
/* Tooltip stops set by portal.js (at-0 … at-20): the tip's own share follows the plot's, so it never leaves it. */
.uc-tip.at-0 { left: 0%; transform: translateX(-0%); }
.uc-tip.at-1 { left: 5%; transform: translateX(-5%); }
.uc-tip.at-2 { left: 10%; transform: translateX(-10%); }
.uc-tip.at-3 { left: 15%; transform: translateX(-15%); }
.uc-tip.at-4 { left: 20%; transform: translateX(-20%); }
.uc-tip.at-5 { left: 25%; transform: translateX(-25%); }
.uc-tip.at-6 { left: 30%; transform: translateX(-30%); }
.uc-tip.at-7 { left: 35%; transform: translateX(-35%); }
.uc-tip.at-8 { left: 40%; transform: translateX(-40%); }
.uc-tip.at-9 { left: 45%; transform: translateX(-45%); }
.uc-tip.at-10 { left: 50%; transform: translateX(-50%); }
.uc-tip.at-11 { left: 55%; transform: translateX(-55%); }
.uc-tip.at-12 { left: 60%; transform: translateX(-60%); }
.uc-tip.at-13 { left: 65%; transform: translateX(-65%); }
.uc-tip.at-14 { left: 70%; transform: translateX(-70%); }
.uc-tip.at-15 { left: 75%; transform: translateX(-75%); }
.uc-tip.at-16 { left: 80%; transform: translateX(-80%); }
.uc-tip.at-17 { left: 85%; transform: translateX(-85%); }
.uc-tip.at-18 { left: 90%; transform: translateX(-90%); }
.uc-tip.at-19 { left: 95%; transform: translateX(-95%); }
.uc-tip.at-20 { left: 100%; transform: translateX(-100%); }
.uc-tip .d { font-weight: 600; color: var(--color-text); display: flex; justify-content: space-between; gap: var(--space-3); }
.uc-tip .d span:last-child { font-family: var(--font-mono); font-weight: 500; }
.uc-tip table { width: 100%; border-collapse: collapse; margin-top: 4px; }
.uc-tip td { padding: 2px 0; color: var(--color-text-secondary); vertical-align: middle; }
.uc-tip td:first-child { display: flex; align-items: center; gap: 6px; }
.uc-tip td.num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--color-text); white-space: nowrap; }
.uc-tip td.muted { color: var(--color-text-tertiary); padding-left: 8px; }
.uc-tip .foot { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--color-border); color: var(--color-text-tertiary); }
.uc-tip .foot a { color: var(--color-accent); }
@media (max-width: 480px) {
  .usage-total .n { font-size: var(--text-xl); }
  .uc-legend .v { display: none; }
}
.usage-table { margin-top: var(--space-3); }
#requirement-search { margin-bottom: var(--space-4); }
.goal-limits-fields { border: 0; margin: 0; padding: 0; min-width: 0; }

/* UX review G2: a deep link to an action (#action-N) must land with Approve
   and Reject in view. The page's chat fills the viewport, the goal's live
   card yields height to the thread, and the arguments fold into a shorter
   scrolling box so the buttons sit under them without a second scroll. */
.chat-main-pane > .chat { height: calc(100dvh - 130px); }
.chat-main-pane .chat-live { max-height: 34%; overflow-y: auto; }
.chat-main-pane .action-args { max-height: 8rem; }
.action-card { scroll-margin: var(--space-3); }
.action-card:target { outline: 2px solid var(--color-attention-border); outline-offset: 2px; }
@media (max-width: 960px) {
  .chat-main-pane > .chat { height: 75dvh; }
}

/* Agent-page fixes (F8, F10): field widths, hints and the markup warnings. */
input.input-num, select.input-num { width: 8rem; max-width: 100%; }
input.input-short, select.input-short, textarea.input-short { width: 100%; max-width: 24rem; }
.field-check { display: flex; align-items: center; gap: var(--space-2); }
.field-check input[type="checkbox"] { margin: 0; flex: none; }
.field .field-hint { max-width: none; }
.main-skill-markup-warning, .skill-markup-warning, .draft-markup-warning, .rule-suggestion-markup-warning {
  background: var(--state-needs-soft);
  border-color: var(--color-attention-border);
  color: var(--color-text);
  font-size: var(--text-md);
  line-height: 22px;
}
.main-skill-markup-warning ul, .skill-markup-warning ul { margin: var(--space-1) 0 0; padding-left: var(--space-5); }
.repo-row-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2); }
.repo-row-actions form { margin: 0; }
.conn-overflow summary, .change-tools summary { text-decoration: none; }

/* ---- Agent page layout (agent-page-layout) ------------------------------
   One visual system for the five tabs: a section heading outside its card
   with an optional right-aligned action, rows with one pattern, filter chips,
   the Overview's two columns and Settings' sticky section list. */
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; margin: var(--space-6) 0 var(--space-2); }
.section-title { font-size: 1rem; font-weight: 600; margin: 0; color: var(--color-text); }
.section-subtitle { font-size: var(--text-sm); font-weight: 600; margin: var(--space-4) 0 var(--space-2); color: var(--color-text-secondary); }
.section-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.section-note { margin: 0 0 var(--space-2); max-width: 70ch; }
.chip-row { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 var(--space-3); }
.chip-row a { padding: 2px 10px; border: 1px solid var(--color-border); border-radius: var(--radius-pill); color: var(--color-text-secondary); text-decoration: none; font-size: var(--text-xs); }
.chip-row a[aria-current="page"] { background: var(--color-accent-soft); color: var(--color-accent); border-color: var(--color-accent); }
.repo-view-links { display: flex; gap: var(--space-3); font-size: var(--text-xs); }
.repo-view-links a[aria-current="page"] { font-weight: 600; text-decoration: none; color: var(--color-text); }

/* The head: name + chip + actions are the page header; this is the meta line. */
.agent-head-meta { color: var(--color-text-secondary); font-size: var(--text-sm); }
.agent-head-desc { color: var(--color-text); }

/* Connections rows: icon, name and detail, status chip, then the actions. */
.conn-panel { padding: 0; }
.conn-list { list-style: none; margin: 0; padding: 0; }
.conn-row { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto auto; align-items: start; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--color-border); }
.conn-list > .conn-row:first-child { border-top: 0; }
.conn-icon { color: var(--color-text-tertiary); text-align: center; line-height: 1.6; }
.conn-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; overflow-wrap: anywhere; }
.conn-name { font-weight: 600; }
.conn-detail { color: var(--color-text-secondary); font-size: var(--text-xs); }
.conn-status { white-space: nowrap; }
.conn-state { color: var(--color-text-secondary); font-size: var(--text-xs); }
.conn-actions { display: flex; flex-direction: row; align-items: center; justify-content: flex-end; gap: var(--space-2); flex-wrap: wrap; }
.conn-extra { padding: 0 var(--space-4) var(--space-3) calc(var(--space-4) + 28px + var(--space-3)); list-style: none; }
/* Built-in tools on Settings › Tools (agent tools D1) */
.builtin-tools { padding-top: var(--space-3); border-top: 1px solid var(--color-border); }
.builtin-form, .builtin-hosts { display: flex; flex-direction: column; gap: var(--space-3); align-items: flex-start; margin-top: var(--space-3); }
.builtin-hosts .field { width: 100%; max-width: 32rem; }
.builtin-hosts textarea { width: 100%; font-family: var(--font-mono); }
.builtin-row { display: flex; flex-direction: column; gap: 2px; }
.builtin-level { display: flex; gap: var(--space-3); border: 0; padding: 0; margin: 2px 0 0; }
.builtin-choice { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--text-xs); }
.builtin-list { list-style: none; padding: 0; margin: var(--space-2) 0; display: flex; flex-direction: column; gap: var(--space-2); }
.builtin-title { font-weight: 600; }
.builtin-hosts-list { white-space: pre-line; }
.conn-more, .conn-form-fold { position: relative; }
.conn-more > summary { cursor: pointer; list-style: none; padding: 4px 8px; border-radius: var(--radius-md); color: var(--color-text-secondary); }
.conn-more > summary::-webkit-details-marker { display: none; }
.conn-more > summary.btn { padding: 0 var(--space-3); }
.conn-pop { position: absolute; right: 0; z-index: 5; min-width: 12rem; margin-top: 4px; padding: var(--space-3); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-pop); display: flex; flex-direction: column; gap: var(--space-2); align-items: flex-start; }
.conn-pop-wide { width: min(22rem, 90vw); }
.conn-add > summary { display: inline-flex; cursor: pointer; list-style: none; }
.conn-add > summary::-webkit-details-marker { display: none; }
.conn-add[open] > summary { display: none; }
.usage-more > summary { cursor: pointer; color: var(--color-text-secondary); font-size: var(--text-sm); margin-top: var(--space-3); }
@media (max-width: 640px) {
  .conn-row { grid-template-columns: 28px minmax(0, 1fr); }
  .conn-status, .conn-actions { grid-column: 2; justify-content: flex-start; }
  .conn-pop { right: auto; left: 0; }
}

/* Overview: main column plus a 300px rail from 1100px, stacked below. */
.overview-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6); align-items: start; }
.overview-main, .overview-rail { min-width: 0; }
.overview-main > .section-head:first-child, .overview-rail > .section-head:first-child { margin-top: 0; }
@media (min-width: 1100px) {
  .overview-layout { grid-template-columns: minmax(0, 1fr) 300px; }
  .overview-rail { position: sticky; top: var(--space-4); }
}
.content:has(.overview-layout) { max-width: 90rem; }
.agent-map-scroll { overflow-x: auto; }
.agent-map-scroll .agent-map { min-width: 720px; width: 100%; height: auto; }
.check-list { list-style: none; margin: 0; padding: var(--space-2) var(--space-4); }
.check-row { display: flex; gap: var(--space-2); align-items: baseline; padding: 6px 0; border-top: 1px solid var(--color-border); }
.check-row:first-child { border-top: 0; }
.check-row a { display: flex; flex: 1; justify-content: space-between; gap: var(--space-2); color: inherit; text-decoration: none; }
.check-mark { width: 1rem; text-align: center; color: var(--color-text-tertiary); }
.check-row.is-done .check-mark { color: var(--state-done); }
.check-row.is-missing .check-detail { color: var(--color-accent); }
.check-detail { color: var(--color-text-secondary); font-size: var(--text-xs); text-align: right; }
.usage-summary .n { font-size: 1.5rem; font-weight: 600; }
.uc-mini { width: 100%; height: 48px; display: block; margin-top: var(--space-2); }

/* Settings: a sticky section list beside short cards. */
.settings-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6); align-items: start; }
.settings-nav { display: flex; flex-wrap: wrap; gap: var(--space-3); font-size: var(--text-sm); }
.settings-nav a { color: var(--color-text-secondary); text-decoration: none; }
.settings-cards { min-width: 0; }
@media (min-width: 900px) {
  .settings-layout { grid-template-columns: 11rem minmax(0, 1fr); }
  .settings-nav { position: sticky; top: var(--space-4); flex-direction: column; gap: var(--space-2); }
}

/* ==== chat polish: layout toggles and answer tables ==== */
/* The chat page has no page header (the chat head names the agent and
   links back), so the chat takes that height too. */
/* No launcher on /chat, so no room kept for it under the page. */
.main:has(.chat-page) { padding-bottom: env(safe-area-inset-bottom, 0px); }
.content:has(.chat-page) { padding-bottom: var(--space-4); }
.chat-main-pane > .chat { height: calc(100dvh - 48px); }
.chat-list-pane { max-height: calc(100dvh - 48px); }
@media (max-width: 960px) {
  .chat-main-pane > .chat { height: 80dvh; }
}
/* The list toggle (portal.js) hides the list; the chat takes the width. */
.chat-page:has(#chat-list-pane[hidden]) { grid-template-columns: minmax(0, 1fr); }
.chat-page:has(#chat-list-pane[hidden]) > .chat-list-pane { display: none; }
.chat-list-toggle[aria-expanded="false"], .chat-wide-toggle[aria-pressed="true"] { color: var(--color-accent); }
/* "Wide": from 1280px the docked rail widens to 60vw (400–960px) and the
   page makes room for it, keeping at least ~560px of page beside the
   sidebar. Below 1280px the toggle has nothing to do. */
.chat-wide-toggle { display: none; }
@media (min-width: 1280px) {
  .chat-wide-toggle:not([hidden]) { display: inline-flex; }
  body.chat-wide { --chat-dock-w: clamp(400px, min(60vw, 100vw - 800px), 960px); }
  body.chat-wide .chat-dock { width: var(--chat-dock-w); }
  body.chat-wide.chat-open .main,
  body.chat-wide:has(.chat-dock:not([hidden])) .main { padding-right: var(--chat-dock-w); }
}

/* Tables in answers: body-size text, a sticky head inside the table's own
   scroll box, hairline rows, and Copy as CSV above (portal.js adds it). */
.markdown-body.chat-md table {
  max-height: min(70vh, 640px);
  overflow: auto;
  font-size: 0.92em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  border-collapse: separate;
  border-spacing: 0;
  max-width: 100%;
  width: max-content;
  background: var(--color-surface);
}
.markdown-body.chat-md table th, .markdown-body.chat-md table td {
  border: 0;
  border-bottom: 1px solid var(--color-border);
  border-right: 1px solid var(--color-border);
  vertical-align: top;
  /* Whole words: a narrow column scrolls the table, never splits a word. */
  overflow-wrap: normal;
  min-width: 10ch;
}
.markdown-body.chat-md table th:last-child, .markdown-body.chat-md table td:last-child { border-right: 0; }
.markdown-body.chat-md table tr:last-child > td { border-bottom: 0; }
.markdown-body.chat-md table th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--color-surface-sunken);
  text-align: left;
  font-weight: 600;
  white-space: nowrap;
}
.markdown-body.chat-md table tbody tr:nth-child(even) > td { background: color-mix(in srgb, var(--color-surface-sunken) 45%, var(--color-surface)); }
.chat-table-tools { display: flex; justify-content: flex-end; margin: 0 0 var(--space-1); }
.chat-table-tools + table { margin-top: 0; }
.chat-table-tools .chat-copy { position: static; }
.chat-copy:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }
.chat-main-pane .chat-editor { margin: var(--space-1) 0; padding: 0 var(--space-5); }
.chat-dock .chat-editor { padding: 0 var(--space-3); }
@media (max-width: 767px) { .chat-main-pane .chat-editor { padding: 0 var(--space-3); } }

/* UX-17: a POST form that is submitting. */
.btn.is-busy { opacity: .7; cursor: progress; }
