/* Vibe Modeling — chat canvas.
   Design contract: product spec v2 §9 (user journey and UX design system).

   Neutral surfaces match the model explorer. Muted tensor colors and a
   restrained blue accent identify structure, state, and primary actions.
   Every result retains its provenance label.

   Shape rule (locked, shared with the landing): cards 12px radius, controls
   and inputs 8px, pills 999px. One primary button, one secondary (.btn.ghost),
   and text buttons for the quiet third tier. */

/* ========== Design tokens (plan 36, design refresh; docs/design-tokens.md) ==========
   The one place the app's look is decided. ab.css mirrors this block for the app-builder pages, and
   report.css's .dc scope copies the colour subset; rules use these names, not raw sizes, radii, shadows or durations.

   Type       font-sans (UI text, the platform's own face), font-brand (the wordmark only), display (headings),
              mono (ids, numbers, code); fs-xs 12 · fs-sm 13 · fs-base 14 · fs-md 15 · fs-lg 17 · fs-xl 20 · fs-2xl 26;
              lh-tight 1.25 · lh-base 1.5; fw-medium 500 · fw-semibold 600 (nothing heavier outside the verdict word)
   Space      sp-1 4 · sp-2 8 · sp-3 12 · sp-4 16 · sp-5 20 · sp-6 24 · sp-8 32 (a 4 px base)
   Radius     r-sm 6 (chips, small controls) · r-md 8 (buttons, inputs) · r-lg 12 (cards; r-card is the same) ·
              r-xl 16 (sheets, the composer) · r-pill 999
   Elevation  shadow-xs (buttons) · shadow-sm (cards; shadow is the same) · shadow-md (hover, the composer;
              shadow-lift is the same) · shadow-lg (menus, popovers, modals)
   Lines      border (hairline: cards, dividers) · line (inputs, stronger edges) · line2 (table rows)
   Colour     paper (page) · card (surface) · paper2 (sunken or raised panel) · ink / ink2 / ink-muted (text; all three
              pass AA on paper and card; ink3 is 4.2:1 on paper, so it is for marks and large text only) ·
              accent / accent-ink / accent-soft / accent-line (the one accent)
   Semantic   ok · warn · bad · info, each with -soft (fill) and -line (edge): verdicts, gates, status chips, notices
   Motion     dur-fast 150ms · dur 200ms · ease (standard) · e (expressive, for entrances); reduced motion is honoured
   Focus      focus-ring (a 3 px halo) next to the 2 px accent outline every :focus-visible gets

   Frozen values: paper, card, ink, ink2, ink3, line, line2, accent, accent-ink, accent-soft, ok, bad, bad-soft,
   amber, amber-soft, run2, sans and mono are copied by report.css, and tests/test_data_ui_render.py holds the copy
   to these values, so a new look comes from a new token, never from changing one of those. One committed light
   palette: there is no OS dark mode (plan 27 phase U; tests/test_ui_assets.py). The build canvas below redefines
   the colour tokens for its dark instrument ground. */

:root{
  --paper:#f5f6f8; --paper2:#fafbfc; --card:#ffffff; --ink:#131d3b;
  --ink2:#465273; --ink3:#6b7590; --ink-muted:#5e6883;
  --line:rgba(96,114,146,.22); --line2:rgba(96,114,146,.10); --border:rgba(96,114,146,.16);
  --accent:#1a56ff; --accent-ink:#0f47e6; --accent-soft:rgba(26,86,255,.10); --accent-line:rgba(26,86,255,.30);
  --ok:#137a4a; --ok-soft:rgba(19,122,74,.10); --ok-line:rgba(19,122,74,.30);
  --bad:#b42318; --bad-soft:rgba(180,35,24,.10); --bad-line:rgba(180,35,24,.30);
  --warn:#8a5a00; --warn-soft:rgba(185,141,46,.14); --warn-line:rgba(185,141,46,.42);
  --info:#0f47e6; --info-soft:rgba(26,86,255,.07); --info-line:rgba(26,86,255,.22);
  /* the platform's own UI face; the wordmark keeps the landing's face; technical values stay mono */
  --sans:"Avenir Next","Segoe UI",Arial,sans-serif;
  --font-sans:-apple-system,BlinkMacSystemFont,"Segoe UI Variable Text","Segoe UI",system-ui,Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-brand:"Avenir Next","Segoe UI",Arial,sans-serif;
  --display:-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",system-ui,Roboto,"Helvetica Neue",Arial,sans-serif;
  --mono:"SF Mono","JetBrains Mono","IBM Plex Mono",Menlo,ui-monospace,Consolas,monospace;
  --fs-xs:12px; --fs-sm:13px; --fs-base:14px; --fs-md:15px; --fs-lg:17px; --fs-xl:20px; --fs-2xl:26px;
  --lh-tight:1.25; --lh-base:1.5; --fw-medium:500; --fw-semibold:600;
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:24px; --sp-8:32px;
  --r-sm:6px; --r-md:8px; --r-lg:12px; --r-xl:16px; --r-pill:999px; --r-card:12px;
  --shadow-xs:0 1px 2px rgba(16,24,40,.05);
  --shadow-sm:0 1px 2px rgba(16,24,40,.04), 0 1px 3px rgba(16,24,40,.06);
  --shadow-md:0 6px 16px -4px rgba(16,24,40,.10), 0 2px 4px -2px rgba(16,24,40,.05);
  --shadow-lg:0 18px 44px -12px rgba(16,24,40,.24), 0 4px 10px -4px rgba(16,24,40,.08);
  --shadow:0 1px 2px rgba(16,24,40,.04), 0 1px 3px rgba(16,24,40,.06);
  --shadow-lift:0 6px 16px -4px rgba(16,24,40,.10), 0 2px 4px -2px rgba(16,24,40,.05);
  --focus-ring:0 0 0 3px rgba(26,86,255,.22);
  --dur-fast:150ms; --dur:200ms; --ease:cubic-bezier(.2,0,0,1);
  --e:cubic-bezier(.22,1,.36,1); --io:cubic-bezier(.65,0,.35,1);
  --rail:min(46vw, 560px);
  --col:768px;
  /* runs in the training-metrics view: distinct in hue and in lightness */
  --run1:#1a56ff; --run2:#d9480f; --run3:#137a4a; --run4:#7b2ff7; --run5:#b98d2e;
  --amber:#b98d2e; --amber-soft:rgba(185,141,46,.18);
}
*{box-sizing:border-box}
*{scrollbar-width:thin; scrollbar-color:rgba(96,114,146,.32) transparent}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--paper); color:var(--ink);
  font-family:var(--font-sans); font-size:var(--fs-base); line-height:var(--lh-base);
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
  height:100dvh; overflow:hidden;
}
button{font:inherit}
h1,h2,h3,h4{font-family:var(--display); font-weight:var(--fw-semibold); letter-spacing:-.01em}
:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
::selection{background:rgba(26,86,255,.18)}

/* ---------- shell ---------- */
.shell{display:flex; flex-direction:column; height:100dvh}
.topbar{
  flex:none; background:var(--card); border-bottom:1px solid var(--border);
  display:flex; align-items:center; gap:var(--sp-2); padding:var(--sp-2) var(--sp-4); flex-wrap:wrap; min-height:52px;
}
.brand{font-family:var(--font-brand); font-weight:650; font-size:16px; letter-spacing:.01em;
  text-decoration:none; color:var(--ink);
  display:inline-flex; align-items:center; min-height:36px; padding:2px 0; border-radius:var(--r-md);
  transition:color var(--dur) var(--ease)}
.brand:hover{color:var(--accent-ink)}
.brand .dot{color:var(--accent)}
.brand{gap:var(--sp-2)}
.brand-mark{width:24px; height:24px; border-radius:7px; flex:none; box-shadow:0 4px 12px -6px rgba(26,86,255,.7)}
.brand-word{font:500 17px/1 var(--font-brand); letter-spacing:-.02em; color:var(--ink)} .brand-word b{font-weight:700}
.domain{font-size:var(--fs-xs); color:var(--ink-muted); font-family:var(--mono); letter-spacing:.06em; text-transform:uppercase; padding-left:var(--sp-3); border-left:1px solid var(--border)}
.topbar .spacer{margin-left:auto}
.legend{display:flex; gap:6px; align-items:center; font-size:11px; color:var(--ink-muted)}
.backend-chip{
  font-family:var(--mono); font-size:11.5px; padding:4px 9px; border-radius:var(--r-pill);
  border:1px solid var(--border); background:var(--card); color:var(--ink2); letter-spacing:.02em;
}
.main{flex:1; display:flex; min-height:0}

/* ---------- lineage chips: structural, every number gets one ----------
   The border style is the label (solid, dashed, dotted, double): keep them distinguishable. */
.lin{
  display:inline-block; font-family:var(--mono); font-size:11px; line-height:1.2;
  padding:2px 6px; border-radius:var(--r-sm); border:1px solid var(--line);
  color:var(--ink2); background:transparent; white-space:nowrap; vertical-align:1px;
  letter-spacing:.02em;
}
.lin[data-l="measured"]{background:var(--accent); border-color:var(--accent);
  color:var(--paper); font-weight:600}
