:root{--fs:13px;--fs-meta:11px;--fs-input:16px;--fs-code:32px;--ctl:28px;--hit:44px;--s1:4px;--s2:8px;--s3:12px;--s4:16px;--kb:0px}
*{box-sizing:border-box}
[hidden]{display:none!important}
/* #114 app-like: no pinch/double-tap zoom, no text-size jump on rotate, no rubber band (inner scrollers contain).
   Text stays 13/11 px; iOS Larger Text applies through the system setting. */
html{touch-action:manipulation;-webkit-text-size-adjust:100%;text-size-adjust:100%}
html,body{overflow-x:hidden;overscroll-behavior:none}
body{margin:0;background:var(--bg);color:var(--fg);font:var(--fs)/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;overflow-wrap:anywhere;padding:0 var(--s3) calc(var(--hit) + var(--ctl) + env(safe-area-inset-bottom))}
/* #68: no text past the screen. Text boxes shrink and wrap anywhere (paths, shas, URLs too); one-line cells (.nw .el, .tl) ellipsise. */
p,li,h2,h3,summary,.kv,.m,.act,.why,.tl,.card *,.msg,.st,code{min-width:0;overflow-wrap:anywhere}
header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--s2);min-height:calc(var(--hit) + var(--s1));background:var(--bg);border-bottom:1px solid var(--line)}
header b{flex:1}
a{color:var(--link)}
.m{color:var(--mute)}.g{color:var(--g)}.a{color:var(--a)}.r{color:var(--r)}
h2{font-size:var(--fs);margin:var(--s4) 0 var(--s1);display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s4)}
h2>span:first-child{flex:1}
p{margin:var(--s2) 0}
.tag{border:1px solid currentColor;border-radius:4px;padding:0 var(--s1);font-size:var(--fs-meta)}
.msg{padding:var(--s2);border:1px solid currentColor;border-radius:6px}
/* #66: an action's toast, one line under the sticky header; the demo banner (.msg.a) stays in the flow. */
.msg.g,.msg.r{position:fixed;z-index:2;top:calc(var(--hit) + var(--s2));left:var(--s3);right:var(--s3);margin:0;padding:var(--s1) var(--s2);background:var(--bg);font-size:var(--fs-meta);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;transition:opacity .4s}
/* #397: an error stays until tapped, in full: it wraps and holds its place in the flow, under the header once scrolled. */
.msg.r{position:sticky;margin:var(--s2) var(--s3);white-space:normal;overflow:visible}
.msg.out{opacity:0}
details,.ev,.kv{border-bottom:1px solid var(--line)}
summary{display:grid;grid-template-columns:7ch minmax(0,1fr) auto;gap:var(--s2);align-items:center;min-height:var(--hit);cursor:pointer;list-style:none}
summary::-webkit-details-marker{display:none}
summary>span{min-width:0}
details>p{margin:0 0 var(--s2);padding-left:var(--s1)}
.lane{border-bottom:1px solid var(--line)}
/* #422: an asleep conductor (its pane closed) is dimmed; a tap still opens its thread. */
.lane[data-thread][data-gone]>.lr{opacity:.55}
/* #205: an open Queue card's lanes, newest first: one-line 44 px tap rows; `+N older` expands. */
.ql{display:block;max-width:100%;min-height:var(--hit);line-height:var(--hit);text-decoration:none;color:inherit}
/* #218: a lane line in the card: the name ellipsises first, `state age` stays at the right (the inline line overflowed the card). */
.qls .ql{display:flex;gap:1ch}.ql>:first-child{flex:none}.ql .qn{min-width:0;overflow:hidden;text-overflow:ellipsis}.ql .qa{flex:none;margin-left:auto}
.ch{margin:var(--s2) 0 0;font-size:var(--fs-meta);font-weight:700;letter-spacing:.08em;color:var(--mute)}
.qm{border:0}.qm>summary{display:block}
.lr{display:grid;grid-template-columns:48px minmax(0,1fr) max-content;gap:0 var(--s2);align-items:center;width:100%;text-align:left;background:none;border:0;border-radius:0;padding:var(--s1) 0}
.lr>span{min-width:0}
/* #53: grid name/state cells stay on one line; only free text (the reason) wraps, at most 2 lines. */
.nw{white-space:nowrap;overflow-wrap:normal}.el{overflow:hidden;text-overflow:ellipsis}
.lr .why{grid-column:2/-1;font-size:var(--fs-meta);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
h3{font-size:var(--fs);color:var(--mute);margin:var(--s3) 0 var(--s1)}
.lane .act{grid-column:1/-1;color:var(--mute);font-size:var(--fs-meta);min-height:1.5em}
.done summary{grid-template-columns:1fr}
form{display:inline-flex;flex-wrap:wrap;align-items:center;gap:var(--s4);margin:0}
form.role{display:flex;padding:var(--s2) 0;border-top:1px solid var(--line)}
.btns{display:flex;flex-wrap:wrap;gap:var(--s4)}
details.q>form+form{margin-left:var(--s4)}
/* #58 amendment B: one terminal-style control. The label in the accent colour inside CSS brackets, 28 px
   visible, no fill (inverted while pressed); the "]" pseudo spans an 8 px ring around it, the 44 px tap
   target. Controls sit 16 px apart so rings never overlap. A select hides behind its `[opus ▾]` label. */
button{font:inherit;color:var(--fg)}
button:not(.lr,.hh,.hqh),.pk{position:relative;display:inline-flex;align-items:center;justify-content:center;flex:none;height:var(--ctl);min-width:28px;max-width:100%;
  margin:0;padding:0 1ch;border:0;border-radius:0;background:none;color:var(--l);font:inherit;font-size:var(--fs);font-weight:400;line-height:1;white-space:nowrap;text-transform:lowercase}
button:not(.lr,.hh,.hqh)>span,.pk>span{min-width:0;overflow:hidden;text-overflow:ellipsis}
button:not(.lr,.hh,.hqh)::before,.pk::before{content:"[";position:absolute;left:0}
button:not(.lr,.hh,.hqh)::after,.pk::after{content:"]";position:absolute;inset:calc(-1 * var(--s2));display:flex;align-items:center;justify-content:flex-end;padding-right:var(--s2)}
button:not(.lr,.hh,.hqh):active,.pk:active{background:var(--l);color:var(--bg)}
button:disabled,.pk:has(:disabled){color:var(--mute);opacity:.6}
.pk::after{pointer-events:none}
.pk select{position:absolute;inset:calc(-1 * var(--s2));width:calc(100% + 16px);opacity:0;font-size:var(--fs-input)}
.pick{flex:0 1 auto;min-width:0;text-transform:none}.pick span{overflow:hidden;text-overflow:ellipsis}
input,textarea{font-size:var(--fs-input)}
.ev,.kv{padding:var(--s2) 0}
nav{position:fixed;left:0;right:0;bottom:0;display:flex;background:var(--bg);border-top:1px solid var(--line);padding-bottom:env(safe-area-inset-bottom)}
/* #141: bracket tabs; the active one a pressed key (accent fill, dark text, a 2 px accent bar over its cell); `·N` in
   red is the needs-you count (dark on the fill). The whole cell (52 px) is the tap target. */
nav a{flex:1;display:flex;align-items:center;justify-content:center;min-height:calc(var(--hit) + var(--s2));line-height:1;color:var(--mute);text-decoration:none}
nav a>span{display:inline-flex;align-items:center;height:var(--ctl);padding:0 .5ch;white-space:nowrap}
nav a>span::before{content:"["}nav a>span::after{content:"]"}
nav a .n{color:var(--r);font-weight:700}
nav a.on{box-shadow:inset 0 2px var(--l)}
nav a.on>span{background:var(--l);color:var(--bg)}
nav a.on .n{color:inherit}
.tl,.cst{grid-column:1/-1;margin-top:calc(-1 * var(--s1));color:var(--mute);font-size:var(--fs-meta);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#dot{width:8px;height:var(--s2);border-radius:50%;background:currentColor;font-style:normal;flex:none}
#dot.p{animation:p .6s}
@keyframes p{50%{transform:scale(1.9)}}
/* #290: the four header controls are one width, so each bracket sits as far from its glyph */header>button:not(.pairb){width:calc(var(--ctl) + var(--s1));padding:0}header>button:not(.pairb)+button{margin-left:var(--s2)} /* 16 px apart: no tap ring over its neighbour */#herd-on svg{width:19px;height:14px}
#rf i,#ptr{font-style:normal}#rf.spin i,#ptr.spin{display:inline-block;animation:s 1s linear infinite}
/* #450: one thin strip under the header on every tab: a wait over 300 ms is the chat's inline mark (.tld: the theme's
   sprite, ascii frames or a spinning glyph) + `loading`; data over 2 min old adds `as of 3m ago`, small and dim, on the
   same row. Nothing to say: no height. The page under it stays visible and tappable. */
#strip{position:sticky;top:calc(var(--hit) + var(--s1));z-index:1;display:flex;align-items:center;gap:var(--s2);padding:0 var(--s2);background:var(--bg);color:var(--mute);font-size:var(--fs-meta)}
#strip:has(#ld:not([hidden]),#stale:not([hidden])){padding-block:var(--s1)}#ld[hidden],#ld[hidden]+.ldw{display:none}
#stale{margin-left:auto;white-space:nowrap}
/* #450 first load: a tab with nothing yet is two empty outlines of its cards (no text) until its data paints. */
main>section:empty::before,main>section:empty::after{content:"";display:block;height:calc(var(--s4) * 5);margin:var(--s3) var(--s2);border:1px solid var(--line);border-radius:6px}
html.bg *{animation-play-state:paused!important} /* #337: no motion while the app is in the background */
@keyframes ldg{0%{--gait:-16deg}50%{--gait:16deg}100%{--gait:-16deg}}
@keyframes ldk{0%,49.9%{--o1:1;--o2:0}50%,100%{--o1:0;--o2:1}}
button[aria-busy=true]::after{content:" ↻";display:inline-block;animation:s 1s linear infinite}
@keyframes s{to{transform:rotate(1turn)}}
#ptr{position:fixed;top:calc(var(--hit) + var(--s3));left:calc(50% - var(--s2));z-index:1}
main{transition:transform .2s}
/* #206: the tab is picked before the first paint (serve.rs's head script sets html[data-tab]; tab() keeps it): only its
   section shows, and [?] only on Queue. */
html:not([data-tab=queue]) :is(#queue,header .qhelp),html:not([data-tab=lanes]) #lanes,html:not([data-tab=chat]) #chat{display:none}
.fl{animation:fl .6s}
@keyframes fl{from{background:color-mix(in srgb,var(--l) 25%,transparent)}}
.ask pre{white-space:pre-wrap;font-size:var(--fs-meta);margin:var(--s1) 0}
/* #127: a permission prompt's reason (2 lines) and command (3 lines, tap to expand). */
.ask .reason{margin:var(--s1) 0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.ask .command{white-space:pre-wrap;font-size:var(--fs-meta);margin:var(--s1) 0;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;cursor:pointer}.ask .command.open{display:block}
.ask .title,.ask .cd{margin:0;font-size:var(--fs-meta)}.ask .cd{color:var(--r)}.ask :is(.title,.reason,.command):empty{display:none}
@media (prefers-reduced-motion:reduce){#dot.p,#rf.spin i,#ptr.spin,.fl,button[aria-busy=true]::after{animation:none}}
.av{display:flex;align-items:center;justify-content:center;width:48px;height:40px;overflow:hidden}
.av>*{display:none}
/* Scene mode shows the glyph until herd.js's symbols land (`.hz`): no fetch or JS, no blank avatar. */
[data-mode=glyph] .av .gl,[data-mode=scene]:not(.hz) .av .gl,[data-mode=scene].hz .av .px{display:block}
[data-mode=ascii] .av .asc{display:grid}
/* #241 terminal (docs/themes.md): today's glyph board from the first paint, before herd.js loads it: glyph avatars. */
[data-theme=terminal] .av>*{display:none!important}[data-theme=terminal] .av .gl{display:block!important}
/* #241: a row's 16 px action sprite in its glyph's place, a Host group's load scene, a moment (silent; reduced motion: still). */
.rsp,.lsc{display:inline-block;flex:none;width:var(--s4);height:var(--s4);vertical-align:middle}
/* #281: the row sprite is 24 px (the 16 px art at 1.5×, never smoothed) in a fixed 28 px slot; its -4 px block margin keeps
   the line box (and the row) its height. */
.rsp{width:calc(var(--s4) + var(--s2));height:calc(var(--s4) + var(--s2));margin:calc(-1 * var(--s1)) calc(var(--s1) / 2);image-rendering:crisp-edges;image-rendering:pixelated;shape-rendering:crispEdges}
/* #335 ascii style: a row's 3-character figure in the sprite's box (so the slot stays 28 px), a Host group's load as text,
   the loading mark's frames (two: .run swaps them, no node replaced; reduced motion: the first). */
.rsa{display:inline-flex;align-items:center;justify-content:center;font-size:var(--fs-meta);line-height:1;font-style:normal;white-space:pre}
.lsa{width:auto;font-size:var(--fs-meta);line-height:var(--s4);font-style:normal;white-space:pre;color:var(--mute)}
:is(details.q,.qc):has(>summary .gt>.rsg){--gw:calc(2 * var(--d, 0) * 1ch + var(--s4) + var(--s3))}
details.er:has(>summary>.rsg)>summary{grid-template-columns:calc(var(--s4) + var(--s3)) var(--s2) 6ch minmax(0,1fr) auto}
details.er:has(>summary>.rsg)>.ex{padding-left:calc(var(--s4) + var(--s3) + 3 * var(--s2))}
#mo{position:fixed;z-index:3;top:calc(var(--hit) + var(--s2));right:var(--s3);width:calc(3 * var(--s4));height:calc(2 * var(--s4) + var(--s1));pointer-events:none;animation:.8s ease-in-out 3 hop}
#mo svg{width:100%;height:100%}#mo.mo-shake{animation-name:shake}#mo.mo-pulse{animation-name:pulse}
@keyframes hop{50%{translate:0 calc(-1 * var(--s2))}}@keyframes shake{25%{translate:calc(-1 * var(--s1)) 0}75%{translate:var(--s1) 0}}@keyframes pulse{50%{scale:1.2}}
@media (prefers-reduced-motion:reduce){#mo{animation:none}}
/* #370: a label's theme word keeps the label's colour and size, its plain word is the muted part in --fs-meta; each tab's
   own first line; an Events kind's word in the row's tone; an empty tab's theme line over the plain one */
.pw{color:var(--mute);font-size:var(--fs-meta);font-weight:400;white-space:nowrap}h2 .pw,.tsub .pw{text-transform:none;letter-spacing:0}
.tsub{margin:var(--s2) 0 0;padding:0 var(--s1);font-weight:600}
.thw.ev{font-weight:600}details.er:has(.t-g) .thw.ev{color:var(--g)}details.er:has(.t-r) .thw.ev{color:var(--r)}details.er:has(.t-l) .thw.ev{color:var(--l)}
p.m.empty{display:grid;gap:var(--s1);padding:var(--s3) 0;color:var(--fg)}p.m.empty .pw{white-space:normal}
/* the Host card's load: its 48 × 16 mini at 1.5×, two frames, and the level word */
.lsm{display:inline-flex;align-items:center;gap:var(--s1);margin-left:auto;padding-left:var(--s2);font-size:var(--fs-meta)}
.lsm svg{width:calc(var(--s4) * 3);height:var(--s4);image-rendering:pixelated;shape-rendering:crispEdges;animation:kfr 1.2s infinite}
.hhd .hnm:has(.lsm){display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--s1)}
/* every row sprite loops its .kf1/.kf2 frames (herd.css's kfr, 0.6 s a frame): a hidden tab is display:none and html.bg
   pauses the rest; the <use> inherits --o1/--o2, so no node is replaced. A moment on its row, 2.4 s, once: merged hops, a
   FAIL shakes the row, a new ask pulses; a rebuilt row resumes it by --mo-d (a negative delay) */
.rsp{animation:kfr 1.2s infinite}
[data-mo] .rsp{animation:kfr 1.2s infinite,mo-hop .8s ease-in-out 3 var(--mo-d,0ms)}
[data-mo=fail]{animation:mo-shake .4s ease-in-out 6 var(--mo-d,0ms)}[data-mo=fail] .rsp{animation:kfr 1.2s infinite}
[data-mo=needs-you]{animation:mo-tint 2.4s ease-out 1 var(--mo-d,0ms)}[data-mo=needs-you] .rsp{animation:kfr 1.2s infinite,mo-pulse .8s ease-in-out 3 var(--mo-d,0ms)}
[data-mo]{position:relative}[data-mo]:is(summary)>:is(.ag,span.m:nth-of-type(3)){visibility:hidden}
.mot{position:absolute;right:0;top:calc((var(--hit) - var(--s4)) / 2);font-style:normal;font-weight:700;font-size:var(--fs-meta);padding:0 var(--s1);border-radius:var(--s1);color:var(--bg);background:var(--g);white-space:nowrap;animation:mo-tag 2.4s ease-out 1 both var(--mo-d,0ms)}
[data-mo=fail] .mot,[data-mo=needs-you] .mot{background:var(--r)}
@keyframes mo-hop{50%{translate:0 calc(-1 * var(--s1))}}@keyframes mo-shake{25%{translate:calc(-1 * var(--s1) / 2) 0}75%{translate:calc(var(--s1) / 2) 0}}
@keyframes mo-pulse{50%{scale:1.25}}@keyframes mo-tint{from{background:color-mix(in srgb,var(--r) 18%,transparent)}}@keyframes mo-tag{0%{opacity:0}8%,85%{opacity:1}100%{opacity:0}}
@media (prefers-reduced-motion:reduce){.rsp,.lsm svg,[data-mo],[data-mo] .rsp,.mot{animation:none!important}}
.gl{font-style:normal;font-size:20px}
.px{width:48px;height:36px}
.av .asc{font:10px/1 ui-monospace,Menlo,monospace;white-space:pre;font-style:normal}
.asc b{grid-area:1/1;font-weight:400}
.run b:last-child{animation:f .5s steps(1) infinite}
.run b:first-child{animation:f .5s steps(1) -.25s infinite}
@keyframes f{0%{visibility:hidden}50%{visibility:visible}}
/* Corral's gait: herd.js's symbols swing diagonal leg pairs in opposition by the inherited --gait. */
@property --gait{syntax:'<angle>';inherits:true;initial-value:0deg}
.av.working .px{animation:gt .4s ease-in-out infinite alternate}
@keyframes gt{from{--gait:-16deg}to{--gait:16deg}}
.av.done .px{opacity:.5}
.av.r .px{filter:sepia(1) saturate(6) hue-rotate(-50deg)}
@media (prefers-reduced-motion:reduce){.run b,.av .px{animation:none!important}.run b:last-child{visibility:hidden}}
/* #200: closed is invisible and untouchable, never display:none; layers only while shown (or sliding off). */
#sheet{position:fixed;inset:0;z-index:3;visibility:hidden;pointer-events:none;overscroll-behavior:contain}
#sheet.on{visibility:visible;pointer-events:auto}
#sheet.on>.sh{will-change:transform}#sheet.on>.bd{will-change:opacity}
.bd{position:absolute;inset:0;background:var(--scrim);touch-action:none;overscroll-behavior:contain;transition:opacity .28s cubic-bezier(.2,.8,.2,1)}
/* #70: a full-height box placed by translateY (serve.js: half 50 %, mid 78 %, full); it follows the finger
   (.drag), snaps (.28 s) and slides off to close (.shut, #166: .2 s ease-out; #200: not .out, the chat blocks' grey box); the backdrop fades with it. */
.sh{position:absolute;left:0;right:0;top:env(safe-area-inset-top);bottom:0;display:flex;flex-direction:column;background:var(--bg);border-top:1px solid var(--edge);border-radius:14px 14px 0 0;padding:0 var(--s3) env(safe-area-inset-bottom);transform:translateY(100%);transition:transform .28s cubic-bezier(.2,.8,.2,1)}
.sh.full{border-radius:0}
#sheet.drag>*{transition:none}
#sheet.shut>*{transition-duration:.2s;transition-timing-function:ease-out}
@media (prefers-reduced-motion:reduce){#sheet>*{transition:none!important}}
/* The handle: the pill plus the title row, at least 56 px; it alone drags (the chat hands off at its top). */
.hd{flex:none;min-height:calc(var(--hit) + var(--s3));padding-bottom:var(--s2);touch-action:none;cursor:grab;user-select:none;-webkit-user-select:none}
.hd::before{content:"";display:block;width:40px;height:var(--s1);margin:var(--s2) auto;border-radius:3px;background:var(--edge)}
.hd p{margin:0}
/* #63 q8: the card takes at most 40 % of the sheet and scrolls inside; it never drags. */
.top{flex:none;max-height:40%;overflow:hidden auto;overscroll-behavior:contain;touch-action:pan-y;border-bottom:1px solid var(--line);padding-bottom:var(--s2)}
.top p{margin:var(--s1) 0}
.chat{flex:1;overflow:hidden auto;overscroll-behavior:contain;touch-action:pan-y;display:flex;flex-direction:column;gap:var(--s2);padding:var(--s2) 0}
.reply,.pairf{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s4);padding:var(--s2) 0;flex:none}
.reply textarea{flex:1;min-width:0;font:inherit;color:var(--fg);background:var(--card);border:1px solid var(--edge);border-radius:6px;padding:var(--s2);min-height:var(--hit);resize:none;font-size:var(--fs-input)}
/* #59: the pairing panel in the flow under the header (or the sheet's Pair button): the code large, how to approve it under it. */
.pairp{flex:none;margin:var(--s2) 0;padding:var(--s3);border:1px solid var(--a);border-radius:8px;cursor:pointer;scroll-margin-top:calc(var(--hit) + var(--s3))}
.pairp.g{border-color:var(--g);color:var(--g)}.pairp.r{border-color:var(--r)}.pairp p{margin:0}
.pairp .code{font-size:var(--fs-code);letter-spacing:.2em;text-align:center}
.st{flex:none;margin:0;font-size:var(--fs-meta);min-height:1.5em}
/* #363 report mode: the tapped element outlined; the note box fixed at the bottom. */
.rep .repo{outline:2px solid var(--r);outline-offset:-2px}
.repf{position:fixed;z-index:4;left:0;right:0;bottom:0;display:flex;align-items:center;gap:var(--s4);padding:var(--s2) var(--s3) calc(var(--s2) + env(safe-area-inset-bottom));background:var(--bg);border-top:1px solid var(--r)}
.repf input{flex:1;min-width:0;font:inherit;color:var(--fg);background:var(--card);border:1px solid var(--edge);border-radius:6px;padding:var(--s2);min-height:var(--hit);font-size:var(--fs-input)}
.ask{border:1px solid var(--r);background:color-mix(in srgb,var(--r) 15%,transparent);border-radius:8px;padding:var(--s2);margin:var(--s2) 0}
.ask b{color:var(--r)}.ask form{display:flex;flex-wrap:wrap;gap:var(--s4)}.ask input[name=text]{flex:1;min-width:8em;font:inherit;font-size:var(--fs-input)}
.ask form button[name]{order:-1}
.pend{border:1px solid var(--line);border-radius:8px;padding:var(--s2);margin:var(--s2) 0}.pend p{margin:0} /* #217: a tapped needs-you card */
.ask>button{display:flex;width:fit-content;margin:var(--s4) 0}
/* #63 amendment A, the one exception to the 28 px rule: a choice is a sentence, not a label. Full width, wrapping,
   at most 4 lines (then an ellipsis; the full text is its title), the brackets on the first line, stacked 8 px apart.
   #139: every choice, wherever the answer form renders (.ask, the queue row card, the Herd card). */
form:has([name=choice]){display:flex;row-gap:var(--s2)}button.pick+button.pick{margin-top:var(--s2)}
button[name=choice],button.pick{display:flex;width:100%;height:auto;min-height:var(--ctl);margin:0;padding:calc((var(--ctl) - 1.35em) / 2) 1ch;
  justify-content:flex-start;align-items:flex-start;text-align:left;white-space:normal;overflow-wrap:anywhere;line-height:1.35}
button[name=choice]::after,button.pick::after{inset:calc(-1 * var(--s1)) calc(-1 * var(--s2));align-items:flex-start;padding-top:calc(var(--s1) + (var(--ctl) - 1.35em) / 2)}
button[name=choice]>span,button.pick>span{display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.ask small,button[name=choice] small{font-size:var(--fs-meta)}
/* #43: sheet actions, kill/clean confirm, `/` menu, per-turn transcript, tool calls collapsed. */
.acts,.cf{flex:none;display:flex;flex-wrap:wrap;align-items:center;gap:var(--s4);padding:var(--s2) 0}
.acts [data-op=kill],.cf .yes{color:var(--r)}
.cf{border:1px solid var(--r);border-radius:8px;padding:var(--s2)}.cf p{flex-basis:100%;margin:0;font-size:var(--fs-meta)}
.cmds{flex:none;list-style:none;margin:0;padding:0;border:1px solid var(--edge);border-radius:6px}
.cmds li{padding:var(--s3);min-height:var(--hit);border-bottom:1px solid var(--line);cursor:pointer}
.chat>.now{display:flex;flex-direction:column;gap:var(--s2)}
/* #138 (docs/design/chat-blocks): a block per role run, a rounded surface with a 2 px left edge in the role colour --k
   (you blue, assistant purple, tool run amber); status is a quiet line recessed toward the base colour. */
.blk{--k:var(--mute);margin:0;border:0;border-left:2px solid var(--k);border-radius:6px;background:var(--card);padding:0 var(--s2) var(--s2)}
.blk.me{--k:var(--l)}.blk.ai{--k:var(--p)}.blk.run{--k:var(--a)}
/* The header is the whole width: 28 px visible plus an 8 px ring above and below, a 44 px tap (#58); a collapsed block keeps its 8 px
   bottom padding, so with the 8 px gap two headers' rings tile instead of overlapping (#147). The role in its
   colour; collapsed, a one-line preview; the chevron right. A tool run's header is its call: `$ cmd` or `Tool path`. */
.blk>summary{position:relative;display:flex;align-items:center;gap:var(--s2);min-height:var(--ctl);font-size:var(--fs-meta);color:var(--mute);white-space:nowrap}
.blk>summary::after{content:"";position:absolute;inset:calc(-1 * var(--s2)) 0}
.blk>summary .k{flex:none;color:var(--k)}
.blk>summary :is(.pv,.cmd){flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
.blk[open]>summary .pv{visibility:hidden}
.blk>summary .cv{flex:none;margin-left:auto;font-style:normal}
.blk>summary .cv::before{content:"▸"}.blk[open]>summary .cv::before{content:"▾"}
.blk.run>summary .cmd{color:var(--fg)}
.blk.run[open]>summary{align-items:flex-start;white-space:normal;padding-top:calc((var(--ctl) - 1.5em) / 2)}
.blk.run[open]>summary .cmd{white-space:pre-wrap;overflow:visible}
/* Prose (you, assistant): 13 px, minimal markdown as escaped text plus spans: bold, inline code, lists, headings. */
.md{font-size:var(--fs)}
.md>*{margin:0 0 var(--s2)}.md>:last-child{margin-bottom:0}
.md .h{font-weight:700;color:var(--fg)}
.md :is(ul,ol){padding-left:3ch}
.md li+li{margin-top:var(--s1)}
/* A code chip is neutral (not link blue) and stays whole up to the line width, then wraps anywhere. */
.md code{display:inline-block;max-width:100%;vertical-align:bottom;color:var(--fg);background:color-mix(in srgb,var(--mute) 18%,transparent);border-radius:3px;padding:0 .3ch;font:inherit;overflow-wrap:anywhere}
/* Tool output: a tinted panel, 11 px, lines wrap inside it (never sideways) under their own start (--i: the gutter
   plus the line's indent, in ch); capped at 20 lines plus [show all] (on a failure the head and tail, `⋯ N lines` between). */
.out{margin-top:var(--s1);border-radius:4px;background:color-mix(in srgb,var(--a) 6%,var(--bg));font-size:var(--fs-meta)}
.out pre{margin:0;padding:var(--s1) var(--s2);white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.5}
.out .ol{display:block;padding-left:calc(var(--i) * 1ch);text-indent:calc(var(--i) * -1ch)}
.out.cap:not(.all) .rest,.out.all .cut{display:none}
.more2{display:flex;align-items:center;gap:var(--s4);margin:var(--s2) 0 0;font-size:var(--fs-meta)}
/* ANSI SGR mapped to the nearest board token (no terminal hex): fg, bold, dim, and two background tints. */
.t-r{color:var(--r)}.t-g{color:var(--g)}.t-a{color:var(--a)}.t-l{color:var(--l)}.t-p{color:var(--p)}.t-c{color:var(--c)}.t-m{color:var(--mute)}.t-b{font-weight:700}
.bg-r{background:color-mix(in srgb,var(--r) 15%,transparent)}.bg-g{background:color-mix(in srgb,var(--g) 15%,transparent)}
.bg-r2{background:color-mix(in srgb,var(--r) 35%,transparent)}.bg-g2{background:color-mix(in srgb,var(--g) 35%,transparent)}
/* Status (`Ran 2 shell commands`, `✻ Cogitated for 37s`): one quiet 11 px line, no header; dashed: a gap in the transcript. */
.qs{margin:0;padding:var(--s1) var(--s2);border-left:2px solid color-mix(in srgb,var(--mute) 40%,var(--bg));border-radius:6px;background:color-mix(in srgb,var(--card) 40%,var(--bg));color:var(--mute);font-size:var(--fs-meta)}
.qs.gap{border-left-style:dashed;text-align:center}
/* #105's live status line: the spinner, under the chat and above the composer, one line. */
.live{flex:none;margin:0;padding-top:var(--s1);color:var(--mute);font-size:var(--fs-meta);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.live b{font-weight:400;color:var(--a)}
.more{align-self:center}
.fvr{position:relative;z-index:1;flex:none;display:flex;justify-content:flex-end;margin:0;padding-top:var(--s1)}
.fv[aria-pressed=true]{color:var(--l);box-shadow:inset 0 -2px var(--l)}
.qs.note{border-left-color:var(--a)}
.act.now{display:flex}.act.now>*{flex:none;min-width:0}.act.now>.el{flex-shrink:1}.act.now>.el~.el{flex-shrink:999}.act.now>i{font-style:normal;white-space:pre}
.qnow{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.qnow{font-size:var(--fs-meta);padding-left:2ch}
.unp{margin:auto;padding:var(--s3);text-align:center;border:1px solid var(--a);border-radius:8px;color:var(--a)}
#dot.demo{color:var(--l)}
[inert]{opacity:.6}
/* #115: the Queue tab as a git-log style graph (serve.js `graph()`). A row's gutter is its node line in box-drawing text
   (│ ├─ └─, then the state dot); each solid glyph also draws its stroke as a 1 px line down the whole row (an open card too),
   so the graph has no gaps at line height 1.5. A clamped row (depth > 3) keeps its dashed ┆─ glyph alone. --d is the drawn
   depth (0-3), the gutter 2·d+1 columns (≤ 6 + the dot); --y is the node line's middle. The row separator starts at the
   #n column, so it never crosses the graph. The card is a box beside the gutter; a hanging row's title wraps. */
:is(details.q,.qc){position:relative;border-bottom:0;--gw:calc((2 * var(--d, 0) + 1) * 1ch);--y:calc(var(--s1) + var(--fs) * .75);
  background:linear-gradient(var(--line),var(--line)) no-repeat calc(var(--gw) + var(--s2)) 100%/100% 1px}
.d0{--d:0}.d1{--d:1}.d2{--d:2}
:is(details.q,.qc)>summary{grid-template-columns:var(--gw) 6ch minmax(0,1fr) auto;align-content:start;padding:var(--s1) 0}
/* #367: titles start in one column at every depth: past the depth-2 gutter (--gm), so no graph line crosses one. */
:is(details.q,.qc){--gm:5ch}:is(details.q,.qc):has(>summary .gt>.rsg){--gm:calc(4ch + var(--s4) + var(--s3))}
:is(details.q,.qc) :is(.tl,.cst){grid-column:1/-1;padding-left:calc(var(--gm) + var(--s2))}
:is(details.q,.qc)>summary>span:first-of-type{grid-column:2} /* #206: the #n column before graph() adds the gutter, too */
details.q[open]{padding-bottom:var(--s2)}
/* #423: beside an issue's plant (a theme with `stages`), a long theme + plain state pair (`inspect · review(1)`)
   ellipsises, never wraps the row. */
:is(details.q,.qc)>summary:has(.rsp use[href^="#hq-"])>span>span:has(>.thw){display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cd{margin-left:calc(var(--gw) + var(--s2));padding:0 var(--s2);border:1px solid var(--edge);border-radius:6px;background:var(--card)}
.cd>p{margin:var(--s2) 0}
.gt,.gt i{font-style:normal;white-space:pre;color:var(--mute)}
.gt b{font-weight:400}
.gt .p::before,.gt .t::before,.gt .e::before,.gt .k::before{content:"";position:absolute;top:0;bottom:0;margin-left:.5ch;border-left:1px solid var(--mute);translate:-50%}
.gt .e::before{bottom:auto;height:var(--y)}
.gt .k::before{top:calc(var(--y) + var(--fs) * .4)}
/* #115 amendment A: the [?] legend (#162: in the header, Queue tab only); it opens in the lane sheet with the lane parts hidden. */
.sh.lg :is(.acts,.cf,.chat,.fvr,.live,.pairf,.cmds,.reply,.st){display:none}
.sh.lg .top{max-height:none;border:0}
/* #141: the Host tab's groups. A group's 44 px header: one status dot, the name, a one-line summary (hidden while open),
   the caret; a problem group's header takes its colour on a 12 % tint. serve.js ranks and opens them. */
.grp{border-bottom:1px solid var(--line)}
.grp>summary{display:flex;align-items:center;gap:var(--s2);min-height:var(--hit);padding:0 var(--s1);white-space:nowrap}
.grp>summary .dt{flex:none;width:var(--s2);height:var(--s2);border-radius:50%;background:currentColor;color:var(--g)}
.grp[data-t=m]>summary .dt{color:var(--mute)}
.grp>summary .gn{flex:none;font-weight:700;letter-spacing:.08em}
.grp>summary .gs{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;color:var(--mute);font-size:var(--fs-meta)}
.grp[open]>summary .gs{visibility:hidden}
.cv{flex:none;margin-left:auto;font-style:normal;color:var(--mute)}
.cv::before{content:"▸"}[open]>summary .cv::before{content:"▾"}
.grp[data-t=a]>summary{color:var(--a);background:color-mix(in srgb,var(--a) 12%,transparent)}
.grp[data-t=r]>summary{color:var(--r);background:color-mix(in srgb,var(--r) 12%,transparent)}
.grp:is([data-t=a],[data-t=r])>summary :is(.dt,.gs){color:inherit}
.grp[open]{padding-bottom:var(--s2)}
/* #183: every row is one grid, label | value | age: the label column is the longest label (`--kw`, set per group, at
   most 11ch), a value wraps inside its own column; a divider between rows, the first one as far under the header. */
.gr,.rw>summary{display:grid;grid-template-columns:var(--kw,9ch) minmax(0,1fr) auto;gap:0 1ch;align-items:baseline}
.gr{margin:0;padding:var(--s1) 0;border:0}
.grp>summary+*{margin-top:var(--s1)}.grp>:is(.gr,.rw,form)+:is(.gr,.rw,form){border-top:1px solid var(--line)}
.gr>.k,.rw>summary>.k{color:var(--mute);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gr>:is(.w,.x){grid-column:2/-1}
.grp .mt{font-size:var(--fs-meta);color:var(--mute)}
/* The gauge: ▕ + 12 cells + ▏ (disk: its floor tick ┃) in the mono font, ▶ past the limit; filled cells and edges take
   the status colour, empty ░ cells the muted one; a 15ch box at least, so wider fallback glyphs grow it, never spill. */
.bar{display:inline-block;min-width:15ch;white-space:pre;color:var(--g)}.bar.a{color:var(--a)}.bar.r{color:var(--r)}
.bar i{font-style:normal;color:var(--mute)}
/* A command chip never breaks inside; the whole chip wraps to the next line. */
.grp code{white-space:nowrap;color:var(--l);background:color-mix(in srgb,var(--l) 12%,transparent);border-radius:3px;padding:0 .3ch;font:inherit;overflow-wrap:normal}
/* A row that opens (a raw line, the accounts): the whole row is the 44 px tap target, the caret on it alone. The raw
   line shows under it, 11 px, wrapping, on the panel colour. */
.rw{border:0}
.rw>summary{align-content:center;padding:var(--s1) 0}
.rw>summary>.x{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.rw>summary>.t{align-self:start;line-height:calc(var(--fs) * 1.5);font-size:var(--fs-meta);color:var(--mute);white-space:nowrap}.rw>summary>.t .cv{margin-left:.5ch}
.rw>pre{margin:0 0 var(--s2) calc(var(--kw,9ch) + 1ch);padding:var(--s1) var(--s2);border-radius:4px;background:var(--card);color:var(--fg);font:inherit;font-size:var(--fs-meta);white-space:pre-wrap;overflow-wrap:anywhere}
.rw>.sub{margin:0 0 var(--s2) calc(var(--kw,9ch) + 1ch)}.rw>.sub>p{margin:0;padding:var(--s1) 0}
.grp form.role{border-top:0}
/* #234: HOSTS, one card per host in a grid, main first, then A→Z; side by side when there is room (#162's 56ch column).
   Every group's rows sit in the cards' columns (one inset), so FLEET DISK lines up with the cards. */
#host>.grp>:is(.gr,.rw,form){padding-left:var(--s2);padding-right:var(--s2)}
.hgd{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,56ch),1fr));gap:0 var(--s3);align-items:start}
.hcd{margin:var(--s2) 0 0;box-shadow:inset 0 0 0 1px var(--line);border-radius:6px;padding:0 var(--s2) var(--s1);min-width:0}
/* A card's head: status dot, name, `main`, the state and why in words, [off]/[on]; it wraps under the name at 390. */
.hhd{display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--s4);min-height:var(--hit);border-bottom:1px solid var(--line)}
.hhd>.hnm{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--s2);white-space:nowrap;overflow:hidden}
.hhd .dt{flex:none;width:var(--s2);height:var(--s2);border-radius:50%;background:currentColor}
.hhd .hw{min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:var(--fs-meta)}
.hhd>form{padding:var(--s1) 0}
/* #303 [sign in ▾]: the logins by name, a row under the head when open */
.hhd>.su{padding:var(--s1) 0}.hhd>.su>summary{list-style:none;cursor:pointer}.hhd>.su>summary::-webkit-details-marker{display:none}
.hhd>.su[open]{flex-basis:100%}.hhd>.su>div{display:flex;flex-wrap:wrap;gap:var(--s4);padding:var(--s2) 0}
.hcd>:is(.gr,.rw)+:is(.gr,.rw){border-top:1px solid var(--line)}
/* One-line values: names ellipsise, never break mid-token; a card's bar is in the meta size, so `free 12 GB of 228` fits at 390. */
.hcd .bar{min-width:0;font-size:var(--fs-meta)}
.hcd :is(.gr>.w,.rw>summary>.w){white-space:nowrap;overflow:hidden;text-overflow:ellipsis;overflow-wrap:normal}
/* An offline or off host: grey (it never pages), the same layout; its history stays readable. */
.hcd[data-c=m],.hcd[data-c=m] :is(.bar,b,.hnm b){color:var(--mute)}
/* A row with history: line 1 is #183's label | value | caret; line 2 the 24 h sparkline under the value, labelled. */
.sp{grid-column:2/-1;display:flex;align-items:end;gap:1ch;margin:var(--s1) 0 0}
.sp>i{font-style:normal;font-size:var(--fs-meta);line-height:1;color:var(--mute)}
.spk{flex:1;min-width:0;display:block;height:calc(var(--s4) + var(--s2));overflow:visible}
/* Lines: the value in the text colour, its part past the limit red; the limit dashed; lanes a purple step line;
   memory pressure a band along the floor (amber warn, red critical); no data a dotted muted line. */
.spk .ln,.hpl .ln{fill:none;stroke:var(--fg);stroke-width:1.25;stroke-linejoin:round}
.spk .ar,.hpl .ar{fill:color-mix(in srgb,var(--fg) 10%,transparent);stroke:none}
.spk .ov,.hpl .ov{fill:none;stroke:var(--r);stroke-width:1.5;stroke-linejoin:round}
.spk .lm,.hpl .lm{stroke:var(--mute);stroke-width:1;stroke-dasharray:3 3}
.spk .st,.hpl .st{fill:none;stroke:var(--p);stroke-width:1.25}
.spk .na,.hpl .na{stroke:var(--mute);stroke-width:1;stroke-dasharray:1 3}
.pw{fill:var(--a)}.pc{fill:var(--r)}
.hcd[data-c=m] .spk .ln{stroke:var(--mute)}
/* The open chart: [1h] [6h] [24h] and the read-out on one line, the plot with a left (value) and right (lanes) axis,
   the times under it, then the legend. Labels are HTML on %-positions, so text never stretches with the SVG. */
.hch{margin:0 0 var(--s2);padding:var(--s1) 0 0}
.htb{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s1) var(--s4);min-height:var(--hit);padding:0 var(--s2)}
.htb button[aria-pressed=true]{color:var(--l);box-shadow:inset 0 -2px var(--l)}
.hrd{flex:1 1 auto;min-width:0;text-align:right;font-size:var(--fs-meta);color:var(--mute);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hrd b{font-weight:400;color:var(--fg)}.hrd .r{color:var(--r)}.hrd .p{color:var(--p)}
.hpl{position:relative;height:calc(var(--hit) * 3);margin:var(--s2) 0 calc(var(--fs-meta) + var(--s1));padding:0 3ch 0 5ch;touch-action:pan-y}
.hpl>svg{position:absolute;top:0;bottom:0;left:5ch;right:3ch;width:calc(100% - 8ch);height:100%;overflow:visible}
.hpl .cx{stroke:var(--mute);stroke-width:1}
.hpl i{position:absolute;font-style:normal;font-size:var(--fs-meta);line-height:1;color:var(--mute);white-space:nowrap}
.hpl .yl{right:calc(100% - 5ch);padding-right:.5ch;transform:translateY(-50%)}
.hpl .yr{left:calc(100% - 3ch);padding-left:.5ch;transform:translateY(-50%);color:var(--p)}
.hpl .ylm{color:var(--fg)}
.hpl .xl{top:100%;padding-top:var(--s1);transform:translateX(-50%)}
.hpl .dot{width:var(--s2);height:var(--s2);border-radius:50%;background:var(--fg);transform:translate(-50%,-50%)}
.hpl .dot.r{background:var(--r)}.hpl .dot.l{background:var(--p)}
.hlg{display:flex;flex-wrap:wrap;gap:0 var(--s3);margin:var(--s4) 0 0;padding-left:5ch;font-size:var(--fs-meta);color:var(--mute)}
.hlg i{font-style:normal;color:var(--fg)}.hlg .p{color:var(--p)}.hlg .a{color:var(--a)}
/* #154: [later] folds a needs-you card into one red line, `n need you ▸ [later all]`; a tap on it shows them in place.
   The line is 28 px controls in 8 px padding: 44 px tall, the rings inside it. */
body:not(.unf) .ask.lt{display:none}
.later{display:flex;align-items:center;gap:var(--s4);margin:var(--s2) 0;padding:var(--s2);border:1px solid var(--r);border-radius:8px;background:color-mix(in srgb,var(--r) 15%,transparent)}
.later .lo{flex:1 1 auto;justify-content:flex-start;color:var(--r);text-transform:none}.later .lo::before{content:none}.later .lo::after{content:""}
/* #162: a fleet card: a bordered box with a 3 px top bar in the fleet's colour --fk (an accent token; red means "needs
   you", so it is never a bar). The header: name in the colour, need-you count, [drive now] [pause] [config]; then the drive line (.dp). */
.fc{--fk:var(--fk-l);margin:var(--s3) 0;border:1px solid var(--edge);border-top:3px solid var(--fk);border-radius:6px;padding:0 var(--s2) var(--s1)}
.k-l{--fk:var(--fk-l)}.k-p{--fk:var(--fk-p)}.k-c{--fk:var(--fk-c)}.k-g{--fk:var(--fk-g)}.k-a{--fk:var(--fk-a)}
.fh{display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--s4);min-height:var(--hit)}
.fn{flex:1 1 auto;min-width:0;display:flex;align-items:baseline;gap:var(--s2);white-space:nowrap;overflow:hidden}
.fn>b{color:var(--fk)}
.fh>.btns{padding-bottom:var(--s1)}
.fc>details.q:last-of-type{background:none}
/* `done today: N` and the paused line get a chevron: a row that opens shows it opens. */
.cv{font-style:normal;color:var(--mute)}.cv::before{content:"▸"}[open]>summary .cv::before{content:"▾"}
.fc>.done{border-bottom:0;border-top:1px solid var(--line)}
.fc>.done>summary{display:flex;gap:var(--s2);color:var(--mute);font-size:var(--fs-meta)}.fc>.done>summary>span{flex:1}
.fc>.done>p{margin:0 0 var(--s1);font-size:var(--fs-meta)}
/* A paused fleet: one grey line, its bar muted; [resume] on the right (paired devices only); a tap peeks its rows. */
.fc.off{--fk:var(--mute);border-bottom:1px solid var(--edge);padding-bottom:0;color:var(--mute)}
.fc.off>summary{display:flex;align-items:center;gap:var(--s4);min-height:var(--hit)}
.fc.off>summary>.fn{flex:1;text-overflow:ellipsis}
/* The [config] sheet: the lane sheet with the fleet's bar on top; groups of read-only rows (key 11 px, value 13 px)
   and the role pickers (the `set` op). A group's muted right-hand hint says where the rest is edited. */
.sh.cs{border-top:3px solid var(--fk)}.sh.cs .hd b{color:var(--fk)}
.sh.cs .top{flex:1 1 auto;min-height:0;padding-bottom:var(--s4)}
.cp{font-size:var(--fs-meta)}
.cg{border-top:1px solid var(--line);padding:var(--s1) 0 var(--s2)}
.cg>h3{display:flex;align-items:center;gap:var(--s2);min-height:var(--ctl);margin:0;font-size:var(--fs-meta);font-weight:400;letter-spacing:.08em;text-transform:uppercase;color:var(--fg)}
.cg>h3>span{margin-left:auto;letter-spacing:0;text-transform:none;color:var(--mute)}
.kv2{display:grid;grid-template-columns:15ch minmax(0,1fr);gap:var(--s1) var(--s2);align-items:baseline;margin:0}
.kv2>dt{font-size:var(--fs-meta);color:var(--mute)}
.kv2>dd{margin:0;min-width:0;overflow-wrap:anywhere}
.kv2 .tag{margin-left:var(--s1)}
.cs .role{display:flex;flex-direction:column;align-items:stretch;gap:var(--s1);padding:var(--s2) 0;border-top:0}
.cs .rh{display:flex;align-items:baseline;gap:var(--s2)}
.cs .top .rh,.cs .top .rk{margin:0}
.cs .rp{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s4);min-height:var(--hit)}
.cs .rk{font-size:var(--fs-meta);color:var(--mute)}
.cs .soon{padding:var(--s2);border:1px dashed var(--edge);border-radius:6px;color:var(--mute);font-size:var(--fs-meta)}
/* #166, #162 A: a card's second line, the drive state in the pass's colour: one full-width line that ellipsises (no
   7ch grid column); a tap lists the stall check, lanes, serial and each action in plain words, a tap on one its code. */
.dp summary{display:flex;align-items:center;gap:var(--s2)}.dp>summary{font-size:var(--fs-meta)}
.dp>summary>span{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dp>summary>i{font-style:normal}
.dp ul{margin:0 0 var(--s2);padding-left:var(--s4);color:var(--fg);font-size:var(--fs-meta)}.dp code{font-size:var(--fs-meta)}
/* #173: the pipeline group (in a fleet's [config] sheet) and the card's current stage. */
/* Stage kinds: a glyph in a fixed colour. ▲ build (pushes code) amber, ◆ check (PASS/FAIL) purple, ◫ gate
   (herdsman's own) cyan, ✓ merge green, ! park red ("needs you", as everywhere on the board). */
.kd{font-style:normal;color:var(--mute)}.kd.b{color:var(--a)}.kd.c{color:var(--p)}.kd.g{color:var(--c)}.kd.m{color:var(--g)}.kd.x{color:var(--r)}
/* The graph: one grid row per text line, all --ln tall, so every edge meets a line's middle. Column 1 is the
   park rail, column 2 the stage boxes, then one 2ch rail per loop target (shortest span innermost).
   serve.js writes grid-row / grid-area / the column list inline (no px). */
.pg{--ln:calc(var(--s4) + var(--s2));display:grid;min-width:0;margin:var(--s2) 0;line-height:var(--ln)}
.pg>*{position:relative;min-width:0;margin:0}
/* A box is a run of lines: the header (glyph, name, kind, "n here"), the role line, then one line per outcome
   that leaves the spine. Every line is one line: it ellipsises, the full text is its title. */
.nb{grid-column:2;display:flex;align-items:center;gap:var(--s2);padding:0 1ch;background:var(--card);border:solid var(--edge);border-width:0 1px;white-space:nowrap;overflow:hidden}
.nb.t{border-top-width:1px;border-radius:6px 6px 0 0}.nb.b{border-bottom-width:1px;border-radius:0 0 6px 6px}.nb.t.b{border-radius:6px}
.nb>b{font-weight:600}
.nb>.tag{margin-left:auto;line-height:1.5}
.nb .dt,.nb.po>span{min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:var(--fs-meta);color:var(--mute)}
.nb .dt.r{color:var(--r)}
.nb.po>span b{font-weight:400}
/* An outcome leaving the box: its word in its colour, then a leader to the box edge, where its rail picks it up.
   Right = back into a loop (grey); left = out of rounds, to park (red, dashed). */
.nb.po::after{content:"";flex:1 0 var(--s2);margin-right:-1ch;border-top:1px solid var(--mute)}
.nb.po.l::after{display:none}
.nb.po.l::before{content:"";flex:0 0 1ch;margin-left:-1ch;border-top:1px dashed var(--r)}
.nb.end{border-color:var(--edge)}
/* Errors: a broken stage gets a red edge; an unreachable one is dashed and dimmed. */
.nb.bad{border-color:var(--r)}
.nb.dead{border-style:dashed;border-color:var(--r)}.nb.dead>:not(.dt){opacity:.55}
/* The spine: the main outcome (push / PASS / ok) straight down to the next stage, its word beside the arrow. */
.pl{grid-column:2;padding-left:4ch;font-size:var(--fs-meta);color:var(--mute);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pl>b{font-weight:400;margin-right:1ch}
.pl::before{content:"";position:absolute;left:2ch;top:0;bottom:0;border-left:1px solid var(--mute)}
.pl::after{content:"▾";position:absolute;left:2ch;bottom:0;translate:-50% 35%;line-height:1;color:var(--mute)}
.pl.no::before,.pl.no::after,.pl.pn::before,.pl.pn::after{display:none}
.pl.pn{padding-left:1ch;white-space:normal}
.nl{grid-column:2;display:flex;gap:var(--s2);padding-left:1ch;white-space:nowrap;overflow:hidden}
.nl>i{position:relative;left:.5ch}
/* Rails. .ea: a line across the row's middle from the box edge to its rail; .in adds the arrowhead into a box.
   .ey: the rail itself, middle of its first row to middle of its last. */
.ea::before{content:"";position:absolute;left:0;right:1ch;top:50%;border-top:1px solid var(--mute)}
.ea.in::after{content:"◂";position:absolute;left:0;top:50%;translate:-20% -52%;font-size:var(--fs);line-height:1;color:var(--mute)}
.ey::before{content:"";position:absolute;left:50%;top:calc(var(--ln) / 2);bottom:calc(var(--ln) / 2);border-left:1px solid var(--mute)}
.ea.l::before{left:1ch;right:0;border-top-style:dashed;border-color:var(--r)}
.ea.l.in::after{content:"▸";left:auto;right:0;translate:0 -52%;color:var(--r)}
.ey.l::before{border-left:2px dashed var(--r)}
.ek{z-index:1}.ek::before{content:"";position:absolute;inset:15% 0;background:var(--bg)}
/* A loop target's header names the rail that joins it. */
.nb>.lp{margin-left:auto;font-size:var(--fs-meta);color:var(--mute)}.nb>.tag~.lp{margin-left:0}
.ea{z-index:2}
/* The pipeline group: a status line, the graph, the source; side by side when there is room for both. */
.pp .pv{margin:0 0 var(--s1);font-size:var(--fs-meta);color:var(--mute)}
.pp .pw2{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,56ch),1fr));gap:0 var(--s4);align-items:start}
.pp .lg{margin:var(--s1) 0 0;font-size:var(--fs-meta);color:var(--mute)}
.pp .lg i{font-style:normal}
.tm{border:0;margin:var(--s2) 0}
.tm>summary{display:flex;align-items:center;gap:var(--s2);min-height:var(--hit);font-size:var(--fs-meta);color:var(--mute)}
.tm pre{margin:0;padding:var(--s2);background:var(--card);border:1px solid var(--edge);border-radius:6px;font:inherit;font-size:var(--fs-meta);white-space:pre-wrap;overflow-wrap:anywhere}
/* A refused pipeline: what stops, then one line per broken rule, each with its place in fleet.toml. */
.pe{margin:var(--s1) 0 var(--s2);padding:0 var(--s2);border:1px solid var(--r);border-radius:6px}
.pe>p{margin:var(--s2) 0}
.pe ol{margin:0 0 var(--s2);padding:0;list-style:none}
.pe li{padding:var(--s1) 0;border-top:1px solid var(--line)}
.pe li>b{font-weight:400;margin-right:1ch}
.pe li>.at{font-size:var(--fs-meta);color:var(--mute);margin-left:1ch}
.pe .qn{color:var(--fg)}
/* The card's "where it is now": queued ─ stages ─ merge, wrapping; the current stage lit in its kind's colour,
   a check that PASSed at the head ticked. Under it, one 11 px line: the round and what it waits on. */
.ps{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s1) 0;margin:var(--s2) 0 0;color:var(--mute)}
.ps .sx{font-style:normal;padding:0 .5ch}
.pt{display:inline-flex;gap:.5ch;padding:0 var(--s1);border:1px solid transparent;border-radius:4px;white-space:nowrap}
.pt.dn{color:var(--fg)}
.pt.on{--kc:var(--mute);color:var(--fg);border-color:var(--kc);background:color-mix(in srgb,var(--kc) 16%,transparent)}
.pt.on.kb{--kc:var(--a)}.pt.on.kc{--kc:var(--p)}.pt.on.kg{--kc:var(--c)}
/* #170 Events: #162's fleet colour --fk and its dot; chips [all] [important] [● fleet] (pressed: unfilled per #58, accent text
   and underline, a fleet chip in its own colour); sticky time groups; a row is glyph · dot · #N · words (2 lines) · age, opening to links + raw. */
.fd{display:inline-block;width:var(--s2);height:var(--s2);border-radius:50%;background:var(--fk,transparent);flex:none}
.chips{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s4);padding:var(--s3) var(--s2) var(--s1)}
.chips button[aria-pressed=true]{color:var(--l);box-shadow:inset 0 -2px var(--l)}
.chips .fc2>span{display:inline-flex;align-items:center;gap:.6ch}
.chips .fc2[aria-pressed=true]{color:var(--fk);box-shadow:inset 0 -2px var(--fk)}
.es{margin:var(--s1) 0 var(--s2);font-size:var(--fs-meta)}
.eg>h3{position:sticky;top:calc(var(--hit) + var(--s1));z-index:1;display:flex;justify-content:space-between;margin:0;
  padding:var(--s1) 0;background:var(--bg);border-bottom:1px solid var(--line);font-size:var(--fs-meta);font-weight:400;
  letter-spacing:.08em;text-transform:uppercase;color:var(--mute)}
.eg>h3>span+span{letter-spacing:0}
details.er>summary{grid-template-columns:2ch var(--s2) 6ch minmax(0,1fr) auto;gap:var(--s2);padding:var(--s1) 0}
.kg{font-style:normal;font-weight:700;text-align:center}
.er .n{white-space:nowrap;overflow:hidden}
.er .sm{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.er .ag{font-size:var(--fs-meta);color:var(--mute);text-align:right;white-space:nowrap}
.er:not(.imp) .sm{color:var(--mute)}
.er[open] .sm{display:block}
.ex{padding:0 0 var(--s2) calc(2ch + 3 * var(--s2))}
.lk{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s4);margin:var(--s2) 0;min-height:var(--ctl)}
.lk>.m{font-size:var(--fs-meta)}
.ex pre{margin:0;padding:var(--s1) var(--s2);border-radius:4px;background:var(--card);font-size:var(--fs-meta);white-space:pre-wrap;overflow-wrap:anywhere}
.fl2{list-style:none;margin:var(--s1) 0 0;padding:0;font-size:var(--fs-meta)}
.fl2 li{padding:calc(var(--s1) / 2) 0}
/* The header never wraps its title: it ellipsises beside [?] [↻] [🐎] [⚙] at 390 (+ [Pair]) as a last resort. */
body>header>b{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* #290: the look sheet (docs/design/pickers), #440: System's Appearance: two listboxes, THEME and COLOURS (`.cg` groups
   as in [config]), then STYLE; ≥ 900 px side by side. */
/* A row: 44 px, the art, the name, `(theme default)`; the current one is in the accent with a ✓. Pressed inverts like a
   control; the keyboard's row has a 2 px accent ring. */
.lko{display:flex;align-items:center;gap:var(--s3);min-height:var(--hit);padding:0 var(--s1);border-top:1px solid var(--line);cursor:pointer;outline:0;-webkit-tap-highlight-color:transparent}
.lko:first-child{border-top:0}
.lko>.ln{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lko>small{flex:none;font-size:var(--fs-meta);color:var(--mute)}
.lko::after{content:"";flex:none;margin-left:auto;width:2ch;text-align:center}
.lko[aria-selected=true]>.ln,.lko[aria-selected=true]::after{color:var(--l)}
.lko[aria-selected=true]::after{content:"✓"}
.lko:active{background:var(--l)}.lko:active>*,.lko:active::after{color:var(--bg)}
.lko:focus-visible{box-shadow:inset 0 0 0 2px var(--l)}
/* The art, one column wide in both lists so the names line up: a theme's row sprite (crisp) or its icon on a 24 px tile,
   the same tile for every theme; a scheme's `Aa` (its fg on its bg, bordered), then its green, amber and red chips. */
.lka,.lsw{display:flex;flex:none;gap:calc(var(--s1) / 2);width:calc(5 * var(--s4));height:calc(var(--s4) + var(--s2))}
.lka>*{width:calc(var(--s4) + var(--s2));height:100%;border:1px solid var(--edge);border-radius:5px;background:var(--card)}
.lka>svg{shape-rendering:crispEdges;image-rendering:pixelated}
.lka>.asc{display:flex;align-items:center;justify-content:center;font-size:var(--fs-meta);font-weight:400;font-style:normal}
.lsw>b{flex:1;border-radius:3px}
.lsw>.aa{flex:none;display:grid;place-items:center;width:calc(var(--s4) + var(--s2));border:1px solid var(--edge);font-size:var(--fs-meta);font-weight:400}
.lkn{margin:var(--s2) 0 0;font-size:var(--fs-meta);color:var(--mute)}
/* #367: the Queue tab one repo at a time (serve.js qchips): repo chips in #170's look, a red dot when it needs you; the
   repo's groups under 13 px headers; a blocked chain one row ([▾] opens its steps in place), `+ N more` likewise; [all]
   shows only the needs-you groups. A sideways swipe is the page's (no pan), a vertical one scrolls. */
#queue{touch-action:pan-y}
.qch{padding-left:0;padding-right:0}.qch .r{margin-left:.6ch}
.qg>h3{margin:var(--s3) 0 0}
/* #391: the chain row is a row (serve.js `qfold`); its third line names the steps and opens them in place. */
.cst::before{content:"▸ "}.qc[open]>summary>.cst::before{content:"▾ "}
.qx{border-bottom:0}.qx>summary{display:flex;white-space:pre;color:var(--link)}.qx>summary>:last-child{flex:1}
.fc.qa>:not(.fh,summary,.qg[data-g=need]){display:none}
/* #365: the backlog under a repo's queue: search, quick filters, rows to tick; [queue N] sits right above the tab bar. */
.bl>summary{display:flex;gap:var(--s2)}.bl>summary>span:first-of-type{flex:1}.bl>summary>.cv{order:1}
.bs{display:flex;margin:var(--s2) 0}.bs input{flex:1;min-width:0;font:inherit;font-size:var(--fs-input)}
.bi{display:grid;grid-template-columns:auto 6ch minmax(0,1fr);gap:0 var(--s2);align-items:center;min-height:var(--hit);border-bottom:1px solid var(--line)}
.bi[hidden],.bbar[hidden]{display:none}
.bi>.tl{grid-column:3;margin-top:0;color:var(--fg)}.bi>.m{grid-column:3;font-size:var(--fs-meta)}
.bl:has(>.bbar:not([hidden])){padding-bottom:calc(var(--hit) + var(--s3))}
.bbar{position:fixed;left:0;right:0;bottom:calc(var(--hit) + var(--s2) + env(safe-area-inset-bottom));display:flex;justify-content:flex-end;padding:var(--s2);background:var(--bg);border-top:1px solid var(--line)}
/* #386: the [chat] tab (docs/design/conductor-chat/): on a phone the thread list or one thread (serve.js's #cht style
   picks it); from 1000 px both, the list a 400 px column on the left, the thread beside it, its prose capped at 100ch. */
#chat{padding-bottom:var(--s2)}
@media (min-width:1000px){
  #chat{display:grid;grid-template-columns:400px minmax(0,1fr);gap:0 calc(2 * var(--s4));align-items:start}
  html:not([data-tab=chat]) #chat{display:none}
  .clp{position:sticky;top:calc(var(--hit) + var(--s1))}
  .cvp{border-left:1px solid var(--line);padding-left:calc(2 * var(--s4))}
  .cvp>*{max-width:100ch}
  .th .bk{display:none}
}
/* A repo card is the Queue tab's fleet card (#162); "all repos" takes the text colour. */
.fc.k-x{--fk:var(--fg)}
.fc .fh .ds{margin-left:1ch;font-size:var(--fs-meta);color:var(--mute)}
/* A thread row: the unread dot, the title, the age; then, 11 px, the state when not plain awake and the last message. */
.tr{display:grid;grid-template-columns:1.5ch minmax(0,1fr) auto;gap:0 var(--s2);align-items:baseline;min-height:var(--hit);padding:var(--s1) 0;border-top:1px solid var(--line);color:inherit;text-decoration:none}
.tr>.ud{font-style:normal;color:var(--link)}
.tr>.tt{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tr.rd>.tt{color:var(--mute)}
.tr>.ta{font-size:var(--fs-meta);color:var(--mute);white-space:nowrap}
.tr>.tp{grid-column:2/-1;font-size:var(--fs-meta);color:var(--mute);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tr>.tp b{font-weight:400;margin-right:1ch}
/* #413: a linked row's chip, `from t5` / `continued in t6`: a tap opens that thread. */
/* `.lk` is the event card's link line; this chip is inline. */
.lc{display:inline;margin:0;color:var(--link);border:1px solid var(--edge);border-radius:6px;padding:0 .5ch;cursor:pointer}
.fc>.done>summary{min-height:var(--hit)}
/* #405: a thread row on one line with its [archive] (shown once the row is swiped left) or, archived, its [restore]. */
.sw{display:flex;align-items:center;gap:var(--s4);border-top:1px solid var(--line)}
.sw>.tr{flex:1;min-width:0;border-top:0;touch-action:pan-y}
.sw:not(.op)>.sb[name=archive]{display:none}
/* The thread bar, sticky under the header: [‹] (phone only), the title, repo · harness · model · state. #408: on the
   [chat] tab the page clips sideways instead of hiding (a hidden body is a scroll box: nothing in it would stick). */
html[data-tab=chat],html[data-tab=chat] body{overflow-x:clip}
.th{position:sticky;top:calc(var(--hit) + var(--s1));z-index:1;display:flex;align-items:center;gap:var(--s4);min-height:calc(var(--hit) + var(--s2));background:var(--bg);border-bottom:1px solid var(--line)}
.th>div{flex:1;min-width:0}
.th b,.th .ds{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.th .ds{font-size:var(--fs-meta);color:var(--mute)}
.th .cw{font-size:var(--fs-meta);font-weight:400} /* #460: `config c1 waiting` under the title while a proposal waits */
.th .dt{display:inline-block;width:var(--s2);height:var(--s2);margin-right:.5ch;border-radius:50%;background:var(--g)}
.tc{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s2) 0}
.tmo{cursor:pointer}
.blk>summary .ct{flex:none;color:var(--mute)}
/* An image at the bubble's width, at most 320 px tall, its name and size under it; any other file one 44 px row. */
.im{margin:var(--s2) 0 0}
.im img{display:block;cursor:zoom-in;max-width:100%;max-height:320px;object-fit:cover;object-position:top;border:1px solid var(--edge);border-radius:6px}
.im figcaption{margin-top:var(--s1);font-size:var(--fs-meta);color:var(--mute)}
/* #406: the image viewer: black in every scheme (a photo's backdrop), the image fitted (the page's gestures off: pinch
   and swipe are its own); [×], the count and [save] in a bar over its top. `.dr`: a finger is down, the image follows it without easing. */
#iv{position:fixed;inset:0;z-index:4;display:flex;align-items:center;justify-content:center;overflow:hidden;background:black;touch-action:none;-webkit-user-select:none;user-select:none}
#iv>img{max-width:100%;max-height:100%;object-fit:contain;transition:transform .2s;-webkit-user-drag:none}
#iv.dr>img{transition:none}
.ivb{position:absolute;top:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;min-height:var(--hit);padding:env(safe-area-inset-top) var(--s3) 0;background:color-mix(in srgb,black 50%,transparent);color:white}
.ivb button{color:white}
.ivn{font-size:var(--fs-meta)}
.tf{display:flex;align-items:center;gap:var(--s2);min-height:var(--hit);margin-top:var(--s2);padding:0 var(--s2);border:1px solid var(--edge);border-radius:6px;color:var(--fg);text-decoration:none}
.tf>span:first-of-type{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tf .m{font-size:var(--fs-meta)}
/* A choice (#63 A's rows, recommended first, and an "other" box); answered, only the green ✓ line stays. Inside a
   thread "waits for you" is amber; red stays the needs-you stack. */
.chq{display:flex;flex-direction:column;align-items:stretch;gap:var(--s2);margin-top:var(--s2)}
.chq .oth{display:flex;gap:var(--s4);align-items:center;margin-top:var(--s1)}
.chq .oth input{flex:1;min-width:0;font:inherit;font-size:var(--fs-input);color:var(--fg);background:var(--bg);border:1px solid var(--edge);border-radius:6px;padding:var(--s1) var(--s2)}
.blk:has(>.md+.chq){--k:var(--a)}
/* #492: a handoff card's older threads behind [more]. */
.chq .more>summary,.chg>summary{display:flex;align-items:center;min-height:var(--hit);color:var(--mute)}
.chq .more>button{margin-top:var(--s2)}
/* #387: a config proposal's diff with [apply] [discard], and a secret's masked input with [save] [dismiss]: both amber. */
.df{margin:var(--s1) 0 0;padding:var(--s2);overflow-x:auto;font-size:var(--fs-meta);background:var(--bg);border:1px solid var(--edge);border-radius:6px;white-space:pre}
/* #409: a fenced block in a message: its exact text in a box that scrolls sideways, [copy] in its top corner (no
   scrollbar: WebKit leaves a classic one out of the box's height inside a flex column). */
.cb{position:relative}.cb pre{margin:0;padding:var(--ctl) var(--s2) var(--s2);overflow-x:auto;scrollbar-width:none;white-space:pre;font-size:var(--fs-meta);background:var(--bg);border:1px solid var(--edge);border-radius:6px}
.cb .cpy{position:absolute;top:0;right:var(--s2)}
:is(.chc,.chs){display:flex;gap:var(--s4);align-items:center;margin-top:var(--s2)}
.chs input{flex:1;min-width:0;font:inherit;font-size:var(--fs-input);color:var(--fg);background:var(--bg);border:1px solid var(--edge);border-radius:6px;padding:var(--s1) var(--s2)}
.blk:has(>.md+:is(.chc,.chs)){--k:var(--a)}
.ans{margin:var(--s2) 0 0;color:var(--g)}.ans .m{font-size:var(--fs-meta)}
.qid{font-size:var(--fs-meta);color:var(--mute)}
/* A device that is not a paired owner device reads the thread; its choices and composer are inert. */
.cvp :is(.chq,.chc):has([disabled]),.cvp .tw:has([disabled])>*{opacity:.6}
.cvp>.ns{margin:0;font-size:var(--fs-meta)}
/* The live line and the composer are the sheet's (.live, .reply). */
.tlv{margin:0;padding-top:var(--s1);color:var(--mute);font-size:var(--fs-meta);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tlv b{font-weight:400;color:var(--a)}.tlv b.g{color:var(--g)}
.tw{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s4);padding:var(--s2) 0}
.tw textarea{flex:1;min-width:0;font:inherit;color:var(--fg);background:var(--card);border:1px solid var(--edge);border-radius:6px;padding:var(--s2);min-height:var(--hit);resize:none;font-size:var(--fs-input)}
/* #404: the composer's chips under the box: an empty thread's harness, a thread's model and effort. */
.cbar{flex-basis:100%;display:flex;flex-wrap:wrap;gap:var(--s4);padding:0 var(--s2);font-size:var(--fs-meta)}
/* The composer, sticky above the tab bar: [+] attach, the text, [send]; #405: the picked files wait above it, a row of
   56 px thumbnails (a file's name in its place), [×] under each. */
.cvp .tw{position:sticky;bottom:calc(var(--hit) + var(--s2) + env(safe-area-inset-bottom));margin-bottom:var(--hit);background:var(--bg);border-top:1px solid var(--line)}
.ats{flex-basis:100%;display:flex;gap:var(--s4);overflow-x:auto;padding:0 var(--s2) var(--s2)}
.att{flex:none;display:flex;flex-direction:column;align-items:center;gap:var(--s2);width:calc(var(--hit) + var(--s3))}
.att>:is(img,span){width:100%;height:calc(var(--hit) + var(--s3));object-fit:cover;object-position:top;border:1px solid var(--edge);border-radius:6px}
.att>span{font-size:var(--fs-meta);color:var(--mute);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* #403: the box grows with its text to 6 lines, then scrolls inside; with the keyboard up (the box focused) a phone
   hides the tab bar. A message sent this session reads `sending…`, then ✓; failed, red with [retry]. A failed
   delivery's system line is red too. A working thread's mark is the loading strip's art (#ld), 24 px, inline. */
.tw textarea{max-height:calc(6lh + 2 * var(--s2) + 2px);overflow-y:auto}
/* #443: on a phone the open thread is fixed between the header and the tab bar, or the keyboard's top (`--kb`,
   serve.js) while the box is focused: the composer sits flush on it, the page never scrolls, only the messages do. */
@media (max-width:999px){
  html[data-tab=chat] .cvp{position:fixed;top:calc(var(--hit) + var(--s1));left:0;right:0;bottom:max(var(--kb),calc(var(--hit) + var(--s2) + env(safe-area-inset-bottom)));display:flex;flex-direction:column;padding:0 var(--s3)}
  html[data-tab=chat] .cvp .tc{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}
  html[data-tab=chat] .cvp .tw{position:relative;bottom:auto;margin-bottom:0}
  html:has(.cvp .tw textarea:focus) nav{display:none}html:has(.cvp .tw textarea:focus) .cvp{bottom:var(--kb)}
}
.snt .md p{white-space:pre-line}.blk>summary .sk{flex:none;font-weight:400;color:var(--g)}
.blk.snt.bad{--k:var(--r)}.snt.bad>summary .ct{color:var(--r)}.qs.note.r{border-left-color:var(--r);color:var(--r)}
.tld{display:inline-grid;place-items:center;min-width:calc(var(--s4) * 1.5);height:calc(var(--s4) * 1.5);vertical-align:middle;font-style:normal}
.tld .lds{width:calc(var(--s4) * 1.5);height:calc(var(--s4) * 1.5);image-rendering:pixelated;shape-rendering:crispEdges;animation:ldg .5s steps(2) infinite,ldk .25s infinite}
.tld i{font-style:normal;color:var(--mute);animation:s 1s linear infinite}.tld i::before{content:"↻"}.tld .lda{display:none;white-space:pre;color:var(--fg)}
html:has(#ld.ld) .tld i,html:has(#ld:not(.ld)) .tld .lds,html:has(#ld.la) .tld :is(.lds,i){display:none}html:has(#ld.la) .tld .lda{display:grid}
@media (prefers-reduced-motion:reduce){.tld :is(.lds,i){animation:none}}
/* #407: a finished turn's commands fold into one `▸ N commands` row; open, its rows under it. */
.blk.fold{--k:var(--a)}.fold>summary::before{content:"▸";color:var(--k)}.fold[open]>summary::before{content:"▾"}
.blk.fold[open]>summary .pv{visibility:visible}.fold>.blk{margin-top:var(--s4)}
/* #407: the floating pill above the box (working, stopping…, reconnecting…, offline); the line it replaces hides. */
.tlv.wk{display:none}
.pill{position:absolute;bottom:calc(100% + var(--s2));left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:var(--s2);max-width:calc(100% - 2 * var(--s4));min-height:var(--ctl);padding:0 var(--s3);border:1px solid var(--edge);border-radius:999px;background:var(--card);color:var(--mute);font-size:var(--fs-meta);white-space:nowrap}
/* #407: queued messages above the box, one line each with [send now] edit [remove]; the edit line; the hint under it. */
.tq{flex-basis:100%;min-width:0;display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--s4);padding:0 var(--s2);border-left:2px solid var(--a);border-radius:6px;background:var(--card)}
.tq>p{flex-basis:100%;margin:0;padding-top:var(--s1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tw>:is(.qe,.qh){flex-basis:100%;margin:0;font-size:var(--fs-meta);color:var(--mute)}.tw>.qh{margin-top:calc(-1 * var(--s2))}
/* #407: a long press's menu: the send's [queue]/[steer] choices, or a message's [copy] [copy as markdown] [quote]. */
#mm{position:fixed;z-index:3;left:var(--s3);right:var(--s3);display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);padding:var(--s2) var(--s3);border:1px solid var(--edge);border-radius:6px;background:var(--card);font-size:var(--fs-meta)}
#mm[hidden]{display:none}
@media (pointer:coarse){.cvp :is(.snd,.tc .blk:is(.me,.ai)){-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}}
/* #440: the System sheet (docs/design/system-sheet). [⚙] in [◐]'s place, its dot red, 8 px, on the top right corner. */
#sysb{position:relative}
#sysb .sd,.sxi .sd{position:absolute;top:0;right:0;width:var(--s2);height:var(--s2);border-radius:50%;background:var(--r);box-shadow:0 0 0 2px var(--bg)}
:is(#sysb,.sxi) .sd[hidden]{display:none}
nav a{flex:1 1 0}
/* Its own layer under #sheet (z 3), at the full detent; the index between its head and its scroller. */
#sys{position:fixed;inset:0;z-index:2;overscroll-behavior:contain}
#sys[hidden]{display:none}
#sys>.sbd{position:absolute;inset:0;background:var(--scrim)}
#sys>.sh{transform:none;transition:none}
html.sysopen{overflow:hidden}
.sh.sys .hd p{display:flex;align-items:center;gap:var(--s2)}
.sh.sys .hd b{flex:1}
/* The index: one line of bracket chips that scrolls sideways at 390, the current one filled like the tab bar's. */
.sxi{flex:none;display:flex;gap:var(--s3);overflow-x:auto;scrollbar-width:none;margin:0 calc(-1 * var(--s3));padding:0 var(--s3) var(--s2);border-bottom:1px solid var(--line);mask-image:linear-gradient(90deg,black calc(100% - 3ch),transparent)}
.sxi::-webkit-scrollbar{display:none}
.sxi a{position:relative;flex:none;display:flex;align-items:center;min-height:var(--ctl);color:var(--mute);text-decoration:none;white-space:nowrap}
.sxi a>span::before{content:"["}.sxi a>span::after{content:"]"}
.sxi a>span{display:inline-flex;align-items:center;height:var(--ctl);padding:0 .3ch}
.sxi a.on>span{background:var(--l);color:var(--bg)}
/* The scroller: every section in one column; a head is the tab line's style (bold, its theme word first). */
/* It spans the sheet's width, its content inset as the sheet's, so a right-aligned control's tap ring is never clipped. */
.sh.sys .top{position:relative;flex:1 1 auto;min-height:0;max-height:none;border:0;margin:0 calc(-1 * var(--s3));padding:0 var(--s3) calc(var(--s4) * 4)}
.sy{padding:var(--s2) 0 var(--s3);border-bottom:1px solid var(--line)}
.syh{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 var(--s2);margin:var(--s2) 0 var(--s1);padding:var(--s1);font-size:var(--fs);font-weight:700}
.syh .syt{flex:none}
.syh .sym{flex:1 1 14ch;min-width:0;font-size:var(--fs-meta);font-weight:400;color:var(--mute);text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.syh .sym.a{color:var(--a)}
.sy[data-t=r]>.syh{color:var(--r);background:color-mix(in srgb,var(--r) 12%,transparent);border-radius:4px}
.sy[data-t=r]>.syh .sym{color:inherit}
/* The moved tabs drop their own first line (the head says it), their padding and sticky offsets. */
#sys :is(#host,#events){display:block;padding:0;margin:0}
#sys :is(#host,#events)>.tsub{display:none}
#sys .eg>h3{top:0}
/* Agent providers: a card per provider (the host card's box), an account or key per row. */
.pvg{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,56ch),1fr));gap:var(--s3);align-items:start}
.pvc{box-shadow:inset 0 0 0 1px var(--line);border-radius:6px;padding:0 var(--s2) var(--s2);min-width:0}
.pvch{display:flex;align-items:center;gap:var(--s2);min-height:var(--hit);border-bottom:1px solid var(--line)}
.pvr{padding:var(--s2) 0;border-bottom:1px solid var(--line)}.pvr:last-child{border-bottom:0}
.pvr p{margin:0}
.pvh{display:flex;align-items:center;gap:var(--s2);min-height:var(--ctl)}
.pvs{margin-left:auto;font-weight:700;text-align:right}
.pvs.g{color:var(--g)}.pvs.a{color:var(--a)}.pvs.r{color:var(--r)}
.pvr[data-t=r]{box-shadow:inset 3px 0 var(--r);padding-left:var(--s2)}
.pvm,.pvf{font-size:var(--fs-meta);color:var(--mute)}
.pvu{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s1) var(--s3);margin-top:var(--s1)!important}
.pm{display:inline-flex;align-items:center;gap:var(--s1);white-space:nowrap}
.pm .k{color:var(--mute);font-size:var(--fs-meta);min-width:2.5ch}
.pvc .bar{font-size:var(--fs-meta)}.pvc .bar.g{color:var(--g)}.pvc .bar.a{color:var(--a)}.pvc .bar.r{color:var(--r)}.pvc .bar i{font-style:normal;opacity:.45}
.pvf{margin:var(--s2) 0 0}
/* Fleets: a row per fleet in its colour; it opens to the [config] content (.cs keeps its rules). */
.sfl{border-top:1px solid var(--line)}.sfl:first-of-type{border-top:0}
.sfl>summary{display:flex;align-items:center;gap:var(--s2);min-height:var(--hit);padding:0 var(--s1);list-style:none;white-space:nowrap}
.sfl>summary::-webkit-details-marker{display:none}
.sfl>summary :is(.fq,b){flex:none;font-style:normal;color:var(--fk)}
.sfl>summary .m{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:var(--fs-meta)}
.sfl[open]{box-shadow:inset 3px 0 var(--fk);padding-left:var(--s2)}
.sfl>.cs{padding:0 0 var(--s2)}
/* Notifications and Conductor reuse the config groups. */
.sy .cs .cg:first-child{border-top:0}
.role2{display:flex;align-items:center;gap:var(--s2);min-height:var(--hit);border-top:1px solid var(--line)}
.role2:first-of-type{border-top:0}
.role2>span{flex:1;min-width:0}
.sy .mt{font-size:var(--fs-meta);color:var(--mute)}
.role2>span>:is(.m,.mt){display:block}
.sy code{color:var(--l);background:color-mix(in srgb,var(--l) 12%,transparent);border-radius:3px;padding:0 .3ch;font:inherit}
.sy a.go{margin-left:var(--s1)}
/* A host card's [sign in ▾] keeps one line beside the name (Claude's sign-in is Agent providers'). */
#sys .hhd>.su>summary{white-space:nowrap}
/* At 900 px and over: the index is a rail on the left, the sections a column on the right. */
@media (min-width:900px){
  .sh.sys{display:grid;grid-template-columns:calc(var(--s4) * 13) minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);column-gap:calc(2 * var(--s4))}
  .sh.sys>.hd{grid-column:1/-1}
  .sxi{flex-direction:column;align-items:stretch;gap:var(--s1);margin:0;padding:var(--s2) 0;border:0;border-right:1px solid var(--line);overflow:visible;mask-image:none}
  .sxi a>span{padding:0 .5ch}
  .sxi a .sd{position:static;margin-left:var(--s2)}
  .sh.sys .top{margin-left:0}
  .sy .look{display:grid;grid-template-columns:repeat(2,minmax(0,420px));gap:0 calc(3 * var(--s4));align-content:start}
  .sy .look .lkn{grid-column:1/-1}
  .sy>.cs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 calc(2 * var(--s4))}
  .sy>.cs>.cg:nth-child(2){border-top:0}
}