.lin[data-l="test_fixture"]{border-style:dashed}
.lin[data-l="estimate"],.lin[data-l="estimated"]{border-color:var(--accent); color:var(--accent-ink)}
.lin[data-l="indicative"]{border-style:dotted; border-color:var(--accent); color:var(--accent-ink)}
.lin[data-l="model_judged"]{border-style:double; border-width:3px; padding:0 4px}
.lin[data-l="unavailable"]{color:var(--ink-muted)}
.lin[data-l="reported"]{border-style:dashed; color:var(--ink2)}
.lin[data-l="in_your_words"]{border-color:var(--ink2); color:var(--ink2)}
.disc{margin:var(--sp-3) 0}
.disc-counts{font-family:var(--mono); font-size:11.5px; color:var(--ink-muted); margin:0 0 var(--sp-2)}
/* one candidate per row inside the plan card, divided by a hairline: rows, not cards inside a card */
.disc-row{display:block; border:0; border-top:1px solid var(--line2); border-radius:0; padding:var(--sp-3) var(--sp-1); margin:0;
  background:transparent; transition:background var(--dur-fast) var(--ease)}
.disc-row.pick{cursor:pointer; border-radius:var(--r-md)}
.disc-row.pick:hover{background:var(--paper2)}
.disc-row.pick input{margin-right:var(--sp-2)}
.disc-head{display:flex; gap:6px var(--sp-2); align-items:center; flex-wrap:wrap; font-size:var(--fs-sm)}
.disc-head .mono{font-weight:600; font-size:var(--fs-sm); color:var(--ink)}
/* the licence keeps its dashed `reported` edge (that is the lineage label); it just reads quieter here */
.disc-head .lin{color:var(--ink-muted); background:var(--paper2)}
.disc-run{font:500 var(--fs-xs)/1.3 var(--font-sans); letter-spacing:0; padding:2px 8px; border-radius:var(--r-pill); border:1px solid var(--border); color:var(--ink-muted); background:var(--paper)}
.disc-run.now{color:var(--ok); border-color:var(--ok-line); background:var(--ok-soft)}
.disc-run.load{color:var(--accent-ink); border-color:var(--accent-line); background:var(--accent-soft)}
.disc-why{font-size:var(--fs-xs); color:var(--ink-muted); margin-top:var(--sp-1); line-height:var(--lh-base)}
.disc-rej{font-size:var(--fs-xs); color:var(--ink-muted); margin-top:var(--sp-2)}
.disc-rej summary{cursor:pointer}

/* ---------- chat rail ----------
   Chat first: one centred column, the composer at the bottom. The canvas is a
   side panel that slides in beside it once there is a plan or a Build. */
.rail{
  flex:1 1 auto; min-width:0; display:flex; flex-direction:column; min-height:0; background:var(--paper);
}
.thread{flex:1; overflow-y:auto; padding:var(--sp-6) 22px var(--sp-2); scroll-behavior:smooth}
.thread > *, .thread > .msg, .thread > .card{max-width:var(--col); margin-left:auto; margin-right:auto}
.shell[data-empty="true"] .thread{display:flex; flex-direction:column; justify-content:safe center}
.sr{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap}

/* the empty state */
.hero{width:100%; padding:var(--sp-2) 0 var(--sp-1); animation:rise .35s var(--e)}
.hero-title{font:600 clamp(22px, 3vw, 28px)/1.2 var(--display); letter-spacing:-.022em; margin:0 0 var(--sp-2); text-align:center}
.hero-sub{color:var(--ink2); font-size:var(--fs-base); margin:0 auto var(--sp-6); text-align:center; max-width:58ch}
.hero .ways{grid-template-columns:repeat(3, minmax(0, 1fr))}
.msg{margin:0 0 var(--sp-5); display:flex; animation:rise .28s cubic-bezier(.16,1,.3,1)}
.msg.user{justify-content:flex-end}
.bubble{
  max-width:min(100%,52ch); background:var(--card); border:1px solid var(--border);
  border-radius:14px; padding:10px 14px; box-shadow:var(--shadow-xs); font-size:var(--fs-md); line-height:1.55;
}
.msg.user .bubble{background:var(--accent-soft); border-color:transparent; box-shadow:none}
.bubble p{margin:0 0 var(--sp-2)}
.bubble p:last-child{margin-bottom:0}
.who{font-size:var(--fs-xs); color:var(--ink-muted); margin-bottom:var(--sp-1); letter-spacing:.01em}
.msg.user .who{text-align:right}
.qs{margin:10px 0 0; padding-left:18px; font-size:var(--fs-base); color:var(--ink2)}
.qs li{margin:var(--sp-1) 0}

.composer{flex:none; padding:var(--sp-2) 22px var(--sp-4); background:var(--paper)}
.composer > *{max-width:var(--col); margin-left:auto; margin-right:auto}
.composer .hint{text-align:center}
.suggest{display:flex; gap:6px; flex-wrap:wrap; margin-bottom:10px}
/* `display:flex` beats the hidden attribute, which is how an invisible panel
   once swallowed every click on this page. Never remove this line. */
.suggest[hidden]{display:none}
.suggest button{
  background:var(--card); border:1px solid var(--border); color:var(--ink2); text-align:left;
  border-radius:var(--r-xl); padding:6px 12px 6px 24px; font-size:var(--fs-sm); cursor:pointer; position:relative; line-height:1.4;
  box-shadow:var(--shadow-xs);
}
.suggest button::before{content:"›"; position:absolute; left:11px; top:5px; color:var(--accent); font-weight:600}
.suggest button{transition:border-color var(--dur) var(--ease), color var(--dur) var(--ease), background var(--dur) var(--ease)}
.suggest button:hover{border-color:var(--accent-line); color:var(--accent-ink); background:var(--accent-soft)}
.composerow{display:flex; gap:var(--sp-2); align-items:flex-end; background:var(--card); border:1px solid var(--line);
  border-radius:var(--r-xl); padding:6px; box-shadow:var(--shadow-md);
  transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease)}
.composerow:focus-within{border-color:var(--accent); box-shadow:var(--focus-ring), var(--shadow-md)}
.composerow .send{border-radius:10px; height:40px}
.composerow .plus{
  flex:none; height:40px; padding:0 12px; border-radius:10px; border:1px solid var(--border); background:var(--paper2);
  color:var(--ink2); font:500 var(--fs-sm)/1 var(--font-sans); cursor:pointer;
  transition:border-color var(--dur) var(--ease), background var(--dur) var(--ease), color var(--dur) var(--ease);
  display:inline-flex; align-items:center; gap:6px;
}
.composerow .plus b{font-size:17px; font-weight:400; line-height:1; color:var(--accent)}
.composerow .plus:hover{background:var(--paper); color:var(--ink)}
.ask{font-size:var(--fs-lg); font-weight:600; letter-spacing:-.015em; margin:0 0 var(--sp-3)}
.ways{display:grid; gap:10px; grid-template-columns:1fr 1fr}
@media (max-width:900px){.ways{grid-template-columns:1fr}}
.way-eg{font-family:var(--mono); font-size:11px; color:var(--ink-muted); line-height:1.6}
.way.rec::after{content:"recommended"; position:absolute; top:12px; right:12px; font:500 10.5px/1 var(--font-sans); letter-spacing:.04em;
  text-transform:uppercase; color:var(--accent-ink); background:var(--accent-soft); border-radius:var(--r-pill); padding:4px 8px}
/* beside an open canvas the cards are narrow: the badge takes its own line above the title instead of covering it */
.shell[data-canvas="open"] .way.rec::after{position:static; order:-1; justify-self:start}
.way{position:relative}
.rank{display:inline-block; margin-left:var(--sp-2); font:500 10.5px/1 var(--mono); letter-spacing:.04em; text-transform:uppercase;
  padding:4px 7px; border-radius:var(--r-pill); border:1px solid var(--border); color:var(--ink-muted); vertical-align:middle}
.rank.recommended{color:var(--ok); border-color:var(--ok-line); background:var(--ok-soft)}
.rank.possible{color:var(--accent-ink); border-color:var(--accent-line); background:var(--accent-soft)}
.floor{font-size:var(--fs-xs); color:var(--ink-muted); display:inline-flex; align-items:center; gap:5px}
.floor input{width:64px; border:1px solid var(--line); border-radius:var(--r-sm); padding:5px 7px; font:inherit; background:var(--card); color:var(--ink)}
tr.winner td{background:var(--accent-soft)}
.models-link{margin-left:14px; color:var(--accent-ink); text-decoration:none; border-bottom:1px solid transparent}
.models-link:hover{border-color:var(--accent)}
.model{border:1px solid var(--border); border-radius:var(--r-lg); padding:var(--sp-3) 14px; margin:10px 0; background:var(--card)}
.model-head{display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin-bottom:6px}
.versions{list-style:none; margin:0; padding:0; font-size:var(--fs-sm); color:var(--ink2)}
.versions li{padding:6px 0; border-top:1px solid var(--line2); display:flex; gap:6px; flex-wrap:wrap; align-items:center}
.versions a{color:var(--accent-ink)}
.third-way{font-size:var(--fs-sm); color:var(--ink-muted); margin:10px 0 0}
/* the start card folds to one line once a way is chosen */
.chosen{display:flex; align-items:center; gap:10px; flex-wrap:wrap; font-size:var(--fs-sm); color:var(--ink2)}
.chosen b{color:var(--ink)} .chosen b::before{content:"→ "; color:var(--accent)}
.chosen button{background:none; border:0; color:var(--accent-ink); font:inherit; font-weight:500; cursor:pointer; padding:0; border-radius:var(--r-sm)}
.third-way button{background:none; border:0; color:var(--accent-ink); font:inherit; font-weight:500; cursor:pointer; padding:0; border-radius:var(--r-sm)}
.chosen button:hover, .third-way button:hover{text-decoration:underline; text-underline-offset:3px}
.composerow textarea{
  flex:1; min-width:0; resize:none; border:0; border-radius:10px;
  padding:10px 8px; font:inherit; font-size:var(--fs-md); background:transparent; color:var(--ink);
  min-height:40px; max-height:200px;
}
.composerow textarea::placeholder{color:var(--ink-muted)}
.composerow textarea:focus{outline:none}
.hint{font-size:var(--fs-xs); color:var(--ink-muted); margin-top:var(--sp-2)}
/* a key pasted into a composer: said under the box, the draft kept (credential_guard.js) */
.cred-warn{margin:var(--sp-2) 0 0; padding:var(--sp-2) 10px; border-radius:var(--r-md); font-size:var(--fs-sm); color:var(--bad); background:var(--bad-soft);
  border:1px solid var(--bad-line); overflow-wrap:anywhere}
.cred-warn a{color:inherit; font-weight:600}

/* ---------- buttons ----------
   .btn is the primary, .btn.ghost the secondary (white, hairline, neutral text), and a bare
   text button (.chosen button, .third-way button) the quiet third tier. */
.btn{
  background:var(--accent); color:var(--paper); border:1px solid var(--accent);
  border-radius:var(--r-md); padding:7px 14px; font-size:var(--fs-sm); font-weight:var(--fw-medium); line-height:1.4;
  cursor:pointer; box-shadow:var(--shadow-xs), inset 0 1px 0 rgba(255,255,255,.12);
  transition:background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
             box-shadow var(--dur-fast) var(--ease), transform .1s var(--ease);
}
.btn:hover{background:var(--accent-ink); border-color:var(--accent-ink)}
.btn:active{transform:scale(.98)}
.btn:disabled{opacity:.45; cursor:default; transform:none}
.btn.ghost{background:var(--card); color:var(--ink); border-color:var(--line); box-shadow:var(--shadow-xs)}
.btn.ghost:hover{border-color:var(--accent-line); background:var(--paper2); color:var(--accent-ink)}
.btn.sm{padding:5px 11px; font-size:12.5px}
a.btn{text-decoration:none; display:inline-block}

/* ---------- cards ---------- */
.card{
  background:var(--card); border:1px solid var(--border); border-radius:var(--r-card);
  box-shadow:var(--shadow-sm); margin:0 0 var(--sp-4); overflow:hidden;
  animation:rise .3s cubic-bezier(.16,1,.3,1);
}
.card-head{
  display:flex; align-items:center; gap:10px; padding:var(--sp-3) var(--sp-4);
  border-bottom:1px solid var(--line2);
}
.card-head h3{margin:0; font-size:var(--fs-base); font-weight:var(--fw-semibold); letter-spacing:-.01em}
.card-head .state{margin-left:auto; font-size:var(--fs-xs); color:var(--ink-muted);
  display:flex; align-items:center; gap:6px; background:var(--paper); border-radius:var(--r-pill); padding:3px 9px}
.state .pulse{width:6px; height:6px; border-radius:50%; background:var(--accent);
  animation:pulse 1.4s ease-in-out infinite}
.card-body{padding:14px var(--sp-4) var(--sp-4)}
.card-body > :first-child{margin-top:0}
.card-body > :last-child{margin-bottom:0}
.card-body h4{font-size:var(--fs-xs); font-weight:var(--fw-semibold); color:var(--ink2); letter-spacing:.02em; margin:var(--sp-5) 0 var(--sp-2)}
.card-actions{display:flex; gap:var(--sp-2); padding:0 var(--sp-4) var(--sp-4); flex-wrap:wrap}
.sub{color:var(--ink2); font-size:var(--fs-sm); margin:0 0 10px}
.kv{display:grid; grid-template-columns:minmax(120px,170px) 1fr; gap:6px var(--sp-3);
  font-size:var(--fs-sm); margin:10px 0}
.kv dt{color:var(--ink-muted)}
.kv dd{margin:0; overflow-wrap:anywhere}
.num{font-family:var(--mono); font-variant-numeric:tabular-nums}
.mono{font-family:var(--mono); font-size:.92em; overflow-wrap:anywhere}
.notice{
  border:1px solid var(--info-line); background:var(--info-soft);
  padding:var(--sp-2) var(--sp-3); border-radius:var(--r-md); font-size:var(--fs-sm); margin:var(--sp-2) 0;
  color:var(--ink2);
}
.notice.warn{border-color:var(--bad-line); background:var(--bad-soft)}
.empty-note{color:var(--ink-muted); font-size:var(--fs-sm); padding:var(--sp-6) var(--sp-4); text-align:center;
  border:1px dashed var(--line); border-radius:var(--r-lg)}
.skel{border-radius:var(--r-sm); background:linear-gradient(90deg,var(--line2),var(--paper),var(--line2));
  background-size:200% 100%; animation:shimmer 1.5s linear infinite}
.skel.line{height:12px; margin:var(--sp-2) 0}
.skel.block{height:64px; margin:var(--sp-2) 0; border-radius:var(--r-md)}

/* ---------- tables: hairline rows, no boxed grid, tabular numbers ---------- */
.tblwrap{overflow-x:auto; margin:10px -18px; padding:0 18px}
table{border-collapse:collapse; width:100%; font-size:var(--fs-sm); font-variant-numeric:tabular-nums}
th,td{text-align:left; padding:var(--sp-2) 10px; border-bottom:1px solid var(--line2);
  white-space:nowrap}
th{color:var(--ink-muted); font-weight:var(--fw-medium); font-size:var(--fs-xs); letter-spacing:.01em;
  border-bottom-color:var(--border)}
tbody tr{transition:background var(--dur-fast) var(--ease)}
tbody tr:hover td{background:rgba(96,114,146,.04)}
td.n{font-family:var(--mono); font-variant-numeric:tabular-nums}
tr.regressed td{background:var(--bad-soft)}
/* Predictions are structured JSON and can be long. Wrapping keeps the
   prediction and the user's target side by side, which is the whole point of
   showing them — a column the reader has to scroll to reach teaches nothing. */
td.wrap{white-space:normal; word-break:break-word; min-width:11ch; max-width:26ch;
  font-family:var(--mono); font-size:11.5px; line-height:1.4}

/* ---------- bars ---------- */
.bar-row{display:grid; grid-template-columns:minmax(90px,132px) 1fr auto; gap:10px;
  align-items:center; padding:6px 0; font-size:var(--fs-sm)}
.bar-row .who2{color:var(--ink2)}
.bar-track{height:8px; background:var(--line2); border-radius:var(--r-pill);
  position:relative; overflow:hidden}
.bar-fill{position:absolute; inset:0 auto 0 0; background:var(--accent);
  border-radius:var(--r-pill); transition:width .5s cubic-bezier(.16,1,.3,1)}
.bar-row.adapted .bar-fill{background:var(--ink)}
.bar-ci{position:absolute; top:50%; height:1px; background:var(--ink3);
  transform:translateY(-50%)}

/* ---------- gates ---------- */
.gates{list-style:none; margin:var(--sp-3) 0; padding:0; display:grid; gap:6px}
.gate{border:1px solid var(--border); border-radius:10px; padding:10px var(--sp-3); background:var(--card);
  display:grid; grid-template-columns:22px 1fr; gap:10px; font-size:var(--fs-sm)}
.gate .mark{font-family:var(--mono); font-weight:600; text-align:center}
.gate.pass .mark{color:var(--ok)}
.gate.fail{border-color:var(--bad-line); background:var(--bad-soft)}
.gate.fail .mark{color:var(--bad)}
.gate.skip{opacity:.72; border-style:dashed}
.gate.skip .mark{color:var(--ink3)}
.gate .gname{font-weight:var(--fw-semibold)}
.gate .gdetail{color:var(--ink2); font-size:12.5px; margin-top:3px}
/* Seam 0, F2: the last ten uses of a credential, under its row. Monospace
   because they are timestamps and routes read in a column, and dense because
   ten of them should not push the rest of the card off the screen. */
.gate .uses{list-style:none; margin:6px 0 0; padding:0;
  font:400 11.5px/1.7 var(--mono); color:var(--ink-muted)}
.gate .uses li{white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.gate .gcmp{font-family:var(--mono); font-size:var(--fs-xs); color:var(--ink-muted); margin-top:3px}

.decision{
  display:flex; align-items:baseline; gap:var(--sp-3); flex-wrap:wrap;
  padding:14px var(--sp-4); border-radius:var(--r-lg); margin:var(--sp-3) 0 var(--sp-1);
  border:1px solid var(--border);
}
.decision.ship{background:var(--ok-soft); border-color:var(--ok-line)}
.decision.noship{background:var(--paper2)}
/* the verdict badge: the landing explorer's word, same face, same colours */
.decision .word{font:700 20px/1 var(--mono); letter-spacing:-.02em; color:var(--bad)}
.decision.ship .word{color:var(--ok)}
.decision.noship{border-color:var(--bad-line); background:var(--bad-soft)}
.decision .why{font-size:var(--fs-sm); color:var(--ink2); flex:1; min-width:200px}

/* ---------- canvas ---------- */
.canvaswrap{flex:0 0 min(58vw, 900px); position:relative; min-width:0; background:var(--paper2);
  overflow:hidden; border-left:1px solid var(--line); animation:slidein .32s var(--e)}
/* Not on the screen until there is something to show, and closed when the person closes it. */
.shell[data-canvas="none"] .canvaswrap, .shell[data-canvas="closed"] .canvaswrap{display:none}
.shell[data-canvas="open"] .rail{flex-basis:var(--rail); min-width:360px}
.view-build[hidden]{display:none}
.view-build{font:500 var(--fs-sm)/1 var(--font-sans); padding:7px 12px; border-radius:var(--r-md); cursor:pointer;
  border:1px solid var(--accent-line); background:var(--accent-soft); color:var(--accent-ink);
  transition:background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease)}
.view-build:hover{background:rgba(26,86,255,.16)}
.view-build[aria-expanded="true"]{background:var(--accent); border-color:var(--accent); color:#fff}
/* The legend sits at the bottom of the canvas, out of the graph's way. */
.canvas-legend{position:absolute; z-index:3; left:12px; bottom:12px; display:flex; gap:6px; flex-wrap:wrap; pointer-events:none}
.canvaswrap .legend .lin{background:rgba(10,16,32,.7)}
.canvaswrap .legend .lin[data-l="measured"]{background:var(--accent)}
.canvas-toolbar{
  position:absolute; z-index:3; top:12px; left:12px; right:12px;
  display:flex; gap:var(--sp-2); align-items:center; pointer-events:none; flex-wrap:wrap;
}
.canvas-toolbar > *{pointer-events:auto}
.canvas-title{font-size:12.5px; color:var(--ink-muted);
  background:var(--paper); border:1px solid var(--line); border-radius:var(--r-md);
  padding:5px 12px}
.zoomers{margin-left:auto; display:flex; gap:6px}
.zoomers button{
  width:32px; height:32px; border-radius:var(--r-md); border:1px solid var(--line);
  background:var(--paper); color:var(--ink2); cursor:pointer; font-size:14px;
  line-height:1; display:grid; place-items:center;
  transition:border-color var(--dur) var(--ease), color var(--dur) var(--ease),
             background var(--dur) var(--ease);
}
.zoomers button.wide{width:auto; padding:0 11px; font-size:var(--fs-xs)}
.zoomers button:hover{border-color:var(--accent); color:var(--accent-ink)}
#graph{position:absolute; inset:0; cursor:grab;
  background-image:radial-gradient(var(--line) 1px, transparent 1px);
  background-size:22px 22px;}
#graph.dragging{cursor:grabbing}
#viewport{position:absolute; top:0; left:0; transform-origin:0 0;
  will-change:transform}
#edges{position:absolute; top:0; left:0; overflow:visible; pointer-events:none}
.edge{fill:none; stroke:var(--line); stroke-width:2}
.edge.live{stroke:var(--accent); stroke-dasharray:5 5; animation:flow 1s linear infinite}
.edge.done{stroke:var(--ink3)}

.node{
  position:absolute; width:214px; background:var(--card);
  border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--shadow);
  font-size:12.5px; overflow:hidden; transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.node:hover{box-shadow:var(--shadow-lift)}
.node.selected{border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-soft)}
.node .nhead{display:flex; align-items:center; gap:7px; padding:var(--sp-2) 11px;
  border-bottom:1px solid var(--line2); font-weight:var(--fw-semibold)}
.node .ntag{font-family:var(--mono); font-size:11px; color:var(--ink3);
  border:1px solid var(--line); border-radius:var(--r-sm); padding:1px 5px}
.node .nbody{padding:9px 11px; color:var(--ink2); min-height:34px}
.node .nrow{display:flex; justify-content:space-between; gap:var(--sp-2); padding:1px 0}
.node .nrow b{font-family:var(--mono); font-weight:600; color:var(--ink);
  font-variant-numeric:tabular-nums}
.node .nempty{color:var(--ink3); font-style:normal}
.node .nbar{height:4px; background:var(--line2); position:relative}
.node .nbar i{position:absolute; inset:0 auto 0 0; background:var(--accent);
  transition:width .4s ease}
.node[data-state="idle"]{opacity:.62}
.node[data-state="running"]{border-color:var(--accent)}
.node[data-state="running"] .nhead{background:var(--accent-soft)}
.node[data-state="done"] .nhead{background:var(--ok-soft)}
.node[data-state="failed"]{border-color:var(--bad)}
.node[data-state="failed"] .nhead{background:var(--bad-soft)}
.node[data-state="skipped"]{opacity:.5; border-style:dashed}
.node[data-state="waiting"]{border-color:var(--amber)}
.node[data-state="waiting"] .nhead{background:var(--amber-soft)}
.node[data-state="waiting"] .dot{background:var(--amber); animation:pulse 1.4s ease-in-out infinite}
.node{cursor:pointer}
.node:focus-visible{outline:2px solid #8fb0ff; outline-offset:3px}
.node .nnote{font-size:11.5px; color:var(--ink3); margin-top:var(--sp-1); line-height:1.4}
.node .dot{width:7px; height:7px; border-radius:50%; background:var(--ink3); flex:none}
.node[data-state="running"] .dot{background:var(--accent); animation:pulse 1.4s ease-in-out infinite}
.node[data-state="done"] .dot{background:var(--ok)}
.node[data-state="failed"] .dot{background:var(--bad)}

.spark{display:block; width:100%; height:34px; margin-top:var(--sp-1)}
.spark path{fill:none; stroke:var(--accent); stroke-width:1.5}
.spark .axis{stroke:var(--line); stroke-width:1}

/* ---------- workflow rail ---------- */
.wf{list-style:none; margin:0; padding:0 var(--sp-4); display:flex; align-items:center; gap:0;
  border-bottom:1px solid var(--border); background:var(--card); overflow-x:auto; flex:none;
  scrollbar-width:none}
/* `display:flex` beats the hidden attribute; the rail stays off until a plan exists. */
.wf[hidden]{display:none}
.wf li{display:flex; align-items:center; gap:var(--sp-2); padding:var(--sp-2) 0; font-size:var(--fs-xs);
  color:var(--ink-muted); white-space:nowrap}
.wf li + li::before{content:""; width:22px; height:1px; background:var(--line); margin:0 10px; flex:none;
  transition:background .4s ease}
.wf li[data-state="done"] + li::before{background:var(--ok)}
.wf .wf-dot{width:12px; height:12px; border-radius:50%; border:1.5px solid var(--line);
  box-sizing:border-box; flex:none; position:relative; transition:border-color .3s, background .3s}
.wf li[data-state="running"] .wf-dot{border-color:var(--accent-soft); border-top-color:var(--accent);
  animation:spin .8s linear infinite}
.wf li[data-state="waiting"] .wf-dot{border-color:#b98d2e; background:rgba(185,141,46,.18);
  animation:pulse 1.4s ease-in-out infinite}
.wf li[data-state="done"] .wf-dot{border-color:var(--ok); background:var(--ok)}
.wf li[data-state="done"] .wf-dot::after{content:""; position:absolute; left:3px; top:1px; width:3px; height:5px;
  border:solid #fff; border-width:0 1.5px 1.5px 0; transform:rotate(45deg)}
.wf li[data-state="failed"] .wf-dot{border-color:var(--bad); background:var(--bad)}
.wf li[data-state="failed"] .wf-dot::after{content:"×"; position:absolute; inset:0; color:#fff; font:700 9px/9px var(--font-sans); text-align:center}
.wf li[data-state="running"] .wf-name, .wf li[data-state="waiting"] .wf-name{color:var(--ink); font-weight:var(--fw-semibold)}
.wf li[data-state="done"] .wf-name{color:var(--ink2)}
.wf .wf-note{font-family:var(--mono); font-size:11px; color:var(--ink-muted)}
.wf .wf-note:empty{display:none}
@keyframes spin{to{transform:rotate(1turn)}}

/* ---------- the canvas as an instrument: the landing's world, continued ---------- */
.canvaswrap{--paper2:#0a1020; --card:#101a33; --line:rgba(143,176,255,.28); --line2:rgba(143,176,255,.14);
  --ink:#ffffff; --ink2:#c7d0e0; --ink3:#8d99b3; --accent-soft:rgba(26,86,255,.24); --ok-soft:rgba(19,122,74,.32); --bad-soft:rgba(180,35,24,.32);
  --border:rgba(143,176,255,.20); --ink-muted:#9aa5bd;
  background:radial-gradient(60% 50% at 72% 18%, rgba(26,86,255,.22), transparent 60%), radial-gradient(40% 40% at 20% 85%, rgba(0,196,255,.10), transparent 60%), #0a1020}
.canvaswrap .canvas-title{color:#aab6cc; background:rgba(10,16,32,.8); font-family:var(--mono); font-size:11px; letter-spacing:.1em; text-transform:uppercase;
  backdrop-filter:blur(6px)}
.canvaswrap .zoomers button{background:rgba(10,16,32,.8); color:#fff; border-color:rgba(143,176,255,.35)}
.canvaswrap .zoomers button:hover{border-color:#8fb0ff; color:#fff}
.canvaswrap .node{box-shadow:0 14px 34px -20px rgba(0,0,0,.9); color:var(--ink)}
/* before a Build starts the graph is the promise, and it says so */
.canvas-empty{position:absolute; z-index:2; left:50%; bottom:22px; transform:translateX(-50%); width:min(520px,calc(100% - 32px));
  background:rgba(10,16,32,.85); border:1px solid var(--line); border-radius:var(--r-lg); padding:var(--sp-3) var(--sp-4); color:#c7d0e0; font-size:var(--fs-sm); line-height:1.5;
  backdrop-filter:blur(8px); pointer-events:none; animation:rise .4s var(--e)}
.canvas-empty b{color:#fff}
.canvaswrap[data-empty="false"] .canvas-empty{display:none}
.canvaswrap .node .nhead{background:rgba(26,86,255,.08)}
.canvaswrap .edge{stroke:rgba(143,176,255,.35)}
.canvaswrap .edge.live{stroke:#1a56ff} .canvaswrap .edge.done{stroke:#137a4a}
/* page transition from the landing */
@view-transition{navigation:auto}
@keyframes vt-out{to{opacity:0; transform:translateY(-6px)}} @keyframes vt-in{from{opacity:0; transform:translateY(8px)}}
::view-transition-old(root){animation:.22s ease-in both vt-out} ::view-transition-new(root){animation:.34s ease-out both vt-in}

/* ---------- teach: the first-run wedge ---------- */
.field{margin:var(--sp-3) 0}
.field label{display:block; font-size:var(--fs-xs); font-weight:var(--fw-medium); color:var(--ink2); margin-bottom:6px}
.field input,.field select{
  width:100%; box-sizing:border-box; border:1px solid var(--line); border-radius:var(--r-md); padding:8px 11px;
  font:inherit; font-size:var(--fs-base); background:var(--card); color:var(--ink); box-shadow:var(--shadow-xs);
  transition:border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.field input:hover,.field select:hover{border-color:rgba(96,114,146,.34)}
.field input:focus,.field select:focus{outline:2px solid transparent; border-color:var(--accent); box-shadow:var(--focus-ring)}
.ways{display:grid; gap:10px}
.way{
  text-align:left; display:grid; gap:6px; align-content:start; padding:var(--sp-4); cursor:pointer; font:inherit; color:var(--ink);
  background:var(--card); border:1px solid var(--border); border-radius:var(--r-lg); box-shadow:var(--shadow-xs);
  transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.way:hover,.way:focus-visible{border-color:var(--accent-line); box-shadow:var(--shadow-md); transform:translateY(-1px)}
/* the keyboard cue is the 2 px accent outline every :focus-visible gets, and an accent border (5.5:1 on the card) */
.way:focus-visible{border-color:var(--accent); outline:2px solid var(--accent); outline-offset:2px; box-shadow:var(--focus-ring), var(--shadow-md)}
.way-k{font-weight:var(--fw-semibold); font-size:var(--fs-md); letter-spacing:-.01em}
.way-k::before{content:"→ "; color:var(--accent)}
.way-d{font-size:var(--fs-sm); color:var(--ink2); line-height:1.5}
.way-d em{font-style:normal; color:var(--accent-ink); font-weight:var(--fw-medium)}
.way-t{font-family:var(--mono); font-size:11px; color:var(--ink-muted); margin-top:2px}
.cap{position:relative; background:var(--paper2); border:1px solid var(--border); border-radius:var(--r-lg); padding:10px; margin:10px 0}
.cap video{display:block; width:100%; max-height:240px; object-fit:cover; border-radius:var(--r-md); background:#000}
.cap video[hidden]{display:none}
.cap-strip{display:flex; gap:var(--sp-1); flex-wrap:wrap; min-height:38px; margin-top:var(--sp-2)}
.cap-strip:empty{min-height:0; margin-top:0}
.cap-strip img{width:56px; height:42px; object-fit:cover; border-radius:var(--r-sm); border:1px solid var(--border); animation:rise .25s var(--e)}
.cap-meter{font-family:var(--mono); font-size:11.5px; color:var(--ink-muted); margin-top:var(--sp-2)}
.cap-meter.ok{color:var(--ok); font-weight:600}
.cap-tools{display:flex; gap:var(--sp-2); flex-wrap:wrap; align-items:center}
.cap-tools label.btn{display:inline-block; cursor:pointer; line-height:1.3}
.vs{display:grid; gap:6px}
.vs-row{display:flex; gap:var(--sp-3); align-items:baseline; padding:var(--sp-2) var(--sp-3); border-radius:var(--r-md); background:var(--paper2); border:1px solid var(--border)}
.vs-row.yours{background:var(--accent-soft); border-color:var(--accent-line)}
.vs-k{font-size:var(--fs-xs); color:var(--ink-muted); min-width:150px}
.vs-v{font-weight:var(--fw-semibold); font-size:var(--fs-md); letter-spacing:-.01em}
.vs-row.yours .vs-v{color:var(--accent-ink)}
@media (max-width:900px){
  .vs-row{flex-direction:column; gap:2px}
  .cap-strip img{width:48px; height:36px}
}

/* ---------- phones: one-row topbar ---------- */
@media (max-width:900px){
  .topbar{gap:8px; padding:8px 16px; flex-wrap:nowrap}
  .topbar .legend, .topbar .domain{display:none}
  .backend-chip{font-size:10.5px; padding:4px 7px}
  .brand-word{display:none}
  .brand-word{font-size:17px}
  .navmore > summary, .view-build{padding:7px 10px}
}

/* ---------- animation ---------- */
@keyframes rise{from{opacity:0; transform:translateY(6px)} to{opacity:1; transform:none}}
@keyframes pulse{0%,100%{opacity:1} 50%{opacity:.35}}
@keyframes shimmer{from{background-position:200% 0} to{background-position:-200% 0}}
@keyframes flow{to{stroke-dashoffset:-10}}
@keyframes slidein{from{opacity:0; transform:translateX(24px)} to{opacity:1; transform:none}}
@keyframes pop{from{opacity:0; transform:translateY(-4px) scale(.98)} to{opacity:1; transform:none}}
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important}
  .thread{scroll-behavior:auto}
  .way:hover,.way:focus-visible,.btn:active{transform:none}
}

/* ---------- responsive ----------
   One column on a phone: the chat, with a 16px gutter and nothing wider than
   the screen. The canvas is a full-screen sheet the person opens ("View build")
   and closes ("Close", or Escape). */
@media (max-width: 900px){
  .main{flex-direction:column}
  .rail{width:auto; min-width:0; flex-basis:auto}
  .shell[data-canvas="open"] .rail{min-width:0; flex-basis:auto}
  .thread{padding:16px 16px 8px}
  .composer{padding:8px 16px 12px}
  .hero .ways{grid-template-columns:1fr}
  .shell[data-canvas="open"] .canvaswrap{position:fixed; inset:0; z-index:30; flex:none; border-left:0}
  /* On a phone the toolbar is the way out: the title goes, Close stays on screen. */
  .canvas-title{display:none}
  .canvas-toolbar{left:16px; right:16px}
  .zoomers{margin-left:0; width:100%; justify-content:flex-end}
  .canvas-legend{display:none}
  .composerow .plus{padding:0 10px}
  /* 16 px stops iOS zooming the page when the box takes focus */
  .composerow textarea, .field input, .field select{font-size:16px}
}

/* ---------- the door (seam 0): signed out, and who you are signed in as --- */
.who{max-width:32ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.who[data-state="out"]{border-color:var(--accent); color:var(--accent-ink)}
/* `hidden` has to win: a rule that sets display beats the UA stylesheet's
   [hidden]{display:none}, and a full-screen panel nobody can see still eats
   every click underneath it. */
.signin{
  position:fixed; inset:0; z-index:40; background:var(--paper);
  display:flex; align-items:center; justify-content:center; padding:var(--sp-6);
}
.signin[hidden]{display:none}
.signin-card{
  max-width:46ch; background:var(--card); border:1px solid var(--border);
  border-radius:var(--r-xl); padding:var(--sp-8) var(--sp-8) 28px; box-shadow:var(--shadow-lg);
}
.signin-card h1{font:600 20px/1.25 var(--display); margin:0 0 var(--sp-2); letter-spacing:-.015em}
.signin-card p{margin:0 0 var(--sp-5); color:var(--ink2); font-size:var(--fs-base); line-height:1.55}
.signin-go{
  display:inline-block; background:var(--accent); color:#fff; text-decoration:none;
  font:500 var(--fs-base)/1 var(--font-sans); padding:11px 18px; border-radius:var(--r-md); box-shadow:var(--shadow-xs);
  transition:background var(--dur-fast) var(--ease);
}
.signin-go:hover{background:var(--accent-ink)}

/* ---------- connections: what this workspace can reach on your behalf ---- */
.conn-add{display:flex; flex-wrap:wrap; gap:var(--sp-2); margin-top:14px}
.conn-add input,.conn-add select{
  flex:1 1 150px; min-width:0; font:400 var(--fs-sm)/1.3 var(--font-sans); color:var(--ink);
  background:var(--card); border:1px solid var(--line); border-radius:var(--r-md); padding:8px 11px; box-shadow:var(--shadow-xs);
}
.conn-add input:focus,.conn-add select:focus{outline:2px solid transparent; border-color:var(--accent); box-shadow:var(--focus-ring)}
.gates .btn.ghost.sm{margin-left:auto; align-self:center}
/* The S3 paste target: a password input that only ever holds dots (s3sources.js). */
.conn-add input.s3-paste{flex:1 1 60%}
.s3-confirm{flex:1 1 100%; display:flex; flex-wrap:wrap; gap:var(--sp-2); align-items:center; font-size:var(--fs-sm)}
.s3-confirm[hidden],#s3-check[hidden]{display:none}
.s3-advanced{flex:1 1 100%}
.s3-advanced>summary{cursor:pointer; font-size:12.5px; color:var(--ink2)}
.s3-advanced[open]{display:flex; flex-wrap:wrap; gap:var(--sp-2)}
.s3-advanced[open]>summary{flex:1 1 100%}

/* ---------- the reading: what the prompt was understood to mean ---------- */
.reading{
  border:1px solid var(--border); border-left:2px solid var(--accent);
  border-radius:var(--r-md); padding:var(--sp-3) 14px; margin:10px 0 14px; background:var(--paper2);
}
.reading p{margin:0 0 6px; font-size:var(--fs-sm); line-height:1.55}
.reading p:last-of-type{margin-bottom:0}
.reading .said{color:var(--ink)}
.reading-change{display:flex; gap:var(--sp-2); margin-top:10px; flex-wrap:wrap}
.reading-change select{
  flex:1 1 260px; min-width:0; font:400 12.5px/1.3 var(--font-sans); color:var(--ink);
  background:var(--card); border:1px solid var(--line); border-radius:var(--r-md); padding:7px 10px; box-shadow:var(--shadow-xs);
}

/* ---------- why a candidate ranks where it does (seam 1, D3) ---------- */
.disc-terms{margin-top:6px}
.disc-terms>summary{
  font-family:var(--mono); font-size:11px; color:var(--ink-muted); cursor:pointer;
  list-style:none; padding:2px 0;
}
.disc-terms>summary::-webkit-details-marker{display:none}
.disc-terms>summary::before{content:"▸ "; color:var(--ink3)}
.disc-terms[open]>summary::before{content:"▾ "}
.disc-terms table{width:100%; border-collapse:collapse; margin:var(--sp-1) 0 2px}
.disc-terms td{padding:2px 6px 2px 0; font-size:11.5px; color:var(--ink2); vertical-align:middle; border-bottom:0}
.disc-terms td.n{font-family:var(--mono); text-align:right; width:44px; font-variant-numeric:tabular-nums}
.disc-terms td.bar{width:38%}
.disc-terms td.bar i{display:block; height:5px; border-radius:var(--r-pill); background:var(--accent-soft);
  box-shadow:inset 0 0 0 999px var(--accent); min-width:2px}
.disc-terms .hint{margin:6px 0 0}

.disc-run-why{font-size:11.5px; color:var(--ink-muted); margin:2px 0 0 2px}

.disc-loaded{border:1px solid var(--border); border-left:2px solid var(--ok);
  border-radius:var(--r-md); padding:10px var(--sp-3); margin:0 0 10px; background:var(--paper2)}
.disc-loaded b{font-size:var(--fs-xs); font-weight:var(--fw-semibold); color:var(--ink2)}
.disc-loaded ul{margin:6px 0 0; padding-left:18px}
.disc-loaded li{font-size:12.5px; margin:2px 0}
.disc-loaded .hint{margin:6px 0 0}

/* ---------- the one measured line on a discovery card (seam 1, D5) ------ */
.disc-proven{font-size:12.5px; color:var(--ink2); margin:3px 0 2px;
  padding-left:var(--sp-2); border-left:2px solid var(--accent)}
.disc-proven a{color:var(--accent-ink)}

/* The account panel. The chip was already the only place that said who you
   are; it is now also where you stop being them. */
.account{position:relative; display:inline-block}
.account-menu{
  position:absolute; right:0; top:calc(100% + 6px); z-index:60; min-width:25ch;
  background:var(--card); border:1px solid var(--border); border-radius:var(--r-lg);
  padding:14px var(--sp-4); box-shadow:var(--shadow-lg); text-align:left; animation:pop var(--dur) var(--ease);
}
.account-menu[hidden]{display:none}
.account-name{margin:0 0 2px; font:600 var(--fs-sm)/1.35 var(--font-sans); word-break:break-all}
.account-meta{margin:0 0 var(--sp-3); font-size:var(--fs-xs); line-height:1.5; color:var(--ink-muted)}
.account-warn{
  margin:0 0 var(--sp-3); padding:var(--sp-2) 10px; border-radius:var(--r-md); font-size:var(--fs-xs); line-height:1.45;
  background:var(--warn-soft); color:var(--warn); border:1px solid var(--warn-line);
}
.account-warn[hidden]{display:none}
.account-action{
  width:100%; border:1px solid var(--line); background:var(--card); color:var(--ink);
  font:500 var(--fs-sm)/1 var(--font-sans); padding:9px var(--sp-3); border-radius:var(--r-md); cursor:pointer;
  box-shadow:var(--shadow-xs); transition:background var(--dur-fast) var(--ease)
}
.account-action:hover{background:var(--paper)}
button.who{font:inherit; cursor:pointer}

/* The account chip is a MENU, and has to look like one. It shipped styled
   exactly like the static `intake:` chip beside it — no caret, no hover — so
   the sign-out behind it was invisible: the first person to use it reported
   "no place to sign out" while looking straight at the control. A menu
   nobody can see they can open is a menu that does not exist. */
button.who{
  display:inline-flex; align-items:center; gap:7px; cursor:pointer;
  font:500 var(--fs-sm)/1 var(--font-sans); letter-spacing:0; color:var(--ink2);
  padding:7px 10px 7px 12px; border-radius:var(--r-md); border:1px solid var(--border); background:var(--card);
  margin:0; min-height:32px;
  transition:border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
button.who:hover{border-color:var(--line); background:var(--paper)}
button.who:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
/* the caret is a drawn chevron (the 9 px glyph read as a dot); its text stays in the markup, at size 0 */
.who-caret{font-size:0; line-height:0; width:6px; height:6px; flex:none; margin:-3px 2px 0 2px; border:solid currentColor; border-width:0 1.5px 1.5px 0;
  transform:rotate(45deg); opacity:.75; transition:transform var(--dur-fast) var(--ease)}
button.who[aria-expanded="true"] .who-caret{transform:rotate(225deg); margin-top:3px}
button.who[aria-expanded="true"]{border-color:var(--accent-line); background:var(--paper)}

/* ---------- plan 38 P8b: the workspace switcher (ui/static/workspaces.js) ---------- */
.wsswitch{position:relative; display:inline-block; min-width:0}
.wsswitch[hidden]{display:none}
.ws-chip{display:inline-flex; align-items:center; gap:7px; max-width:28ch; min-height:32px; margin:0; cursor:pointer;
  font:500 var(--fs-sm)/1 var(--font-sans); color:var(--ink2); padding:7px 10px 7px 12px; border-radius:var(--r-md);
  border:1px solid var(--border); background:var(--card); transition:border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease)}
.ws-chip:hover{border-color:var(--line); background:var(--paper)}
.ws-chip:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
.ws-chip[aria-expanded="true"]{border-color:var(--accent-line); background:var(--paper)}
.ws-chip[aria-expanded="true"] .who-caret{transform:rotate(225deg); margin-top:3px}
.ws-chip-name{overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; color:var(--ink)}
.ws-chip-meta{font-size:var(--fs-xs); color:var(--ink-muted); white-space:nowrap}
/* bounded by the screen (review of #746: with many workspaces the rows and the form ran off a phone, where the body
   hides overflow): the list scrolls inside the menu, and the form for a new one stays under it */
.ws-menu{position:absolute; right:0; top:calc(100% + 6px); z-index:60; width:min(34ch, calc(100vw - 32px));
  max-height:calc(100vh - 80px); max-height:calc(100dvh - 80px); display:flex; flex-direction:column;
  background:var(--card); border:1px solid var(--border); border-radius:var(--r-lg); padding:12px;
  box-shadow:var(--shadow-lg); text-align:left; animation:pop var(--dur) var(--ease)}
.ws-menu[hidden]{display:none}
.ws-head{flex:none; margin:0 0 6px; font:600 var(--fs-xs)/1.3 var(--font-sans); color:var(--ink-muted); text-transform:uppercase; letter-spacing:.04em}
.ws-list{list-style:none; margin:0 0 10px; padding:0; display:flex; flex-direction:column; gap:2px;
  flex:1 1 auto; min-height:0; overflow-y:auto; overscroll-behavior:contain}
.ws-row{flex:none; display:flex; align-items:center; gap:6px}
.ws-pick{flex:1; min-width:0; display:flex; flex-direction:column; align-items:flex-start; gap:2px; text-align:left; cursor:pointer;
  padding:7px 10px; border:1px solid transparent; border-radius:var(--r-sm); background:transparent; color:var(--ink); font:inherit}
.ws-pick:hover{background:var(--paper)}
.ws-pick[aria-current="true"]{border-color:var(--accent-line); background:var(--accent-soft)}
.ws-pick-name{font:500 var(--fs-sm)/1.3 var(--font-sans); overflow-wrap:anywhere}
.ws-pick-meta{font-size:var(--fs-xs); color:var(--ink-muted)}
.ws-leave{flex:none; border:1px solid var(--line); background:var(--card); color:var(--ink2); border-radius:var(--r-sm);
  font:500 var(--fs-xs)/1 var(--font-sans); padding:6px 8px; cursor:pointer}
.ws-leave:hover{background:var(--paper)}
.ws-new{flex:none; display:flex; flex-wrap:wrap; gap:6px; align-items:center; padding-top:10px; border-top:1px solid var(--line2)}
.ws-new-label{flex-basis:100%; font-size:var(--fs-xs); color:var(--ink-muted)}
.ws-new-name{flex:1 1 12ch; min-width:0; padding:7px 9px; border:1px solid var(--line); border-radius:var(--r-sm); font:inherit; background:var(--card); color:var(--ink)}
.ws-new-go{flex:none; padding:7px 10px; border:1px solid var(--line); border-radius:var(--r-sm); background:var(--card); color:var(--ink); font:500 var(--fs-sm)/1 var(--font-sans); cursor:pointer}
.ws-says{flex:none; margin:8px 0 0; font-size:var(--fs-xs); line-height:1.45; color:var(--warn)}
.ws-says:empty{display:none}
@media (max-width: 900px){
  .ws-chip{max-width:11ch; min-height:44px}
  .ws-chip-meta{display:none}
  .ws-pick, .ws-leave, .ws-new-go, .ws-new-name{min-height:44px}
  .ws-menu{right:-60px}
}

/* ---------- the workspace menu: the nav, folded ---------- */
.navmore{position:relative}
.navmore > summary{list-style:none; cursor:pointer; font:500 var(--fs-sm)/1 var(--font-sans); color:var(--ink2);
  padding:7px 10px 7px 12px; border:1px solid var(--border); background:var(--card); border-radius:var(--r-md); min-height:32px;
  display:flex; align-items:center; transition:background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease)}
.navmore > summary:hover{background:var(--paper); color:var(--ink)}
.navmore > summary::-webkit-details-marker{display:none}
.navmore > summary::after{content:""; width:6px; height:6px; margin:-3px 2px 0 9px; border:solid currentColor; border-width:0 1.5px 1.5px 0;
  transform:rotate(45deg); opacity:.75; transition:transform var(--dur-fast) var(--ease)}
.navmore[open] > summary::after{transform:rotate(225deg); margin-top:3px}
.navmore[open] > summary{background:var(--paper); color:var(--ink); border-color:var(--border)}
.navmore-menu{position:absolute; right:0; top:calc(100% + 6px); z-index:60; min-width:22ch;
  display:flex; flex-direction:column; gap:1px; padding:6px; background:var(--card);
  border:1px solid var(--border); border-radius:var(--r-lg); box-shadow:var(--shadow-lg); animation:pop var(--dur) var(--ease)}
.navmore-menu .models-link{margin:0; padding:7px 10px; border-radius:var(--r-sm); border:0; font-size:var(--fs-sm); color:var(--ink)}
.navmore-menu .models-link:hover{background:var(--paper); color:var(--accent-ink)}
.navmore-menu .backend-chip{margin:6px 10px 2px; align-self:flex-start; white-space:nowrap}

/* ---------- a stage's details (the node panel) ---------- */
.npanel{position:absolute; z-index:4; top:56px; right:12px; bottom:12px; width:min(400px, calc(100% - 24px));
  display:flex; flex-direction:column; background:#0d1630; border:1px solid var(--line); border-radius:var(--r-lg);
  box-shadow:0 24px 60px -24px rgba(0,0,0,.9); color:var(--ink); animation:slidein .25s var(--e)}
.npanel[hidden]{display:none}
.npanel-head{display:flex; align-items:center; gap:10px; padding:var(--sp-3) 14px; border-bottom:1px solid var(--line2)}
.npanel-head h2{margin:0; font:600 var(--fs-md)/1.25 var(--display); letter-spacing:-.01em}
.npanel-head h2:focus{outline:none}
.npanel-state{font:500 11px/1 var(--mono); letter-spacing:.04em; text-transform:uppercase; color:var(--ink3);
  border:1px solid var(--line); border-radius:var(--r-pill); padding:5px 8px}
.npanel-state[data-state="running"]{color:#8fb0ff; border-color:#8fb0ff}
.npanel-state[data-state="done"]{color:#5fd39a; border-color:#5fd39a}
.npanel-state[data-state="failed"]{color:#ff8a80; border-color:#ff8a80}
.npanel-state[data-state="waiting"]{color:#e3b95c; border-color:#e3b95c}
.npanel-close{margin-left:auto; width:32px; height:32px; border-radius:var(--r-md); border:1px solid var(--line);
  background:transparent; color:var(--ink); cursor:pointer; font-size:18px; line-height:1}
.npanel-close:hover{background:rgba(143,176,255,.10)}
.npanel-body{overflow-y:auto; padding:var(--sp-3) 14px var(--sp-4); font-size:var(--fs-sm)}
.npanel-body .kv{grid-template-columns:minmax(96px,140px) 1fr}
.npanel-body .sub{color:var(--ink2)}
.np-h{font:500 11px/1 var(--mono); letter-spacing:.08em; text-transform:uppercase; color:var(--ink3); margin:var(--sp-4) 0 6px}
.np-time{font-family:var(--mono); font-size:var(--fs-xs); color:var(--ink2); margin:0 0 var(--sp-2)}
.np-log{list-style:none; margin:0; padding:0; display:grid; gap:var(--sp-1); font-size:12.5px; color:var(--ink2)}
.np-log li{border-left:2px solid var(--line); padding:2px 0 2px var(--sp-2); overflow-wrap:anywhere}
.np-t{color:var(--ink3); margin-right:6px; font-size:11px}
.np-actions{display:flex; gap:var(--sp-2); flex-wrap:wrap; margin-top:var(--sp-4)}
.np-spark{margin:var(--sp-2) 0}
.npanel .btn.ghost{color:#c7d6ff; background:transparent; border-color:var(--line); box-shadow:none}
.npanel .btn.ghost:hover{background:rgba(143,176,255,.10); color:#fff}
.npanel .notice{background:rgba(26,86,255,.14); border-color:rgba(143,176,255,.24); color:var(--ink2)}
.npanel .notice.warn{background:rgba(180,35,24,.28); border-color:rgba(255,138,128,.3)}
.mini-spark{display:inline-block; vertical-align:middle}
.mini-spark path{fill:none; stroke:var(--accent); stroke-width:1.5}
.npanel .mini-spark path{stroke:#8fb0ff}
@media (max-width: 900px){
  .npanel{top:52px; right:8px; left:8px; bottom:8px; width:auto}
}

/* ---------- training progress, in the chat ---------- */
.live-train{display:flex; gap:10px 14px; align-items:center; flex-wrap:wrap; margin:var(--sp-3) 0 0; padding:10px var(--sp-3);
  border:1px solid var(--border); border-radius:var(--r-md); background:var(--paper2); font-size:var(--fs-sm)}
.live-k{font:600 11px/1 var(--mono); letter-spacing:.06em; text-transform:uppercase; color:var(--accent-ink)}

/* ---------- training metrics: the TensorBoard view ---------- */
.mx{position:fixed; inset:0; z-index:80; background:rgba(12,18,38,.45); display:flex; align-items:stretch;
  justify-content:center; padding:var(--sp-6); backdrop-filter:blur(4px)}
.mx[hidden]{display:none}
.mx-panel{width:min(1240px, 100%); background:var(--paper); border-radius:var(--r-xl); overflow-y:auto;
  box-shadow:0 30px 80px -30px rgba(0,0,0,.5); display:flex; flex-direction:column; border:1px solid var(--border);
  animation:pop var(--dur) var(--ease)}
.mx-head{display:flex; align-items:center; gap:var(--sp-3); padding:var(--sp-3) 18px; border-bottom:1px solid var(--border);
  position:sticky; top:0; background:var(--card); z-index:2}
.mx-title{margin:0; font:600 var(--fs-lg)/1.25 var(--display); letter-spacing:-.015em}
.mx-title:focus{outline:none}
.mx-status{font:500 11px/1 var(--mono); color:var(--ink-muted); text-transform:uppercase; letter-spacing:.05em}
.mx-close{margin-left:auto; width:32px; height:32px; border-radius:var(--r-md); border:1px solid var(--border);
  background:var(--card); cursor:pointer; font-size:18px; line-height:1; color:var(--ink2);
  transition:background var(--dur-fast) var(--ease)}
.mx-close:hover{background:var(--paper); color:var(--ink)}
.mx-tools{display:flex; gap:10px var(--sp-4); flex-wrap:wrap; align-items:center; padding:var(--sp-3) 18px 0}
.mx-smooth{display:inline-flex; gap:var(--sp-2); align-items:center; font-size:var(--fs-sm); color:var(--ink2)}
.mx-smooth input{width:140px; accent-color:var(--accent)}
.mx-smooth output{font-family:var(--mono); font-size:var(--fs-xs); min-width:3ch}
.mx-runs{display:inline-flex; gap:6px; flex-wrap:wrap}
.mx-run{display:inline-flex; gap:6px; align-items:center; font-size:12.5px; padding:5px 10px; border-radius:var(--r-pill);
  border:1px solid var(--border); background:var(--card); color:var(--ink); cursor:pointer; box-shadow:var(--shadow-xs)}
.mx-run i{width:8px; height:8px; border-radius:50%}
.mx-run[aria-pressed="false"]{opacity:.5; text-decoration:line-through}
.mx-compare{display:inline-flex; gap:6px; align-items:center; flex-wrap:wrap; margin-left:auto}
.mx-compare input{font:400 var(--fs-sm)/1.2 var(--mono); padding:7px 9px; border:1px solid var(--line); border-radius:var(--r-md);
  background:var(--card); color:var(--ink); width:16ch}
.mx-compare input:focus{outline:2px solid transparent; border-color:var(--accent); box-shadow:var(--focus-ring)}
.mx-compare-out{font-size:var(--fs-xs); color:var(--ink-muted)}
.mx-keys{font-size:var(--fs-xs); color:var(--ink-muted); margin:var(--sp-2) 18px 0}
.mx-grid{display:grid; grid-template-columns:repeat(auto-fit, minmax(min(100%, 520px), 1fr)); gap:14px; padding:14px 18px}
.mx-chart{border:1px solid var(--border); border-radius:var(--r-lg); background:var(--card); padding:10px var(--sp-3) 6px; min-width:0;
  box-shadow:var(--shadow-xs)}
.mx-chart header{display:flex; gap:var(--sp-2); align-items:center; flex-wrap:wrap; margin-bottom:var(--sp-1)}
.mx-chart h3{margin:0; font-size:var(--fs-sm); font-weight:var(--fw-semibold)}
.mx-tag{color:var(--ink-muted); font-size:11px}
.mx-log{margin-left:auto; font:500 11px/1 var(--mono); padding:5px 8px; border-radius:var(--r-sm); border:1px solid var(--border);
  background:transparent; color:var(--ink2); cursor:pointer}
.mx-log[aria-pressed="true"]{background:var(--accent); color:#fff; border-color:var(--accent)}
.mx-plot{position:relative; overflow:hidden; touch-action:none; cursor:crosshair; border-radius:var(--r-sm)}
.mx-plot:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
.mx-svg{display:block; max-width:100%; height:auto}
.mx-bg{fill:var(--card)}
.mx-gl{stroke:var(--line2); stroke-width:1}
.mx-yl, .mx-xl{fill:var(--ink3); font:11px var(--mono)}
.mx-none{fill:var(--ink3); font:12px var(--font-sans)}
.mx-line{fill:none; stroke-width:1.8; stroke-linejoin:round}
.mx-raw{fill:none; stroke-width:1; opacity:.28}
.mx-cur{stroke:var(--ink3); stroke-width:1; stroke-dasharray:3 3}
.mx-tip{position:absolute; top:8px; right:8px; max-width:calc(100% - 70px); background:rgba(255,255,255,.96);
  border:1px solid var(--border); border-radius:var(--r-md); padding:6px 9px; font-size:var(--fs-xs); box-shadow:var(--shadow-md);
  pointer-events:none; backdrop-filter:blur(6px)}
.mx-tip[hidden]{display:none}
.mx-tip i{display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:5px}
.mx-tip .lin{font-size:10px; padding:1px 5px}
.mx-foot{display:flex; gap:var(--sp-3); align-items:center; flex-wrap:wrap; padding:var(--sp-1) 18px 18px}
@media (max-width: 900px){
  .mx{padding:0}
  .mx-panel{border-radius:0; border:0}
  .mx-compare{margin-left:0}
  .mx-head, .mx-tools, .mx-grid, .mx-foot{padding-left:16px; padding-right:16px}
  .mx-keys{margin-left:16px; margin-right:16px}
}

/* ---------- phones: the topbar fits 390px (after the menu rules it overrides) ---------- */
@media (max-width: 900px){
  .topbar{gap:6px}
  .navmore > summary{padding:7px 10px}
  .view-build{padding:7px 10px; white-space:nowrap}
  .account{min-width:0}
  button.who{max-width:9.5ch}
  #who-name{overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0}
  .navmore-menu{right:-60px}
}

/* ---------- phones: every control a thumb can hit, nothing under the home indicator ----------
   Measured at 375 and 320 px (client access, 2026-10-17): the topbar's View build was 29 px tall, the account
   chip 33, every `.btn.sm` 33. 44 px is the smallest target Apple's guidelines allow. */
@media (max-width: 900px){
  .btn, .btn.sm, .view-build, button.who, .navmore > summary, .zoomers button, .npanel-close, .mx-close,
  .mx-run, .mx-log, .chosen button, .people-box select, .people-box input{min-height:44px}
  a.btn, .btn{display:inline-flex; align-items:center; justify-content:center; text-align:center}
  .zoomers button, .npanel-close, .mx-close{min-width:44px}
  .composer{padding-bottom:max(12px, env(safe-area-inset-bottom))}
  .share-url{max-width:100%; width:100%}
  .people-box form{display:flex; flex-wrap:wrap; gap:6px}
  .people-box input[type=email]{flex:1 1 12em; min-width:0}
  .people-list{padding-left:0; list-style:none}
  .people-list li{display:flex; flex-wrap:wrap; gap:6px; align-items:center; margin:6px 0}
  .people-who{overflow-wrap:anywhere; min-width:0}
  .brand{min-height:44px}
}
.people-level{font-size:var(--fs-xs); padding:2px 8px; border-radius:var(--r-pill); border:1px solid var(--border); color:var(--ink-muted)}
.people-level[data-level="client"]{border-color:var(--accent-line); color:var(--accent-ink); background:var(--accent-soft)}
.people-state{font-size:var(--fs-xs); overflow-wrap:anywhere}
@media (max-width: 900px){
  .navmore-menu a{min-height:44px; display:flex; align-items:center}
  .navmore > summary{display:flex; align-items:center}
}
/* A 320 px phone: the team's topbar (View build, Workspace, the account) on one line inside the gutter */
@media (max-width: 360px){
  .topbar{gap:4px; padding-left:12px; padding-right:12px}
  .navmore > summary, .view-build{padding:7px 8px; white-space:nowrap}
  .navmore > summary::after{margin-left:6px}
  button.who{padding-left:8px; padding-right:8px; gap:5px}
}
/* A 320 px phone: a label above its value (beside it, "not computable" broke as "computabl / e"), and a table's
   long first column wraps so the figures beside it stay on screen. */
@media (max-width: 420px){
  .kv, .npanel-body .kv{grid-template-columns:1fr; gap:0 12px}
  .kv dd{margin:0 0 8px}
  .tblwrap td:first-child, .tblwrap th:first-child{white-space:normal; overflow-wrap:break-word; min-width:10ch}
  .tblwrap th, .tblwrap td{padding:7px 6px}
}

/* Client access (2026-10-17): a guest sees the Build the team gave them, never a control the server would
   refuse them. The server refuses each of these anyway; this keeps them off the screen. */
[data-guest] #navmore, [data-guest] #add-data, [data-guest] .suggest, [data-guest][data-no-thread] #composer,
[data-guest][data-guest-home] #composer,
[data-guest] [data-cancel-build], [data-guest] .share-build, [data-guest] .share-people,
[data-guest] #act-approve, [data-guest] #act-adjust, [data-guest] #act-probe-seed, [data-guest] #act-research,
[data-guest] #act-research-stop, [data-guest] #act-deploy, [data-guest] #act-keep, [data-guest] #act-keep-go,
[data-guest] #act-brief, [data-guest] #act-curve-run, [data-guest] #act-probe, [data-guest] #act-cap,
[data-guest] #act-chat, [data-guest] #act-chat-api, [data-guest] #act-route, [data-guest] #act-start-over,
[data-guest] #act-show-plan, [data-guest] a[href*="/artifact"],
[data-guest] .field:has(#in-photo, #in-row, #in-route, #cap-file, #chat-q, #in-probe, #in-instruction),
[data-guest] #out-route, [data-guest] #cap-out, [data-guest] #chat-a { display: none !important; }
.guest-builds { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 8px; }
.guest-builds li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; min-width: 0; }
.guest-builds .btn { max-width: 100%; overflow-wrap: anywhere; white-space: normal; text-align: left; }
/* The team's Reply under a client's message (client access): full width, a thumb's target. */
.reply-form{display:flex; flex-wrap:wrap; gap:6px; margin-top:8px}
.reply-form textarea{flex:1 1 14em; min-width:0; min-height:44px; font:inherit; padding:8px 10px; border:1px solid var(--line);
  border-radius:var(--r-md); background:var(--card); color:var(--ink)}
.reply-form textarea:focus{outline:2px solid transparent; border-color:var(--accent); box-shadow:var(--focus-ring)}
.reply-form .btn{min-height:44px}
/* "Use in a plan" under a client's message, and the client's message attached to the composer as a read-only quote
   (never text in the box). Thumb-sized targets; long words wrap at phone width. */
.use-in-plan{min-height:44px; margin-top:8px}
[data-guest] .use-in-plan, [data-guest] .client-quote .btn{display:none !important}
.client-quote{margin:0 0 8px; padding:8px 10px; border-left:2px solid var(--line); border-radius:var(--r-sm); background:var(--card);
  color:var(--ink); min-width:0; overflow-wrap:anywhere}
.client-quote-head{margin:0 0 6px; font-size:var(--fs-xs); color:var(--ink-muted)}
.client-quote blockquote{margin:0; max-height:9em; overflow:auto; white-space:pre-wrap}
.client-quote .btn{min-height:44px; margin-top:6px}
@media (max-width: 480px){ .client-quote blockquote{max-height:5.5em} }
