/* Atelier — one stylesheet for the three screens.
   Theme-aware: the palette is defined once on :root and only redefined for dark. */
:root{
  --bg:#f3f5fb; --panel:#fff; --panel-2:#f7f9fe; --ink:#0e0f15; --ink-2:#262833; --muted:#4c5063;
  --line:#c9cedd; --line-2:#e0e4ee;
  --accent:#0f7a47; --accent-soft:#dcf5e7;
  --live:#0b7489; --live-soft:#d6f3f8;
  --doing:#8a5600; --doing-soft:#ffeecb;
  --q:#8233d6; --q-soft:#f1e4ff;
  --note:#b3206c; --note-soft:#fde3f0;
  --todo:#1256e0; --todo-soft:#e0ebff;
  --paused:#4c5063; --paused-soft:#e8eaf1;
  --tagmix:58%; --on-st:#fff; --heremix:24%;
  --armed:#f5a300; --on-armed:#1a1205;
  --danger:#c2362b; --shadow:0 1px 2px rgba(0,0,0,.06), 0 4px 12px rgba(0,0,0,.05);
}
/* --live is a worker RUNNING (r582): its own cyan, never --accent, which is done and
   Archive — a board with sessions going read as a board whose work was finished. */
/* r196, Simon: text a bit more white, the blue more blue, borders you can see. */
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --bg:#111219; --panel:#1b1c26; --panel-2:#232532; --ink:#fcfcff; --ink-2:#eceef6; --muted:#c3c7d9;
  --line:#464b63; --line-2:#34374b;
  --accent:#4feb9f; --accent-soft:#12372a;
  --live:#3fd3ee; --live-soft:#0f3340;
  --doing:#ffc53d; --doing-soft:#372a0e;
  --q:#d096ff; --q-soft:#301c4a;
  --note:#ff7ac6; --note-soft:#3f1932;
  --todo:#4f95ff; --todo-soft:#142a52;
  --paused:#b3b7ca; --paused-soft:#262834;
  --tagmix:100%; --on-st:#0e0f15; --heremix:38%;
  --armed:#ffc53d; --on-armed:#1a1205;
  --danger:#ff7667; --shadow:0 1px 2px rgba(0,0,0,.3), 0 4px 14px rgba(0,0,0,.25);
}}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);
  font:15px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
a{color:var(--accent)}
header{position:sticky;top:0;z-index:20;background:var(--panel);border-bottom:1px solid var(--line);
  padding:10px 20px;display:flex;gap:12px;align-items:center;flex-wrap:wrap}
h1{font-size:15px;margin:0;font-weight:700;letter-spacing:.01em;
  display:flex;align-items:center;gap:2px;flex:none;white-space:nowrap}
.wordmark{color:var(--ink);text-decoration:none;padding:4px 8px;border-radius:7px;
  display:inline-flex;align-items:center;gap:8px}
/* The logo (r220, atelierLogo in app.js): colours land one by one on the first
   draw, and hop seat to seat while the pointer is on the wordmark. */
.logo{display:inline-block;width:32px;height:32px;flex:none;margin:-5px 0}
.logo svg{display:block;width:100%;height:100%}
.logo .lg-seats{transform-box:view-box;transform-origin:32px 32px}
.logo .lg-c{transform-box:fill-box;transform-origin:center}
.logo.appear .lg-c{animation:lgpop .32s cubic-bezier(.3,1.6,.6,1) calc(.2s + var(--i) * .11s) both}
.wordmark:hover .lg-seats{animation:lgturn 2s steps(8) infinite}
@keyframes lgpop{from{transform:scale(0)}to{transform:scale(1)}}
@keyframes lgturn{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion: reduce){
  .logo.appear .lg-c,.wordmark:hover .lg-seats{animation:none}
}
a.wordmark:hover{background:var(--panel-2);color:var(--accent)}
/* On the mother page it is a label, not a door. */
.wordmark.here{color:var(--accent);cursor:default}
h1 span{color:var(--muted);font-weight:400}
/* NAV. Nine flat buttons in a row read as nine equally important things. They
   are three groups — where you work, what the board knows, what keeps it
   honest — so they are drawn as three groups, with an icon each so the shape is
   recognisable before the word is read. */
/* The nav never wraps the header onto a second row. Nine items plus a wordmark
   plus a counts pill does not fit at every width, and a header that grows a row
   pushes the whole page down — so the nav scrolls sideways instead, at every
   size, and the pill shrinks before anything else does. */
nav{display:flex;align-items:center;gap:3px;flex-wrap:nowrap;
  overflow-x:auto;scrollbar-width:none;min-width:0}
nav::-webkit-scrollbar{display:none}
header{flex-wrap:nowrap}
header .pill{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.nvl{display:inline-flex;align-items:center;gap:6px;color:var(--muted);
  text-decoration:none;font-size:14.5px;border:1px solid transparent;
  padding:4px 10px;border-radius:7px;white-space:nowrap}
.nvl:hover{background:var(--panel-2);color:var(--ink)}
.nvi{width:14px;height:14px;flex:none;fill:none;stroke:currentColor;
  stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
.navsep{width:1px;height:18px;background:var(--line);margin:0 8px;flex:none}
/* A group is only a fold line for fitNav (app.js): it lays out as its links. */
.navgrp{display:contents}
.navgrp.folded,.navsep.folded,.nvl.folded,.navmore[hidden]{display:none}
.navmore{display:inline-flex;flex:none;margin-left:6px}
button.navmorebtn{background:transparent;min-height:0;font:inherit;font-size:14.5px;
  cursor:pointer}
button.navmorebtn.on{background:var(--accent);border-color:var(--accent);color:var(--on-st);font-weight:600}
.navmorebtn .bscaret{color:inherit;opacity:1}
.navmenu{position:fixed;z-index:40;display:flex;flex-direction:column;gap:2px;
  min-width:220px;padding:6px;background:var(--panel);border:1px solid var(--line);
  border-radius:10px;box-shadow:var(--shadow),0 10px 30px rgba(0,0,0,.18)}
.navmenu[hidden]{display:none}
.navmenu .nvl{font-size:15px;padding:8px 10px}
/* The burgers (r885): three lines, the nav's and the tray's, and nothing else. */
button.navmorebtn .nvi{width:17px;height:17px}
.actsmore{margin-left:0}
header .actsmore > button{min-height:0;padding:5px 9px;background:var(--panel)}
/* The tray's buttons, moved into its menu: one per line, word first. */
.actsmenu > button,.actsmenu > a{justify-content:flex-start;width:100%;text-align:left;
  display:flex;align-items:center;gap:8px}

/* Find (r494, findBox in app.js): a button beside the nav, a panel under the
   header. The panel is fixed and on <body>, so the nav's sideways scroll cannot
   clip it. */
button.navfind{background:transparent;min-height:0;font:inherit;font-size:14.5px;
  cursor:pointer;flex:none}
.findpanel{position:fixed;z-index:40;right:20px;width:min(560px,calc(100vw - 40px));
  max-height:min(70vh,640px);display:flex;flex-direction:column;gap:6px;padding:10px;
  background:var(--panel);border:1px solid var(--line);border-radius:10px;
  box-shadow:var(--shadow),0 10px 30px rgba(0,0,0,.18)}
.findpanel[hidden]{display:none}
.findq{width:100%;font:inherit;font-size:15px;padding:7px 10px}
.findout{overflow-y:auto;display:flex;flex-direction:column;gap:2px}
.findhit{display:flex;flex-direction:column;gap:1px;padding:6px 8px;border-radius:7px;
  color:var(--ink);text-decoration:none}
a.findhit:hover,a.findhit:focus{background:var(--panel-2)}
.findhit.named{border:1px solid var(--line)}
.findtop{display:flex;gap:7px;align-items:baseline;flex-wrap:wrap;min-width:0}
.findkind{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);
  min-width:52px;flex:none}
.findmeant{margin-left:2px;cursor:help}
.findst,.findboard{font-size:12.5px;color:var(--muted)}
.findtt{flex:1 1 0;min-width:0;font-size:14px;overflow:hidden;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.findboard{margin-left:auto;border:1px solid var(--line);border-radius:6px;padding:0 6px}
.findline{font-size:13px;color:var(--muted);padding-left:59px;overflow:hidden;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.findhit.named .findline{display:block}
.findaka{font-size:12.5px;color:var(--muted);padding-left:59px;font-style:italic}
.findalso,.findnone{font-size:12.5px;color:var(--muted);padding:2px 8px}
.navmenu .navsep{width:auto;height:1px;margin:4px 6px}

/* The two surfaces you actually stand on carry a border even when inactive:
   everything else is somewhere you VISIT. */
.nvl.g-work{border-color:var(--line);color:var(--ink)}
.nvl.on{background:var(--accent);border-color:var(--accent);color:var(--on-st);font-weight:600}
.nvl.on .nvi{stroke-width:1.7}
/* A lit link is bold, and bold is wider: pressing Board from Panel moved the pair
   2px sideways (r895). Each word keeps room for its bold self, drawn as a
   zero-height row under it, so lit or not a link is one width. */
.nvt[data-t]{display:inline-grid}
.nvt[data-t]::after{content:attr(data-t);font-weight:600;height:0;visibility:hidden;overflow:hidden}
.grow{flex:1}
.pill{padding:2px 10px;border-radius:999px;border:1px solid var(--line);font-size:14px;color:var(--muted)}
main{padding:16px 20px 90px;max-width:1200px;margin:0 auto}
h2{font-size:13px;text-transform:uppercase;letter-spacing:.09em;color:var(--muted);
  margin:24px 0 8px;font-weight:700}
button{font:inherit;cursor:pointer;border-radius:7px;border:1px solid var(--line);
  background:var(--panel);color:var(--ink);padding:5px 11px}
button:hover{border-color:var(--muted)}
button.primary{background:var(--accent);border-color:var(--accent);color:var(--on-st);font-weight:600}
button.ghost{border-color:transparent;background:transparent;color:var(--muted)}
button.del{color:var(--danger);border-color:transparent;background:transparent}
input,textarea,select{font:inherit;color:var(--ink);background:var(--panel);
  border:1px solid var(--line);border-radius:7px;padding:7px 10px}
input:focus,textarea:focus,select:focus{outline:2px solid var(--accent);outline-offset:-1px;
  border-color:transparent}
textarea{resize:none;overflow:hidden;line-height:1.5}

/* --- tag chips: the routing vocabulary, everywhere --- */
.tags{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.tag{font-size:13px;padding:2px 9px;border-radius:999px;border:1px solid var(--line);
  background:var(--panel-2);color:var(--muted);white-space:nowrap}
.tag.t{border-color:transparent;font-weight:600}
.tag.pick{cursor:pointer;user-select:none}
/* Unselected is an OUTLINE, not a faded chip: opacity .4 put every tag name at
   2.1 to 2.9:1 against the panel (r148). --muted on the panel is 5.9:1. The
   !important beats the tag colour tagChip sets inline. */
/* Tag colours are picked for the dark theme; on white their ink is darkened. */
.tag.t{color:color-mix(in srgb,var(--tc,var(--muted)) var(--tagmix),#000);background:color-mix(in srgb,var(--tc,var(--muted)) 17%,transparent)}
.tag.pick.off{background:transparent;border-color:color-mix(in srgb,var(--tc,var(--muted)) 55%,transparent);
  font-weight:500}
.tag.pick.off:hover{border-color:var(--tc,var(--muted))}
/* Selected in a picker is FILLED: the tag's colour, dark ink on it. */
.tag.pick:not(.off){background:var(--tc,var(--muted));color:#101117}
/* No ceiling. Reads as a state, not as a tag it happens to carry. */
.tag.any{border-style:dashed;font-style:italic}
.tag.ag{background:var(--doing);color:var(--on-st);border-color:transparent;font-weight:600}
.tag.cx{background:var(--q-soft);color:var(--q);border-color:transparent;font-weight:700}
.tag.subp{background:transparent;color:var(--q);border-color:var(--q);font-weight:700}  /* r353 */
.tag.pastceil{border-style:dashed;font-weight:700}
.tag.light{background:var(--todo-soft);color:var(--todo);border-color:transparent;font-weight:700}
.tag.gh{background:var(--accent-soft);color:var(--accent);border-color:transparent}
.tag.lk{color:var(--accent);border-style:dashed}
.tag.pri{background:var(--danger);color:var(--on-st);border-color:transparent;font-weight:700}
/* A phase waiting on an earlier one. Amber while it waits, quiet once it is
   simply the order things were done in. */
.tag.wait{background:var(--doing);color:var(--on-st);border-color:transparent;font-weight:600}
.tag.wait.done{background:none;color:var(--muted);border-color:var(--line);font-weight:400}

/* --- the quick-add bar --- */
.quick{background:var(--panel);border:1px solid var(--line);border-radius:11px;
  padding:11px;margin-bottom:8px;box-shadow:var(--shadow)}
.quick .row{display:flex;gap:8px;align-items:flex-start}
.quick textarea{flex:1;min-height:40px}
.quick .opts{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:9px}
/* r151: the board's new-task box is its input until used (addboxWatch). */
#addbox:not(.open) .addmore{display:none}
.boardbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:10px 0 4px}
button.filterbtn{border-radius:999px;padding:4px 12px;font-size:14px;color:var(--muted);
  background:transparent;border-style:dashed}
button.filterbtn::after{content:" \25BE"}
button.filterbtn[aria-expanded="true"]::after{content:" \25B4"}
button.filterbtn.on{border-style:solid;border-color:var(--todo);color:var(--todo);font-weight:600}
#fleet{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
a.fleetw{text-decoration:none}
a.fleetw:hover{background:var(--todo-soft)}
.filterrow{margin:4px 0 8px}
label.chk{display:flex;align-items:center;gap:6px;font-size:14.5px;color:var(--muted);cursor:pointer}
label.chk input{width:15px;height:15px;accent-color:var(--q);padding:0}
/* r459: the Add box's "waits for" refs — text fields, not checkboxes. r581: one
   box per ticket, each opened by "+", saying the ticket it names beside it. */
.afterbox{display:flex;align-items:center;gap:6px;flex-wrap:wrap;
  font-size:14.5px;color:var(--muted)}
button.afteradd{padding:2px 11px;font-weight:700}
.waitboxes{display:contents}
.waitbox{display:inline-flex;align-items:center;gap:6px;max-width:100%;font-size:13.5px;
  border:1px solid var(--line);border-radius:999px;padding:2px 2px 2px 3px;
  background:var(--panel-2)}
.waitbox input.afterin{width:6ch;min-width:6ch;max-width:16ch;flex:none;box-sizing:content-box;
  height:auto;padding:2px 8px;border-radius:999px}
.waitbox .wt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:18em;
  min-width:0;color:var(--muted)}
.waitbox .wt:empty{display:none}
.waitbox.no{border-color:var(--danger)}
.waitbox.no .wt{color:var(--danger)}
.hint{font-size:14px;color:var(--muted)}

/* --- cards --- */
.card{background:var(--panel);border:1px solid var(--line);border-left-width:5px;
  border-radius:10px;padding:11px 13px;margin-bottom:8px;box-shadow:var(--shadow)}
/* THE LEFT BORDER SAYS WHO THE CARD WAITS ON, and only that (r148, Simon chose A):
   amber  an agent has it          doing
   violet it waits on you          question · open doubt
   pink   for your information    new notice · a board's own note (r238)
   blue   queued for an agent      todo · decided doubt
   green  finished                 done · applied · seen
   grey   set aside                paused · a task waiting on another (r444)
   COMPLEX is not a state, so it is its chip and never the border. --st is the
   state's colour; the ref chip and the discussion names wear it too. The whole
   card is tinted in it (--*-soft) and its outline is a faint mix of it, so the
   colour reads before the border is found (r148, Simon chose B). The chart
   Simon reads is the Colours section of /lexicon: change one, change both. */
.card{--st:var(--line)}
.card.doing{--st:var(--doing);background:var(--doing-soft)}
.card.question,.card.open{--st:var(--q);background:var(--q-soft)}
.card.new{--st:var(--note);background:var(--note-soft)}
.card.todo,.card.decided{--st:var(--todo);background:var(--todo-soft)}
.card.done,.card.applied,.card.seen{--st:var(--accent)}
.card.paused{--st:var(--paused);background:var(--paused-soft)}
.card{border-color:color-mix(in srgb,var(--st) 60%,var(--line));border-left-color:var(--st)}
/* A closed or set-aside card RECEDES — its tint, no shadow — and its text stays
   opaque. Opacity took every line on it to about 2.5:1. No strike-through on a
   closed title either: being on Archive already says it is done, and the line
   only made the text harder to read (r434). */
.card.paused{box-shadow:none}
.card.done,.card.applied,.card.seen{background:var(--accent-soft);box-shadow:none}
.card.done .title{color:var(--ink-2)}
.meta > .tag.ref{color:var(--st);border-color:var(--st);background:transparent;font-weight:700}
.card.todo .meta > .tag.ref,.card.decided .meta > .tag.ref{color:var(--todo);border-color:var(--todo)}
/* A task behind an unfinished ticket is not queued for anyone (r444): it is set
   aside until that one is done, so it wears the pause's grey, not the queue's blue. */
.card.todo.blocked{--st:var(--paused);background:var(--paused-soft);box-shadow:none}
.card.todo.blocked .meta > .tag.ref{color:var(--paused);border-color:var(--paused)}
.head{display:flex;gap:11px;align-items:flex-start}
.title{font-weight:600;flex:1;min-width:0}
.title[contenteditable]:focus{outline:2px solid var(--accent);outline-offset:3px;border-radius:3px}
.acts{display:flex;gap:4px;flex:none;flex-wrap:wrap;justify-content:flex-end}
.acts button{padding:3px 9px;font-size:14px}
.meta{margin-top:6px;font-size:14px;color:var(--muted);display:flex;gap:7px;
  flex-wrap:wrap;align-items:center}
.detail{margin-top:7px;font-size:14.5px;color:var(--ink-2);white-space:pre-wrap;
  max-height:14em;overflow:auto;border-left:2px solid var(--line);padding-left:9px}
.detail.full{max-height:none}
.qbox{margin-top:8px;padding:9px 11px;border-radius:8px;background:var(--panel);
  border:1px solid var(--q)}
.qbox .lbl{font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:var(--q);
  font-weight:700;margin-bottom:4px}
.qbox textarea,.notebox textarea{width:100%;background:var(--bg);min-height:56px}
.notebox{display:flex;gap:7px;margin-top:8px;align-items:flex-start}
/* Opened by the card's Note button, so its own summary is not shown. */
details.addnote > summary{display:none}
.card:has(details.addnote[open]) button.notetoggle{border-color:var(--accent);color:var(--accent)}
.notebox textarea{flex:1;min-height:36px}
/* SCHEDULE (r345): opened by the card's Schedule button, like the note box. */
details.schedfold > summary{display:none}
.card:has(details.schedfold[open]) button.schedtoggle{border-color:var(--accent);color:var(--accent)}
.schedbox{display:flex;gap:7px;margin-top:8px;align-items:center;flex-wrap:wrap}
.schedbox input[type=text]{flex:1 1 200px;min-width:0}
.schedquick{display:inline-flex;gap:4px}
.tag.due{color:var(--paused);border-color:currentColor;font-weight:600}
@media (max-width:720px){
  .schedbox input{font-size:16px}
  .schedbox input[type=datetime-local]{flex:1 1 100%}
}
.opts-row{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap;align-items:flex-start}
.hirebar{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap;align-items:center}
.opts-row textarea{flex:1;min-width:220px;background:var(--bg);min-height:52px}
/* A question asking several decisions: each stem over its own buttons. A pick is
   held, not sent, so it has to look held. */
.optgroups{margin-top:8px}
.optgroup + .optgroup{margin-top:10px}
.optstem{font-size:14.5px;color:var(--muted)}
.optgroups .opts-row{margin-top:4px}
.optgroups .opttail{margin-top:12px}
button.pick[aria-pressed="true"]{border-color:var(--q);background:var(--q-soft);color:var(--q)}
/* A question asked as JSON (r570): a block a question, a button an option with
   its words on it, the agent's pick marked on the option itself. */
.asks{margin-top:8px}
.askq + .askq{margin-top:14px}
.askstem{font-size:15px;font-weight:650;color:var(--ink);line-height:1.35}
.askn{color:var(--q);font-weight:800;margin-right:7px}
.askmany{font-size:12.5px;font-weight:500;color:var(--muted);margin-left:8px;white-space:nowrap}
.askinfo{margin-top:6px;padding:6px 10px;border-left:3px solid var(--q-soft);
  white-space:pre-wrap;overflow-wrap:anywhere;font-size:14px;line-height:1.45;color:var(--ink)}
.askopts{display:flex;flex-direction:column;gap:6px;margin-top:6px}
button.askopt{display:flex;gap:10px;align-items:baseline;width:100%;text-align:left;
  white-space:normal;line-height:1.35;font-weight:500}
button.askopt b{flex:none;min-width:1.2em;color:var(--q)}
.askwords{flex:1;min-width:0}
.askwords small{display:block;margin-top:2px;font-size:13px;color:var(--muted)}
button.askopt[aria-pressed="true"]{border-color:var(--q);background:var(--q-soft)}
.askpick{flex:none;align-self:center;font-size:11px;font-weight:700;color:var(--accent);
  border:1px solid var(--accent);border-radius:999px;padding:0 6px;line-height:16px}
.askrun{display:flex;gap:6px;align-items:flex-start;margin-top:6px}
.askopts .askrun{margin:-2px 0 2px 26px}
.askrun pre{flex:1;min-width:0;margin:0;padding:6px 9px;white-space:pre-wrap;overflow-wrap:anywhere;
  font:13px/1.45 ui-monospace,SFMono-Regular,Menlo,monospace;background:var(--bg);
  border:1px solid var(--line);border-radius:6px;color:var(--ink)}
.askrun pre code{background:none;border:0;padding:0;font:inherit;color:inherit}
.askrun button.askcopy{flex:none;padding:0 10px;font-size:13px;line-height:1.9}
.asks textarea.askwords-box{width:100%;margin-top:6px;background:var(--bg);min-height:40px}
.asks .asksend{margin-top:12px}
.dec{margin-top:5px;font-size:14.5px}
.dec b{color:var(--accent)}

/* --- progress --- */
.prog{margin-top:8px}
.prog .bar{height:6px;border-radius:99px;background:var(--line);overflow:hidden;display:flex}
.prog .bar i{display:block;height:100%;background:var(--accent)}
.prog .bar i.insp{background:var(--line-2);opacity:.9}
.prog .txt{font-size:13.5px;color:var(--muted);margin-top:4px}

/* --- media: the point of the rewrite --- */
.shots{display:flex;gap:8px;flex-wrap:wrap;margin-top:9px}
.shot{position:relative;border:1px solid var(--line);border-radius:8px;overflow:hidden;
  background:var(--panel-2);cursor:zoom-in;max-width:230px}
.shot img{display:block;max-width:230px;max-height:150px;object-fit:cover}
.shot .cap{font-size:13px;color:var(--muted);padding:3px 7px;border-top:1px solid var(--line-2);
  max-width:230px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.shot .cap .fignum{color:var(--ink);font-weight:600}
/* A reference to one of them in the text: a link into the viewer (r617). */
a.figref{color:var(--accent);text-decoration:underline dotted;text-underline-offset:2px;
  cursor:zoom-in;white-space:nowrap}
.shot .kind{position:absolute;top:5px;right:5px;background:rgba(0,0,0,.66);color:#fff;
  font-size:13px;padding:1px 6px;border-radius:4px;letter-spacing:.05em}
/* A sound: the waveform is the picture and the player sits under it, so hearing
   what an agent heard costs no click. The card still opens the viewer. */
.shot.sound{width:230px;cursor:default}
.shot.sound img{width:100%;height:46px;object-fit:cover;cursor:zoom-in}
.shot.sound .nowave{height:46px;display:flex;align-items:center;justify-content:center;
  font-size:13px;color:var(--muted);background:var(--panel-2);cursor:zoom-in}
.shot.sound audio{display:block;width:100%;height:34px}
/* A file has no picture: its name is the tile. It was a broken image. */
.shot.doc{width:180px;padding:22px 10px 10px}
.shot.doc .docname{font:14px/1.35 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--ink);
  overflow-wrap:anywhere;max-height:4.1em;overflow:hidden}
.shot.doc .docsize{font-size:13px;color:var(--muted);margin-top:3px}
.shot.doc .kind{background:var(--line);color:var(--ink)}
.shot.doc .cap{margin:8px -10px -10px}
.notebox textarea.hot{border-color:var(--accent);background:var(--accent-soft)}
/* Screenshots waiting in the new-task box, and where a dragged file will land. */
.tray{display:flex;gap:8px;flex-wrap:wrap;margin-top:9px}
.tray .pend{position:relative;border:1px solid var(--line);border-radius:8px;overflow:hidden;
  background:var(--panel-2, var(--panel))}
.tray .pend.stuck{border-color:var(--bad, #c55)}
.tray img{display:block;height:72px;max-width:140px;object-fit:cover}
.tray .fname{display:block;padding:24px 10px;font-size:14px;color:var(--muted);max-width:140px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tray .for{position:absolute;left:0;right:0;bottom:0;font-size:13px;padding:1px 5px;
  background:rgba(0,0,0,.7);color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tray .x{position:absolute;top:3px;right:3px;min-height:0;width:22px;height:22px;padding:0;
  border-radius:50%;background:rgba(0,0,0,.66);color:#fff;border:0;font-size:15px;line-height:1}
.quick.hot,.card.hot{outline:2px dashed var(--accent);outline-offset:2px}
#lightbox{position:fixed;inset:0;background:rgba(0,0,0,.96);display:none;z-index:100;
  backdrop-filter:blur(6px);
  align-items:center;justify-content:center;cursor:zoom-out;
  padding:16px 16px calc(64px + env(safe-area-inset-bottom))}
#lightbox.on{display:flex}
.lb-stage{max-width:100%;max-height:100%;display:flex;align-items:center;
  justify-content:center}
/* Actual size, with the stage itself doing the panning. A dense comparison grid
   is only readable this way on a narrow screen. */
.lb-stage.zoom{overflow:auto;max-width:100vw;max-height:86vh;cursor:grab;
  align-items:flex-start;justify-content:flex-start;-webkit-overflow-scrolling:touch}
.lb-stage.zoom img{max-width:none;max-height:none;width:auto;height:auto;cursor:grab}
#lightbox img,#lightbox video{max-width:96vw;max-height:82vh;object-fit:contain;
  cursor:default;border-radius:4px}
/* A sound has nothing to fill a screen with but its own waveform. */
.lb-audio{display:flex;flex-direction:column;gap:14px;align-items:center;width:min(760px,92vw)}
.lb-audio img{width:100%;max-height:40vh}
.lb-audio audio{width:100%;color-scheme:dark}   /* the viewer is black in either theme */
/* A text file is read in the viewer, as text, on a page of its own. */
.lb-doc{width:min(860px,calc(100vw - 130px));max-height:84vh;display:flex;flex-direction:column;
  background:#15161a;color:#e9e9e4;border:1px solid #33343c;border-radius:8px;cursor:auto;
  color-scheme:dark}
.lb-dochead{display:flex;gap:12px;align-items:baseline;padding:10px 14px;
  border-bottom:1px solid #33343c;font-size:15px}
.lb-dochead b{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;overflow-wrap:anywhere}
.lb-dochead span{color:#9a9a92}
.lb-dochead a{margin-left:auto;color:#7fc9a1;white-space:nowrap}
.lb-doctext{margin:0;padding:14px 16px;overflow:auto;font:15px/1.5 ui-monospace,SFMono-Regular,
  Menlo,monospace;white-space:pre-wrap;overflow-wrap:anywhere;user-select:text}
.lb-doctext.md{font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  white-space:normal}
.lb-docnote{padding:18px 16px;color:#9a9a92}
@media (max-width:720px){ .lb-doc{width:94vw} }

/* The arrows sit over the edges, big enough to hit with a thumb and out of the
   way of the picture itself. */
.lb-nav{position:absolute;top:50%;transform:translateY(-50%);z-index:2;
  width:52px;height:84px;border:0;border-radius:10px;cursor:pointer;
  background:rgba(255,255,255,.08);color:#fff;font-size:34px;line-height:1;
  display:flex;align-items:center;justify-content:center;padding:0;min-height:0}
.lb-nav:hover{background:rgba(255,255,255,.18)}
.lb-nav.prev{left:8px}
.lb-nav.next{right:8px}
.lb-nav[hidden]{display:none}

.lb-bar{position:absolute;left:0;right:0;bottom:0;display:flex;gap:12px;
  align-items:baseline;justify-content:center;flex-wrap:wrap;
  padding:12px 18px calc(12px + env(safe-area-inset-bottom));
  background:linear-gradient(transparent,rgba(0,0,0,.65));pointer-events:none}
.lb-count{color:#fff;font-size:15px;font-weight:700;opacity:.85;
  font-variant-numeric:tabular-nums}
.lb-cap{color:#e9e9e4;font-size:15px;max-width:70vw;text-align:center}
.lb-hint{color:#9a9a92;font-size:13.5px}

@media (max-width:720px){
  #lightbox img,#lightbox video{max-width:100vw;max-height:74vh}
  .lb-nav{width:46px;height:96px;font-size:30px}
  .lb-nav.prev{left:2px} .lb-nav.next{right:2px}
}

/* --- contexts --- */
.cluster{margin:26px 0 8px;font-size:14px;font-weight:700;letter-spacing:.04em;
  color:var(--ink);border-bottom:1px solid var(--line);padding-bottom:5px}
.ctx{background:var(--panel);border:1px solid var(--line);border-left:4px solid var(--accent);
  border-radius:10px;padding:11px 13px;margin-bottom:8px;box-shadow:var(--shadow)}
.ctx.stale{border-left-color:var(--danger)}
.ctx.superseded{background:var(--bg);box-shadow:none;border-left-color:var(--muted)}
.ctx .sum{color:var(--muted);font-size:14.5px;margin-top:4px}
.ctx .abs{margin-top:7px;font-size:14.5px;white-space:pre-wrap}
.ctx .next{margin-top:6px;font-size:14.5px;color:var(--accent);font-weight:600}
/* THE PAGE OF HANDOVERS (r743): a card a parked session, edged in its persona's
   colour; its sections labelled small, NEXT in the accent since it is the move. */
.ctx.hov{border-left-color:var(--pc,var(--accent))}
.hovhead{display:flex;align-items:center;gap:8px}
/* The intro stays on a phone, where the add bar's hints go (.quick .opts .hint). */
.quick.hovtop .opts .hint{display:inline}
.hovbody.quiet{color:var(--muted);font-size:13.5px}
.hovbody > :last-child{margin-bottom:0}
.hovwho{display:flex;align-items:center;gap:7px;min-width:0;overflow-wrap:anywhere}
.hovat{white-space:nowrap}
.ctx.hov .meta{margin-top:6px}
.hovsec{margin-top:8px}
.hovsec .lbl{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);
  font-weight:700}
.hovbody{font-size:14.5px;overflow-wrap:anywhere}
.hovsec.s-next .hovbody{color:var(--accent);font-weight:600}
.hovresume{margin-top:9px}
.hovresume > summary{cursor:pointer;color:var(--accent);font-weight:600;font-size:14.5px;
  margin:0;text-transform:none;letter-spacing:0}
.hovway{margin-top:9px}
.hovway .resume{overflow-wrap:anywhere;max-height:260px;overflow:auto}
.hovway button{margin-top:6px}
.hovfilter{margin-top:10px;flex-wrap:wrap}
#more{margin:6px 0 18px}
.oldctx{margin-top:22px}
.oldctx > summary{cursor:pointer;font-weight:700;font-size:14px;color:var(--muted)}
.oldctx > .opts{margin-top:10px}
.resume{background:var(--panel-2);border:1px solid var(--line);border-radius:8px;
  padding:9px 11px;margin-top:9px;font:14px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;
  white-space:pre-wrap;color:var(--ink)}

/* --- triage --- */
.issue{background:var(--panel);border:1px solid var(--line);border-radius:9px;
  padding:9px 12px;margin-bottom:7px;display:flex;gap:11px;align-items:flex-start}
.issue.dismissed{background:var(--bg);color:var(--muted)}
.issue .n{font-weight:700;color:var(--muted);flex:none;min-width:46px}
.issue .b{flex:1;min-width:0}
.issue .body{font-size:14px;color:var(--muted);margin-top:4px;max-height:4.4em;overflow:hidden}

.empty{color:var(--muted);font-size:15px;padding:3px 0 8px}
.toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:var(--ink);
  color:var(--bg);padding:9px 20px;border-radius:999px;font-size:15px;opacity:0;
  transition:opacity .18s;pointer-events:none;z-index:120;max-width:90vw;text-align:center}
.toast.show{opacity:1}
details summary{cursor:pointer;color:var(--muted);font-size:13px;text-transform:uppercase;
  letter-spacing:.08em;font-weight:700;margin:24px 0 8px}
code{background:var(--panel-2);border:1px solid var(--line-2);border-radius:4px;padding:1px 5px;
  font:14px ui-monospace,SFMono-Regular,Menlo,monospace}

/* ===================================================================
   TAGS — a tag is a thing with a page, not a chip
   =================================================================== */
.tagcard{background:var(--panel);border:1px solid var(--line);border-left-width:5px;
  border-radius:11px;padding:13px 15px;margin-bottom:10px;box-shadow:var(--shadow)}
.tagcard.dead{border-left-color:var(--danger) !important;background:var(--panel-2)}
.tagcard .head{display:flex;gap:12px;align-items:baseline;flex-wrap:wrap}
.tagname{font:600 15px/1.3 ui-monospace,SFMono-Regular,Menlo,monospace;
  display:flex;align-items:center;gap:7px;flex:1;min-width:0}
.tagname .dot{width:9px;height:9px;border-radius:99px;flex:none}
.nums{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.num{font-size:13.5px;padding:2px 9px;border-radius:999px;border:1px solid var(--line);
  background:var(--panel-2);color:var(--muted);white-space:nowrap;flex:none}
.num.todo{border-color:var(--todo);color:var(--todo);font-weight:600}
.num.doing{border-color:var(--doing);color:var(--doing);font-weight:600}
.num.q{border-color:var(--q);color:var(--q);font-weight:600}
.num.ctx{border-color:transparent;background:var(--accent-soft);color:var(--accent)}
.num.done,.num.empty{background:transparent}
.taglabel{font-weight:600;margin-top:7px}
.tagdesc{color:var(--muted);font-size:15px;margin-top:3px}
.warn{margin-top:9px;padding:8px 11px;border-radius:8px;font-size:14.5px;
  background:var(--q-soft);color:var(--q);border:1px solid var(--q)}
.tagcard.dead .warn{background:transparent;border-color:var(--danger);color:var(--danger)}
.pack{margin-top:10px}
.pack summary{margin:0;text-transform:none;letter-spacing:0;font-size:14.5px;
  font-weight:600;color:var(--accent)}
.pack pre{margin:8px 0 0;background:var(--panel-2);border:1px solid var(--line-2);
  border-radius:8px;padding:11px 13px;white-space:pre-wrap;
  font:14px/1.65 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--ink);
  max-height:22em;overflow:auto}
.tagacts{display:flex;gap:7px;margin-top:11px;flex-wrap:wrap}
.btnlink{font-size:14px;text-decoration:none;color:var(--ink);border:1px solid var(--line);
  border-radius:7px;padding:5px 11px;display:inline-block}
.btnlink:hover{border-color:var(--muted)}
.filterbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:14px 0 4px}
.filterbar .on{background:var(--accent);border-color:var(--accent);color:var(--on-st);font-weight:600}

/* ===================================================================
   PHONE
   Consulting the board from a phone is a first-class use, so every screen
   reflows rather than shrinking. Three rules drive all of it:
     - one column, and actions go BELOW the thing they act on;
     - every tap target at least 44px tall;
     - inputs at 16px, or iOS zooms the page on focus and never zooms back.
   =================================================================== */
@media (max-width:720px){
  body{font-size:15px}
  /* Two rows: identity + counts, then the whole nav. Sharing one row left the
     nav clipped to two and a half tabs. */
  header{padding:8px 12px;gap:6px;row-gap:8px;
    padding-top:calc(8px + env(safe-area-inset-top))}
  h1{font-size:15px;order:-2;flex:1}
  header .grow{display:none}
  header .pill{font-size:13px;padding:2px 8px;order:-1}
  header > button{order:-1;min-height:34px;padding:5px 10px;font-size:14.5px}
  header > .headacts{order:-1;padding:3px;gap:4px}
  .headacts > button{min-height:34px;padding:5px 10px;font-size:14.5px}
  /* Home's Stats and Personas (r332) share the logo's row; the focus button,
     when there is one, takes the row below rather than squeezing them. */
  header > .homelinks{order:-1;gap:6px}
  .homelinks > .btnlink{min-height:34px;padding:5px 10px;font-size:14.5px;
    display:inline-flex;align-items:center}
  header:has(.homelinks) > .focusgo{order:0;flex:1 0 100%;justify-content:center}
  /* Home: the pill restates the lede just under it, and Stats needs its place. */
  header:has(#statsgo) .pill{display:none}
  nav{display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;
    -webkit-overflow-scrolling:touch;flex:1 0 100%;padding-bottom:2px}
  nav::-webkit-scrollbar{display:none}
  nav a{margin:0;flex:none;padding:8px 13px;font-size:15px}
  main{padding:12px 12px calc(72px + env(safe-area-inset-bottom));max-width:100%}
  h2{margin:20px 0 7px}

  input,textarea,select{font-size:16px;padding:9px 11px}
  button{padding:9px 13px;min-height:40px}
  .acts button{padding:8px 12px;font-size:15px;min-height:40px}

  /* One swipeable row instead of three wrapped ones: thirteen tag chips twice
     over pushed every actual task below the fold. */
  .tags{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    -webkit-overflow-scrolling:touch;padding-bottom:3px}
  .tags::-webkit-scrollbar{display:none}
  /* ...except where you opened the chips on purpose: there, all of them. */
  #addbox .tags,.filterrow .tags{flex-wrap:wrap;overflow:visible}
  .meta,.nums,.tagacts{flex-wrap:wrap}
  .quick{padding:10px;border-radius:10px}
  .quick .row{flex-wrap:wrap}
  /* Two lines at rest: at 16px the placeholder needs them, and a clipped
     placeholder is the first thing you see on the phone. */
  .quick .row textarea{flex:1 1 100%;min-height:64px}
  .quick .row button{width:100%;min-height:44px}
  .quick .opts{gap:8px}

  /* Actions belong at the FOOT of the card, not between the title and its
     metadata. `.head` becomes display:contents so its two children join the
     card's own flex flow and can be ordered independently. */
  .card,.ctx,.tagcard{padding:11px 12px;display:flex;flex-direction:column}
  .head{display:contents}
  .card > *,.ctx > *{order:5}
  .head > .title,.head > .tagname{order:1}
  .head > .acts,.head > .nums{order:90}
  .card > .cardstrike{order:91}         /* r779: under the review row it belongs to */
  /* `.tagcard .head` outranks display:contents and stays a wrapping row. There,
     flex:1 with no basis squeezed a title into what its pills left, and an
     unbreakable word ran under them (r397, "Parked contexts" on /upkeep): at its
     own width the title keeps its line and the pills wrap below it. */
  .tagcard .tagname{flex:1 1 auto}
  .acts{width:100%;justify-content:flex-start;margin-top:10px;
    border-top:1px solid var(--line-2);padding-top:10px}
  .acts button{flex:1 1 auto}
  .acts button.del{flex:0 0 auto;min-width:52px}
  .nums{margin-top:9px}
  .detail{max-height:11em;font-size:15px}
  .notebox{flex-wrap:wrap}
  .notebox textarea{flex:1 1 100%}
  .notebox button{flex:1 1 auto}
  .opts-row textarea{flex:1 1 100%;min-width:0}
  .opts-row button{flex:1 1 auto}

  /* A screenshot is the point of looking on a phone: give it the full width. */
  .shots{gap:7px}
  .shot,.shot img,.shot .cap{max-width:100%}
  .shot{width:100%}
  .shot img{width:100%;max-height:52vh;object-fit:contain;background:var(--panel-2)}
  .shot.sound{width:100%}
  .shot.sound img{height:56px;object-fit:cover}

  .issue{flex-wrap:wrap;gap:7px}
  .issue .n{min-width:0}
  .issue .b{flex:1 1 100%}
  .tagacts .btnlink,.tagacts button{flex:1 1 auto;text-align:center;min-height:40px;
    display:flex;align-items:center;justify-content:center}
  .tagacts button.ghost{border-color:var(--line);color:var(--ink)}
  .pack pre{max-height:none;font-size:14.5px}
  .resume{font-size:14px}
  #lightbox{padding:10px}
  .toast{bottom:calc(14px + env(safe-area-inset-bottom));font-size:15px}
}

/* Very narrow: drop the ornament, keep the content. */
@media (max-width:400px){
  .meta{font-size:13.5px;gap:5px}
  .quick .opts .hint{display:none}
  .nums{gap:5px}
}

/* Coarse pointers get the same generosity even on a tablet-width screen. */
@media (pointer:coarse){
  .tag.pick{padding:6px 12px;font-size:14.5px}
  details summary{padding:4px 0}
}

/* --- feedback on write -----------------------------------------------------
   A new task sorts to the BOTTOM of the queue (the order is the real claim
   order, oldest first, and must stay that way). On a phone with thirty tasks
   that means the thing you just made is off-screen, and a toast alone reads as
   "nothing happened". So the card announces itself instead. */
@keyframes landed{
  0%{background:var(--accent-soft);border-left-color:var(--accent)}
  100%{background:var(--panel);border-left-color:var(--line)}
}
.card.landed,.sessrow.landed{animation:landed 2.6s ease-out;border-left-color:var(--accent)}
@media (prefers-reduced-motion:reduce){
  .card.landed,.sessrow.landed{animation:none;border-left-color:var(--accent);
    background:var(--accent-soft)}
}
button.busy{opacity:.65;pointer-events:none}
/* Armed by a first click (twoTap, r506): the next one does it. THE BUTTON DOES
   NOT MOVE OR RESIZE (r533) — the label stays, and only paint changes, so the
   second click lands where the first one did. Nothing in here may change a
   metric: no font-weight, no padding, no border-width. It is amber, not
   --danger, because Close up Shop and Stop now are ALREADY filled danger at
   rest, and an armed button that looks like the one you just clicked says
   nothing. --armed is amber in both themes — a FILL, where --doing is the ink
   light mode writes "doing" in and would land as mud behind white text.
   The class is DOUBLED so the fill beats .stopbtn and .primary, which are as
   specific and sit further down this file: with a single .armed the armed Close
   up Shop kept its red and only the ring changed — which is the whole defect. */
button.armed.armed,button.armed.armed:hover{background:var(--armed);
  border-color:var(--armed);color:var(--on-armed);
  outline:2px solid var(--armed);outline-offset:2px;
  animation:armpulse 1.3s ease-out infinite}
@keyframes armpulse{
  0%{box-shadow:0 0 0 0 var(--armed)}
  70%{box-shadow:0 0 0 8px transparent}
  100%{box-shadow:0 0 0 0 transparent}
}
@media (prefers-reduced-motion:reduce){
  button.armed.armed,button.armed.armed:hover{animation:none;
    box-shadow:0 0 0 4px var(--doing-soft)}
}
/* The toast is the only confirmation for actions that change nothing on screen,
   so give it room to name what happened rather than truncating to one word. */
.toast{max-width:min(520px,92vw);line-height:1.45;padding:11px 20px}
.toast.ok{background:var(--accent);color:var(--on-st);font-weight:600}
.toast.bad{background:var(--danger);color:var(--on-st);font-weight:600}

/* The priority control carries its level in its own colour, so a glance down the
   action rows reads the queue order without reading any text. */
button.pri1{border-color:var(--doing);color:var(--doing);font-weight:600}
button.pri2{background:var(--danger);border-color:var(--danger);color:var(--on-st);font-weight:700}
button.cxon{background:var(--q-soft);border-color:var(--q);color:var(--q);font-weight:700}
/* r583, r585: Simon's verdict on the work. "Reopen · badly done" is in the danger ink so
   it is not pressed for a plain reopen. A review's score wears its end of the scale:
   1-2 danger, 3 muted, 4-5 accent — the same on the button and on its pick. */
button.rebad{color:var(--danger)}
.revrow{display:inline-flex;flex-wrap:wrap;gap:4px}
/* A SCORE COSTS ONE TAP (r813): a close To review wears its five on its foot,
   number over word, in the scale's colours, as /focus draws them. */
.cardscore{display:flex;align-items:stretch;gap:8px;margin-top:12px;padding-top:12px;
  border-top:1px solid var(--line)}
.cardscorelbl{align-self:center;color:var(--q);font-weight:700;margin-right:6px;white-space:nowrap}
.cardscore .revpick{flex:1;display:flex;flex-direction:column;align-items:center;gap:1px;
  padding:6px 4px;font-size:12.5px;line-height:1.15}
.cardscore .revpick b{font-size:18px}
@media (max-width:720px){
  .cardscore{flex-wrap:wrap;gap:6px;order:99}      /* under the buttons, as picked */
  .cardscorelbl{flex-basis:100%}
  .cardscore .revpick{font-size:11px;padding:6px 1px;min-height:48px}
}
button.revpick{font-size:13px;padding:3px 8px}
button.revbtn.s1,button.revbtn.s2,button.revpick.s1,button.revpick.s2{color:var(--danger)}
button.revbtn.s3,button.revpick.s3{color:var(--muted)}
button.revbtn.s4,button.revbtn.s5,button.revpick.s4,button.revpick.s5{color:var(--accent)}
/* The Commissar's grade of a close you scored, and its agreement with you in
   To score's head (r908, gradeLine/gradeAgreement in board.html). */
.gradeline,.gradeagree{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;
  font-size:13px;color:var(--muted);margin-top:6px;line-height:1.4}
.gradeagree{margin-top:4px}
.gradeagree b{color:var(--ink);font-variant-numeric:tabular-nums}
.gradewho{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--sec,var(--doing))}
.gradescore{font-weight:700}
.gradescore.s1,.gradescore.s2{color:var(--danger)}
.gradescore.s3{color:var(--muted)}
.gradescore.s4,.gradescore.s5{color:var(--accent)}
.gradeline.same .gradevs{color:var(--accent)}
.gradewhy{flex-basis:100%;color:var(--ink);opacity:.85}
/* A close just scored in To score, beside the Commissar's grade (r983,
   scoredLine in board.html): two panels, each score in the scale's colour. */
.markcard.scored{border-color:var(--line)}
.scoredline{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;margin-top:8px}
.scoredpane{display:flex;align-items:baseline;gap:6px;padding:6px 12px;border-radius:10px;
  border:1px solid currentColor;min-width:0}
.scoredpane .gradewho{color:inherit}
.scoredpane.s1,.scoredpane.s2{color:var(--danger)}
.scoredpane.s3,.scoredpane.none{color:var(--muted)}
.scoredpane.s4,.scoredpane.s5{color:var(--accent)}
.scoredpane.none{border-style:dashed}
.scoredn{font-size:22px;line-height:1;font-variant-numeric:tabular-nums}
.scoredword{font-size:13px}
.scoredwait{font-size:13px;font-style:italic}
.scoredgap{font-size:13px;color:var(--muted)}
.scoredgap.same{color:var(--accent);font-weight:700}
.scoredline .gradewhy{font-size:13px;line-height:1.4}
.focus-answer .scoredline{margin-top:0}
.focus-answer .scoredn{font-size:28px}
.focus-answer .scoredline .gradewhy{font-size:15px}
.revnext{margin-top:14px}
button.revbtn.s1,button.revbtn.s2,button.revbtn.s3,button.revbtn.s4,button.revbtn.s5,
button.revpick.on{font-weight:700;border-color:currentColor}

/* The board switcher sits in the title, so it must read as part of it rather
   than as a form control dropped into the header. */
.board{color:var(--muted);font-weight:400}
.board{position:relative}
button.boardsel{font:inherit;font-weight:650;color:var(--ink);background:transparent;
  border:1px solid transparent;border-radius:6px;padding:2px 6px;margin-left:2px;
  cursor:pointer;max-width:46vw;display:inline-flex;align-items:center;gap:6px}
button.boardsel:hover{border-color:var(--line);background:var(--panel-2)}
button.boardsel:focus-visible{outline:2px solid var(--accent);outline-offset:-1px}
/* `h1 span` greys every span in the title; these are names, not asides. */
.bsname,.bmname{color:var(--ink)}
.bsname{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bscaret{font-size:.7em;color:var(--muted)}
.bsdot{display:none;width:8px;height:8px;border-radius:50%;background:var(--q);flex:none}
button.boardsel.elsewhere .bsdot{display:inline-block}
@media (max-width:720px){ button.boardsel{padding:4px 6px;min-height:32px} }

/* The open switcher: a grid, one row a board — logo, name, queue, waiting, now,
   workers — in the order and colours of the board's view tabs (r219): blue is
   queued, purple waits on you, amber is in progress, green is sessions up. */
.boardmenu{position:absolute;top:calc(100% + 6px);left:0;z-index:40;
  display:grid;grid-template-columns:auto minmax(9em,1fr) auto auto auto auto auto;
  column-gap:12px;row-gap:2px;padding:8px;min-width:460px;
  /* A list of boards taller than the screen used to run off the bottom of it,
     and the rows down there were on no screen at all — nothing scrolls a menu
     with no height. The 32px twisty made every row 8px taller and pushed the
     last board over that edge at 390px, so the menu keeps itself inside the
     viewport and scrolls what did not fit. overscroll-behavior stops the page
     behind it from taking over the flick. */
  max-height:calc(100dvh - var(--headh, 52px) - 24px);
  overflow-y:auto;overscroll-behavior:contain;
  font-size:15px;font-weight:400;letter-spacing:0;text-transform:none;
  background:var(--panel);border:1px solid var(--line);border-radius:10px;
  box-shadow:var(--shadow),0 10px 30px rgba(0,0,0,.18)}
.boardmenu[hidden]{display:none}
.bmhead{font-size:13px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);
  padding:2px 0 6px;text-align:center}
.bmhead:nth-child(2){text-align:left}
.bmrow{grid-column:1/-1;display:grid;grid-template-columns:subgrid;align-items:center;
  padding:6px 8px 6px 11px;margin:0 -8px;border-radius:7px;color:var(--ink);text-decoration:none;
  position:relative;isolation:isolate}
.bmrow:hover,.bmrow:focus{background:var(--panel-2);outline:none}
/* Neutral, not green: green is the Workers column now, and a green row hid its
   own Workers pill (r219). */
.bmrow:focus-visible{box-shadow:inset 0 0 0 2px var(--muted)}
.bmrow.here,.bmrow.here:hover,.bmrow.here:focus{background:color-mix(in srgb,var(--ink) 10%,var(--panel))}
.bmrow.here .bmname{font-weight:650}
/* THE STRIPE on a row's left says how the board is doing, in one look (r588):
   a small amber flow while a task is on Now (the sessions up ride it as dots, r625) —
   with purple in it as much as its open work is On Hold (--held, 0 to 1); solid
   purple when all of its work waits on you; solid blue when there is work and
   nothing running; nothing when there is no work. paintStripe() picks the class.
   It is the row's own LEFT BORDER, curved round its 7px corners, as the stripe was
   before r588 — Simon: "the little curvature looked way better" (r593). A real
   border cannot take a gradient, so ::before is the row's left end with a 5px left
   border (3px until r623: "a bit thicker to appreciate the colors"), masked down to that border alone — only the left end, square on its
   right: masking the whole box left hairlines round the right-hand corners. */
.stripe{--stripew:5px;--stripr:7px;--stripex:0px;--stripey:0px;--flow:36px}
.stripe::before{content:"";position:absolute;left:var(--stripex);top:var(--stripey);
  bottom:var(--stripey);width:calc(var(--stripr) + var(--stripew));
  border-radius:var(--stripr) 0 0 var(--stripr);
  border-left:var(--stripew) solid transparent;background-origin:border-box;pointer-events:none;
  mask:linear-gradient(#000 0 0) padding-box exclude,linear-gradient(#000 0 0)}
.stripe.st-held::before{background-color:var(--q)}
.stripe.st-idle::before{background-color:var(--todo)}
/* In progress is ALIVE (r593, "not fun enough"): the stripe runs down with a bright
   comet in it, its colour breathes, and a soft glow of the same colour pulses into
   the row behind the logo (::after, under the text by isolation on the row). */
.stripe.st-run{--runc:color-mix(in srgb,var(--q) calc(var(--held, 0) * 100%),var(--doing))}
.stripe.st-run::before{
  background-image:
    linear-gradient(180deg,transparent 0 22%,rgba(255,255,255,.95) 34%,transparent 46% 100%),
    linear-gradient(180deg,var(--doing) 0 calc((1 - var(--held, 0)) * 100%),
                    var(--q) calc((1 - var(--held, 0)) * 100%) 100%);
  background-size:100% var(--flow),100% var(--flow);
  animation:bmflow .9s linear infinite,bmglow 2.4s ease-in-out infinite alternate}
.stripe.st-run::after{content:"";position:absolute;inset:0;border-radius:inherit;z-index:-1;
  pointer-events:none;
  background:linear-gradient(90deg,color-mix(in srgb,var(--runc) 45%,transparent),transparent 26px);
  animation:bmhalo 2.4s ease-in-out infinite alternate}
@keyframes bmflow{from{background-position:0 0,0 0}to{background-position:0 var(--flow),0 var(--flow)}}
@keyframes bmglow{from{filter:brightness(.9) saturate(1)}to{filter:brightness(1.25) saturate(1.4)}}
@keyframes bmhalo{from{opacity:.15}to{opacity:.85}}
@media (prefers-reduced-motion:reduce){
  .stripe.st-run::before,.stripe.st-run::after{animation:none}
  .stripe.st-run::after{opacity:.5}}
/* Home's cards and sub rows wear it too, by the same rule (r623), OVER their own
   left border: that border is the stripe's width, so the stripe sits where the
   grey one was and a board with no work keeps the grey. */
.bcard.stripe{--stripew:5px;--stripr:12px;--stripex:-5px;--stripey:-1px;--flow:72px;
  isolation:isolate}
:is(.subrow,.parkrow).stripe{--stripew:4px;--stripr:9px;--stripex:-4px;--stripey:-1px;
  position:relative;isolation:isolate}
.stripe:is(.bcard,.subrow,.parkrow):is(.st-run,.st-held,.st-idle){border-left-color:transparent}
.bmrow.quiet .bmname{color:var(--muted)}
.bmark.menu{width:24px;height:24px;border-radius:6px;font-size:14px}
.bmname{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* THE SESSIONS UP on a board, a dot each ON its stripe (r625) — Simon: "on the
   left side bar". The stripe's colour is the work; a session with nothing on Now
   is not work in hand, so it is a dot riding the bar, never its colour. Each dot
   is SOLID, in its persona's colour (--pc, PERSONA_MARKS), ringed in the page's
   ground so it reads on any bar; one mid-task flashes gently (r623) — brighter and
   haloed in its own colour, never fading to see-through. A waiting one holds still. */
.stripe > .agdots{position:absolute;z-index:1;pointer-events:none;
  left:calc(var(--stripex) + var(--stripew) / 2);top:50%;transform:translate(-50%,-50%);
  display:flex;flex-direction:column;align-items:center;gap:1.5px}
.agdots[hidden]{display:none}
.agdot{--ring:1.5px;width:5px;height:5px;border-radius:50%;background:var(--pc,var(--live));
  flex:none;box-shadow:0 0 0 var(--ring) var(--bg)}
.agdot.busy{animation:agflash 1.6s ease-in-out infinite;
  animation-delay:calc(var(--i, 0) * -.3s)}
/* r637: one that cannot reach the API is a HOLLOW ring in its colour, still —
   there, holding a task, and not working. Solid-and-flashing is reserved for work. */
.agdot.offline{background:var(--bg);animation:none;
  box-shadow:inset 0 0 0 1.5px var(--pc,var(--live)),0 0 0 var(--ring) var(--bg)}
.bcard.stripe .agdot.offline{box-shadow:inset 0 0 0 2.5px var(--pc,var(--live)),0 0 0 var(--ring) var(--bg)}
.agdot.more{height:12px;border-radius:3px}
.bcard.stripe > .agdots{gap:5px}
.bcard.stripe .agdot{--ring:2px;width:10px;height:10px}
.bcard.stripe .agdot.more{height:20px;border-radius:5px}
/* r745: on a home card each dot is its persona's LOGO, the tile personaMark()
   draws, ringed in its colour. Busy still flashes; offline is the logo dimmed. */
.agdot > .agmark{display:none}
.bcard.stripe .agdot{width:18px;height:18px;border-radius:5px;background:#16171f;
  display:grid;place-items:center;
  box-shadow:0 0 0 1.5px var(--pc,var(--live)),0 0 0 3px var(--bg)}
.bcard.stripe .agdot > .agmark{display:block;width:16px;height:16px}
.bcard.stripe .agdot.busy{animation-name:agflashmark}
.bcard.stripe .agdot.offline{box-shadow:0 0 0 1.5px var(--pc,var(--live)),0 0 0 3px var(--bg)}
.bcard.stripe .agdot.offline > .agmark{opacity:.4}
.bcard.stripe .agdot.more{height:28px;align-items:start;padding-top:1px;
  background:linear-gradient(#16171f 18px,var(--pc,var(--live)) 18px)}
@keyframes agflashmark{
  0%,100%{filter:brightness(1);box-shadow:0 0 0 1.5px var(--pc,var(--live)),0 0 0 3px var(--bg)}
  50%{filter:brightness(1.45);box-shadow:0 0 0 1.5px var(--pc,var(--live)),0 0 0 3px var(--bg),
      0 0 8px 3px var(--pc,var(--live))}}
@keyframes agflash{
  0%,100%{filter:brightness(1);box-shadow:0 0 0 var(--ring) var(--bg)}
  50%{filter:brightness(1.45);
      box-shadow:0 0 0 var(--ring) var(--bg),0 0 7px 2px var(--pc,var(--live))}}
@media (prefers-reduced-motion:reduce){ .agdot{animation:none} }
/* A sub board (r415): a small ↳ before its logo (r424), in the menu and in the header.
   The first column is as wide as the widest lead, so a sub board's logo sits indented
   under its main board's and every name still lines up. */
.bmlead{display:flex;align-items:center;gap:3px}
.bmrow.sub .bmlead{padding-left:4px}
/* A main board's sub boards fold shut, and STAY shut on the next opening (r542).
   .bmrow sets display:grid, which beats the UA's [hidden] rule on specificity —
   same trap the menu itself already carries. */
.bmrow[hidden]{display:none}
/* TWICE the size it shipped at — Simon, on the render: "way too small". It is a
   button you aim at, not a mark you read, so it is now bigger than the board's
   own logo beside it (.bmark.menu, 24px) rather than half of it. The empty slot
   on a childless row grows with it, which is what keeps every logo in line. */
.bmfold{position:relative;flex:none;display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;border-radius:6px;color:var(--muted);
  font-size:22px;line-height:1;cursor:pointer}
.bmfold.none{pointer-events:none}
.bmfold:hover{background:var(--panel);color:var(--ink);box-shadow:inset 0 0 0 1px var(--line)}
/* Folded over the board you are ON: the twisty wears what its hidden row wore. */
.bmfold.holds{color:var(--ink);box-shadow:inset 0 0 0 1px var(--line)}
.bmsub{flex:none;color:var(--muted);font-size:.85em;font-weight:400;line-height:1}
.board>.bmsub{margin-left:6px}
.board>.bmsub+.bmark.head{margin-left:2px}
.bmn{min-width:3.2em;text-align:center;font-size:15px;font-weight:700;border-radius:999px;
  padding:1px 8px}
.bmn:empty::before{content:"\2014";color:var(--line);font-weight:400}
.bmn.needs:not(:empty){color:var(--q);background:var(--q-soft)}
.bmn.note:not(:empty){color:var(--note);background:var(--note-soft)}
.bmn.queue:not(:empty){color:var(--todo);background:var(--todo-soft)}
.bmn.now:not(:empty){color:var(--doing);background:var(--doing-soft)}
.bmn.live:not(:empty){color:var(--live);background:var(--live-soft)}
/* r574: the second count beside On Hold — tasks waiting on another task. Smaller,
   hollow and grey like the tab's (.jumpsub): seen, not acted on. Alone in the
   cell, it takes no purple fill: there is nothing there for you. */
.subn{display:inline-block;font-size:11px;font-weight:600;padding:0 5px;min-width:16px;
  line-height:16px;text-align:center;border-radius:999px;color:var(--muted);
  background:transparent;border:1px solid color-mix(in srgb,var(--muted) 70%,transparent);
  vertical-align:middle}
/* Pinned to the cell's corner, not beside the number: beside it, the one wide
   cell widened the whole column, and on a phone that came out of the board names. */
.bmn.needs{position:relative}
.bmn .subn{position:absolute;top:-7px;right:-5px;font-size:10px;line-height:13px;
  padding:0 3px;min-width:13px;background:var(--panel)}
.bmn.needs.behindonly{background:transparent}
.bmn.behindonly .subn{position:static;font-size:11px;line-height:16px;padding:0 5px;min-width:16px}
/* Each count is a way in: to that board's Queue, Waiting, Now or Workers. */
.bmn[data-href]{cursor:pointer}
.bmn[data-href]:hover{box-shadow:inset 0 0 0 1px currentColor}
@media (max-width:720px){
  .boardmenu{position:fixed;left:8px;right:8px;top:calc(var(--headh, 52px) + 4px);min-width:0;
    grid-template-columns:auto minmax(0,1fr) auto auto auto auto auto;column-gap:3px}
  .bmhead{letter-spacing:0;font-size:11px}
  /* The box is 32px everywhere now, so it IS the tap target and the invisible
     ::after that used to grow one is gone. That is 16px straight out of the
     first column, which every row shares — and at 390px it took the board
     NAMES down to "S…", where Shadow, Slides and SynAndKaya are one letter.
     Bought back, and then some, from the five count columns: the gap between
     them, their padding, and the header labels that were what actually set
     their width ("WORKERS" is wider than any count it sits over). Nothing
     there is read for its size; the names are. */
  .bmn{min-width:2em;padding:1px 4px}
  .bmrow{padding:10px 4px 10px 7px;margin:0 -4px}
  .bmfold{border-radius:8px}
  .bmrow.sub .bmlead{padding-left:0}
}

/* The meter switch: two states, one visibly chosen. Small, because it sits in a
   header, but never below a comfortable tap target on a phone. */
.meterswitch, .dmode{display:inline-flex;border:1px solid var(--line);border-radius:8px;
  overflow:hidden;vertical-align:middle}
.meterswitch button, .dmode button{border:0;border-radius:0;background:var(--panel);color:var(--muted);
  padding:4px 10px;font-size:14px;min-height:0;font-weight:600;letter-spacing:.02em}
.meterswitch button + button, .dmode button + button{border-left:1px solid var(--line)}
.meterswitch button.on, .dmode button.on{background:var(--accent);color:var(--on-st)}
.meterswitch button:not(.on):hover,
.dmode button:not(.on):hover{background:var(--panel-2);color:var(--ink)}
/* .dmode is /doctrine's In place | Proposal: the same look, not the $/tok switch. */
@media (max-width:720px){ .meterswitch button, .dmode button{padding:7px 13px;font-size:15px;min-height:36px} }

/* A tag someone is working right now. It reads as activity, not as an error —
   being unable to claim it is the rule doing its job. */
.num.held{border-color:transparent;background:var(--doing);color:var(--on-st);font-weight:700}

/* Recently done: a scannable line, not a card. The point is to take it in at a
   glance and click through only when something looks worth reading. */
.recent{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;
  padding:8px 12px;border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:8px;margin-bottom:6px;background:var(--panel)}
.recent:hover{border-color:var(--muted)}
a.reclink{font:600 14px ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--accent);
  text-decoration:none;border:1px solid var(--accent);border-radius:999px;
  padding:1px 9px;flex:none}
a.reclink:hover{background:var(--accent);color:var(--on-st)}
.rectitle{flex:1;min-width:0;font-size:15px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.recmeta{display:flex;gap:6px;align-items:center;flex-wrap:wrap;font-size:13.5px;
  color:var(--muted)}
@media (max-width:720px){
  .recent{gap:7px}
  .rectitle{flex:1 1 100%;white-space:normal}
  a.reclink{min-height:28px;display:inline-flex;align-items:center}
}

/* Why nothing is happening. Loud enough to answer the question before it is
   asked, quiet enough not to read as a crash. */
.quick.alarm{border-color:var(--doing);background:var(--doing-soft)}
.quick.alarm b{color:var(--doing)}
.quick.alarm .resume{margin-top:8px;background:var(--panel)}

/* The tick-off on a recent row, and the header's clear-all. Deliberately quiet:
   nothing here deletes anything. */
button.recx{border:0;background:transparent;color:var(--muted);padding:0 6px;
  min-height:0;font-size:16px;line-height:1;flex:none;cursor:pointer}
button.recx:hover{color:var(--danger)}
h2 button.ghost{font-size:13px;text-transform:none;letter-spacing:0;padding:2px 8px;
  margin-left:8px;min-height:0;vertical-align:middle;border-color:var(--line)}
/* Session slots: the count you read first, and the two buttons that change it. */
.slots{display:inline-flex;align-items:center;gap:0;border:1px solid var(--line);
  border-radius:8px;overflow:hidden;margin-left:auto}
.slots button{border:0;border-radius:0;background:var(--panel);color:var(--ink);
  padding:4px 11px;min-height:0;font-size:15px;font-weight:700;line-height:1.2}
.slots button:disabled{opacity:.3;cursor:not-allowed}
.slots button:hover:not(:disabled){background:var(--accent);color:var(--on-st)}
.slots .n{padding:4px 12px;font-size:14.5px;font-weight:600;white-space:nowrap;
  border-left:1px solid var(--line);border-right:1px solid var(--line)}
@media (max-width:720px){ .slots button{padding:8px 15px;min-height:38px} }

.quick.headline{display:flex;align-items:baseline;flex-wrap:wrap;gap:2px}
.quick.headline b{font-size:15px}

/* ===================================================================
   SECTION DIVISIONS
   The board was one column of cards with small-caps labels between them, so
   where a section ended had to be inferred from the cards themselves. A header
   is now a block: a heavy edge in the same colour as the cards it introduces,
   the name at a readable size, a count, and — for the channels that exist for
   Simon — one line saying what the channel is for.
   =================================================================== */
.sect{--st:var(--muted);margin:34px 0 12px;padding:10px 14px;border-radius:10px;
  border:1px solid var(--line);border-left:5px solid var(--st);
  background:var(--panel-2)}
.sect:first-child{margin-top:6px}
.sect-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.sect-name{font-size:15.5px;font-weight:700;letter-spacing:.01em;color:var(--ink)}
.sect-n{font-size:14px;font-weight:700;padding:1px 10px;border-radius:999px;
  background:var(--line);color:var(--ink);min-width:26px;text-align:center}
.sect-hint{font-size:14px;color:var(--muted);margin-top:4px;line-height:1.45}
.sect .ghost{margin-left:auto}
.sect{border-color:color-mix(in srgb,var(--st) 60%,var(--line));border-left-color:var(--st)}

/* Each channel wears the colour of its cards, so the eye pairs header to block
   without reading either. */
/* The tones follow the card border (r148): waiting on you is violet, whatever
   kind of ticket it is. A notice asks nothing, so it is pink (r238). */
.sect.question,.sect.doubt{--st:var(--q);background:var(--q-soft)}
.sect.know{--st:var(--note);background:var(--note-soft)}
.sect.doing   {--st:var(--doing);background:var(--doing-soft)}
.sect.todo{--st:var(--todo);background:var(--todo-soft)}
.sect.paused  {--st:var(--paused);background:var(--paused-soft)}
.sect.done    {--st:var(--accent);background:var(--accent-soft)}
.sect.liv     {--st:var(--live);background:var(--live-soft)}
.sect.mark    {--st:var(--q);background:var(--q-soft)}
:is(.sect.know,.sect.question,.sect.doubt,.sect.doing,.sect.todo,.sect.paused,.sect.done,.sect.liv,.sect.mark) .sect-name{color:var(--st)}
:is(.sect.know,.sect.question,.sect.doubt,.sect.doing,.sect.todo,.sect.paused,.sect.done,.sect.liv,.sect.mark) .sect-n{background:var(--st);color:var(--on-st)}

/* A zero state sits INSIDE its section's colour, so an empty channel still
   reads as that channel rather than as a stray line of grey text. */
.sect + .empty{margin:-6px 0 4px;padding:0 15px 2px;border-left:5px solid transparent}

/* Cards belong to the header above them: pull them in slightly so the group
   reads as one block with a lip, not as two unrelated things. */
.sect + .card, .sect + .empty + .card{margin-top:0}

@media (max-width:720px){
  .sect{margin:26px 0 10px;padding:9px 12px;border-left-width:6px}
  .sect-name{font-size:15px}
  .sect-hint{font-size:14.5px}
}

/* A doubt asks something. The question is the headline; the reasoning behind it
   is context and reads as context. */
/* A prose headline — a doubt's question, a notice's finding. Big enough to be
   the first thing read, capped so it cannot become the whole card. */
.title.q{font-size:15px;line-height:1.45;color:var(--ink);
  display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.title.q.full{-webkit-line-clamp:unset}
/* WHAT IT OFFERS, under what it asks (r357). The options used to run on inside
   the headline, which is clamped at four lines and stopped in the middle of one
   — and the only place their words existed otherwise was a button's tooltip,
   which a phone has not got. One paragraph each, a line skip between, never
   clamped: on a card you must act on, the choice is the card. */
.optlist{margin-top:8px;font-size:14.5px;color:var(--ink-2)}
.optlist .mdp{margin:0 0 .5em;padding-left:10px;border-left:2px solid var(--line-2)}
.optlist .mdp:last-child{margin-bottom:0}
/* The reasoning: one line until asked for. A doubt's job is to pose a choice;
   the argument behind it is reference material, and with a button that opens the
   real thing it is rarely the fastest way to decide. */
details.why{margin-top:9px}
details.why > summary{margin:0;text-transform:none;letter-spacing:0;font-size:14px;
  font-weight:600;color:var(--muted);display:flex;gap:8px;align-items:baseline;
  padding:2px 0}
details.why > summary:hover{color:var(--ink)}
details.why .whypeek{font-weight:400;color:var(--muted);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}
details.why[open] .whypeek{display:none}
.whybody{font-size:14.5px;color:var(--muted);line-height:1.55;margin-top:6px;
  padding-left:11px;border-left:2px solid var(--doing);white-space:pre-wrap}
/* r252: what a question card folds away is still read in full when opened —
   at reading size and ink, not as a muted afterthought. */
details.note .whybody{font-size:15px;color:var(--ink);border-left-color:var(--accent);
  padding:8px 11px;background:var(--panel);border-radius:0 8px 8px 0}
details.talk > .thread{margin-top:6px}
details.talk > .thread > .lbl{display:none}
details.note > summary::before,details.talk > summary::before{content:"\25b8";
  display:inline-block;transition:transform .15s}
details.note[open] > summary::before,details.talk[open] > summary::before{transform:rotate(90deg)}

/* Where a doubt's evidence came from. Small, and it links back to the task that
   produced it so the full account is one tap away. */
.frommeta{font-size:13.5px;color:var(--muted);margin-top:9px;display:flex;
  align-items:center;gap:6px;flex-wrap:wrap}

/* What a task behind an unfinished phase waits for (r444), in words, under its
   title. Marked in the question colour when the head of that line is yours. */
.waitline{font-size:14px;color:var(--ink-2);margin-top:8px;padding:6px 10px;
  border-left:3px solid var(--paused);background:var(--panel-2);border-radius:4px}
.waitline.you{border-left-color:var(--q);background:var(--q-soft)}
.waitline .reclink{font-size:14px}

/* The micro program. Deliberately the loudest control on the card: seeing the
   thing is what makes a taste call answerable at all. */
.viewbar{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
button.open{display:inline-flex;align-items:center;gap:9px;padding:9px 15px;
  font-size:14.5px}
button.open .openwhat{font:13.5px/1 ui-monospace,SFMono-Regular,Menlo,monospace;
  background:rgba(0,0,0,.22);padding:3px 7px;border-radius:5px}
@media (max-width:720px){
  .viewbar button.open{flex:1 1 auto;justify-content:center;min-height:46px}
}

/* An inspectable surface: a name, what it lets you judge, and one button that
   opens it on the machine with the checkout. */
.labrow{display:flex;gap:12px;align-items:center;background:var(--panel);
  border:1px solid var(--line);border-left:4px solid var(--accent);
  border-radius:10px;padding:11px 13px;margin-bottom:7px;box-shadow:var(--shadow)}
.labbody{flex:1;min-width:0}
.labname{font:600 15px/1.3 ui-monospace,SFMono-Regular,Menlo,monospace}
.lababout{color:var(--muted);font-size:14.5px;margin-top:3px}
/* A STAR (r803, starButton in app.js): pins the row's lab, tool or action to the
   Panel's quick actions. An outline until pressed, then filled in amber. */
.starbtn{display:inline-grid;place-items:center;width:38px;height:38px;padding:0;flex:none;
  border-radius:10px;background:transparent;border:1px solid var(--line);color:var(--muted);
  cursor:pointer}
.starbtn .nvi{width:18px;height:18px;stroke-width:1.5}
.starbtn:hover{color:var(--s4);border-color:var(--s4)}
.starbtn.on{color:var(--s4);border-color:color-mix(in srgb,var(--s4) 55%,transparent);
  background:color-mix(in srgb,var(--s4) 14%,transparent)}
.starbtn.on .nvi{fill:currentColor}
@media (max-width:720px){
  .labrow{flex-wrap:wrap}
  .labrow .open{flex:1 1 calc(100% - 58px);justify-content:center;min-height:44px}
  .starbtn{width:44px;height:44px}
  .actbtns .starbtn{flex:none}
}

/* The Actions tab (r599): a labrow with the command it runs always in view, since
   Keep is a yes to exactly that command. A proposed one is greyed until kept. */
.actrow.proposed{border-left-color:var(--line);opacity:.82}
.actrow.error{border-left-color:var(--doing)}
.actrow.lib{border-left-color:var(--line)}
.actcmd{display:block;font:13px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;
  background:var(--bg);border:1px solid var(--line);border-radius:6px;padding:4px 8px;
  margin-top:6px;overflow-wrap:anywhere}
.meta .actcmd{display:inline-block;margin-top:0}
.actfold{margin-top:6px}
.actfold summary{cursor:pointer;color:var(--muted);font-size:14px}
.actprompt{white-space:pre-wrap;font-size:14.5px;margin-top:4px}
.actlog{white-space:pre-wrap;font-size:12.5px;max-height:260px;overflow:auto;margin:4px 0 0;
  background:var(--bg);border:1px solid var(--line);border-radius:6px;padding:6px 8px}
.tag.actok{color:var(--done,#1f9d55);border-color:currentColor}
.tag.actrun{color:var(--accent);border-color:currentColor}
.actbtns{display:flex;gap:8px;align-items:center}
@media (max-width:720px){
  .actbtns{flex:1 1 100%}
  .actbtns button{flex:1;justify-content:center;min-height:44px}
}

/* The default reply. It comes first and it is the loud one, because "what I
   wrote" is the answer that fits every question — the lettered options are the
   shortcut, not the other way round. */
button.mine{order:-1}
button.mine:disabled{opacity:.45;cursor:default;pointer-events:none}
@media (max-width:720px){ .opts-row button.mine{flex:1 1 100%} }
/* Bad question (r869): a verdict on the asking, set apart from the answers above it. */
.opts-row.badq{align-items:center;border-top:1px dashed var(--line);padding-top:8px}
.opts-row.badq .hint{color:var(--muted)}
@media (max-width:720px){ .opts-row.badq .hint{flex:1 1 100%} }

/* No tags: nobody is equipped for it and nobody will be told what to read. It
   should look unfinished, because it is. */
.tag.untagged{border-color:var(--danger);color:var(--danger);font-weight:700;
  letter-spacing:.03em}

/* A word the project has defined. Marked, not shouted: a dotted underline you
   can ignore while reading and tap when you cannot place it. */
.term{border-bottom:1px dashed var(--accent);cursor:help;
  text-decoration:none;color:inherit}
.term:hover{background:var(--accent-soft);border-bottom-style:solid}
@media (pointer:coarse){ .term{border-bottom-width:2px} }

/* A lexicon entry: the word, what it means in one line, and where it is really
   defined so the definition here never becomes the authority. */
.termrow{background:var(--panel);border:1px solid var(--line);
  border-left:4px solid var(--accent);border-radius:10px;padding:11px 13px;
  margin-bottom:7px;box-shadow:var(--shadow)}
.termhead{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}
.termword{font:700 15.5px/1.3 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}
.termshort{margin-top:4px;font-size:15px;line-height:1.5}
.termlong{margin-top:6px;font-size:14.5px;color:var(--muted);white-space:pre-wrap}
.termsrc{margin-top:6px;font:13.5px ui-monospace,SFMono-Regular,Menlo,monospace;
  color:var(--muted)}

/* Upkeep: what the machine already sees, under what needs judging. */
.projkind{display:flex;gap:9px;align-items:baseline;flex-wrap:wrap;margin-bottom:8px;
  font-size:15px;color:var(--muted)}
.finding{font-size:14.5px;line-height:1.5;margin-bottom:5px}
.finding b{color:var(--ink)}
.flevel{display:inline-block;min-width:44px;font-size:13px;font-weight:700;
  text-transform:uppercase;letter-spacing:.04em;margin-right:7px}
.flevel.stale,.flevel.error{color:var(--danger)}
.flevel.gap{color:var(--doing)}
.flevel.note{color:var(--muted)}
.fnames{font:13.5px ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--muted);
  margin:2px 0 0 51px}
.tagcard.ok{box-shadow:none}
@media (max-width:720px){ .tagacts button{flex:1 1 auto;min-height:44px} }

/* THE STATS PAGE. One number per cell, big enough to read across a room, with
   the words that make it mean something underneath. A figure with no unit and
   no qualifier is a number you cannot check, so every cell carries both. */
.statband{margin:18px 0 26px}
.figs{display:grid;gap:12px;margin-top:12px;
  grid-template-columns:repeat(auto-fill,minmax(190px,1fr))}
.fig{background:var(--panel);border:1px solid var(--line);border-radius:10px;
  padding:14px 16px}
.fig-n{font-size:30px;font-weight:700;line-height:1.05;letter-spacing:-.5px}
.fig-l{margin-top:4px;font-size:15px;color:var(--text)}
.fig-h{margin-top:5px;font-size:13.5px;color:var(--muted);line-height:1.45}
.statfoot{display:block;margin-top:6px}
.stattable{overflow-x:auto;margin-top:12px;background:var(--panel);
  border:1px solid var(--line);border-radius:10px}
.stattable table{border-collapse:collapse;width:100%;font-size:15px}
.stattable th,.stattable td{padding:8px 12px;border-bottom:1px solid var(--line-2);
  text-align:left;white-space:nowrap;font-weight:400}
.stattable tr:first-child th{color:var(--muted);font-size:13.5px;font-weight:600}
.stattable th a{color:inherit;text-decoration:underline;text-decoration-color:var(--line);text-underline-offset:3px}
.stattable th a.on{font-weight:700;text-decoration-color:currentColor}
.stattable td.statnum{text-align:right;font-variant-numeric:tabular-nums}
.stattable tr:first-child th:not(:first-child){text-align:right}
.stattable tr.total th,.stattable tr.total td{font-weight:700;border-bottom:0}
/* A lab's trials side by side (r475, board.html trialsSection). On a phone a row
   of nine columns is a sideways scroll nobody does: each trial is a block, each
   cell a line that names its column (td[data-label]). */
.trials td a{color:inherit}
.trials .tpersona{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
/* Ten columns since Persona (r505): the model is the one cell that may wrap, or the
   judgement is pushed off a desk's edge. */
.trials td:nth-child(2){white-space:normal}
.trials .nowrap{white-space:nowrap}
.trials tr:first-child th:is(:nth-child(2),:nth-child(3),:last-child){text-align:left}
.trials td:first-child a{font-weight:600}
.trials .trun{margin-left:8px;font-size:12.5px;padding:1px 8px;border-radius:999px;
  background:var(--doing-soft);color:var(--doing);font-weight:600}
.trials .hint{color:var(--muted)}
.trials tr:last-child td{border-bottom:0}
@media (max-width:720px){
  .trials tr:first-child{display:none}
  .trials table,.trials tbody,.trials tr,.trials td{display:block;width:auto}
  .trials tr{padding:8px 0;border-bottom:1px solid var(--line)}
  .trials tr:last-child{border-bottom:0}
  .trials td{border:0;padding:2px 12px;white-space:normal;text-align:left}
  .trials td.statnum{text-align:left}
  .trials td:not(:first-child)::before{content:attr(data-label) " ";color:var(--muted);
    display:inline-block;min-width:118px}
  .trials td:first-child{font-size:16px;padding-bottom:4px}
}

/* WHERE IT WENT — /stats' breakdown. Eight categorical slots in a fixed order,
   validated for colour-blind separation against the panel in both themes (the
   dataviz reference palette); a ninth bucket is grey "other", never a new hue.
   Names and values stay in ink: the swatch beside them carries the identity. */
:root{--s1:#2a78d6;--s2:#eb6834;--s3:#1baf7a;--s4:#eda100;--s5:#e87ba4;
  --s6:#008300;--s7:#4a3aa7;--s8:#e34948;--s-other:#b4b3ab}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --s1:#3987e5;--s2:#d95926;--s3:#199e70;--s4:#c98500;--s5:#d55181;
  --s6:#008300;--s7:#9085e9;--s8:#e66767;--s-other:#5e5e58}}
:root[data-theme="dark"]{--s1:#3987e5;--s2:#d95926;--s3:#199e70;--s4:#c98500;
  --s5:#d55181;--s6:#008300;--s7:#9085e9;--s8:#e66767;--s-other:#5e5e58}
.uctl{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center;margin-top:12px}
.useg{display:inline-flex;flex-wrap:wrap;max-width:100%;border:1px solid var(--line);
  border-radius:9px;overflow:hidden;background:var(--panel)}
.useg button{font:inherit;font-size:15px;padding:7px 11px;border:0;cursor:pointer;
  background:transparent;color:var(--ink);border-left:1px solid var(--line-2);
  min-height:36px;white-space:nowrap}
.useg button:first-child{border-left:0}
.useg button.on{background:var(--todo-soft);color:var(--ink);font-weight:700;
  box-shadow:inset 0 0 0 2px var(--todo),inset 0 -4px 0 var(--todo)}
.ucrumbs{display:flex;flex-wrap:wrap;gap:4px 6px;align-items:baseline;margin:16px 0 4px;
  font-size:15px}
.ucrumbs button{font:inherit;border:0;background:none;padding:0;cursor:pointer;
  color:var(--muted);text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:var(--line)}
.ucrumbs b{font-weight:700}
.ucrumbs .usum{flex-basis:100%;font-size:14.5px;color:var(--muted)}
.uchart{position:relative;margin-top:10px;background:var(--panel);
  border:1px solid var(--line);border-radius:10px;padding:12px 12px 6px}
.uchart svg{display:block;width:100%;height:auto;overflow:visible}
.uchart .grid{stroke:var(--line-2);stroke-width:1}
.uchart .axis{fill:var(--muted);font-size:13px;font-variant-numeric:tabular-nums}
.uchart .hit{fill:transparent;cursor:default}
/* /stats' work time against tokens (r486): a Chart.js scatter sizes to .wplot. */
.wplot{position:relative;height:320px}
@media (max-width:620px){ .wplot{height:260px} }
.wmodel{display:inline-flex;flex-wrap:wrap;align-items:center;gap:2px 6px;
  white-space:normal}
.wmodel .wtag{color:var(--muted);font-size:13.5px}
@media (max-width:620px){ .wmodel .wtag{flex-basis:100%;padding-left:16px} }
.tag.worked{color:var(--muted)}
.ulegend{display:flex;flex-wrap:wrap;gap:4px 14px;margin:8px 2px 4px;font-size:14.5px}
.ulegend span{display:inline-flex;align-items:center;gap:6px}
.usw{display:inline-block;width:10px;height:10px;border-radius:3px;flex:none}
.utip{position:absolute;z-index:5;pointer-events:none;background:var(--panel);
  border:1px solid var(--line);border-radius:8px;box-shadow:var(--shadow);
  padding:8px 10px;font-size:14px;line-height:1.5;min-width:160px}
.utip div{display:flex;align-items:center;gap:6px}
.utip .v{margin-left:auto;padding-left:12px;font-variant-numeric:tabular-nums}
.urows{margin-top:12px;background:var(--panel);border:1px solid var(--line);
  border-radius:10px}
.urow{display:grid;grid-template-columns:minmax(150px,1.3fr) minmax(80px,2fr) 9.5em;
  gap:4px 14px;align-items:center;padding:9px 12px;border-bottom:1px solid var(--line-2)}
.urow:last-child{border-bottom:0}
.urow .un{display:flex;gap:8px;align-items:center;min-width:0}
.urow .un button,.urow .un a,.urow .un span.nm{font:inherit;font-size:14.5px;border:0;
  background:none;padding:0;color:var(--ink);text-align:left;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.urow .un button{cursor:pointer;text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:var(--line)}
.urow .un a{text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:var(--line)}
/* Beside a board's bucket: that board's own stats page (r400). Quieter than the
   name, which splits in place. */
.urow .un a.ugo{color:var(--muted);font-size:13px;flex:none;text-decoration:none}
.urow .un a.ugo:hover{color:var(--ink)}
.urow .ubar{height:10px;border-radius:0 4px 4px 0;min-width:2px}
.urow .uv{text-align:right;font-variant-numeric:tabular-nums;font-size:14.5px;
  font-weight:650;white-space:nowrap}
.urow .uv small{font-weight:400;color:var(--muted);margin-left:6px}
.urow .uh{grid-column:1/-1;font-size:13.5px;color:var(--muted);margin:-2px 0 0 18px;
  line-height:1.45}
@media (max-width:620px){
  .urow{grid-template-columns:1fr auto}
  .urow .ubar{grid-column:1/-1;grid-row:2}
  .urow .uh{grid-row:3;margin-left:0}
  .useg button{font-size:15px;min-height:40px}
}
@media (max-width:520px){
  .figs{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:9px}
  .fig{padding:11px 12px}
  .fig-n{font-size:24px}
}

/* THE VIEW BAR. Queue, Waiting, Notifications, Now, Archive — the five places the board is,
   sticky under the header, counts on them. They were small grey pills and read
   as tags: nobody could tell they were buttons, or which one they were on. So
   they are BUTTONS — equal width, dark ink, tall enough for a thumb — and the
   one you are on is filled solid, not a shade off its neighbours. */
.jump{position:sticky;top:var(--headh,52px);z-index:15;display:flex;gap:8px;
  overflow-x:auto;padding:10px 0 12px;margin:10px 0 2px;
  background:var(--bg);border-bottom:1px solid var(--line);
  scrollbar-width:none}
.jump::-webkit-scrollbar{display:none}
.jumpbtn{flex:1 1 0;display:flex;align-items:center;justify-content:center;
  gap:9px;white-space:nowrap;min-height:44px;padding:8px 14px;
  cursor:pointer;font:inherit;font-size:15.5px;font-weight:600;
  text-decoration:none;color:var(--ink);background:var(--panel);
  border:1px solid var(--line);border-left-width:5px;
  border-left-color:var(--muted);border-radius:10px;
  box-shadow:0 1px 2px rgba(0,0,0,.08)}
.jumpbtn:hover{border-color:var(--muted);background:var(--panel-2)}
.jumpn{font-size:14px;font-weight:700;padding:1px 8px;border-radius:999px;
  background:var(--line);color:var(--ink);min-width:22px;text-align:center}
/* r202: the one you are on is no longer filled white — it wears its OWN colour
   harder (a deeper tint, a full-colour ring) and a bar underneath points at it. */
.jumpbtn{position:relative}
.jumpbtn.here{--st:var(--ink);background:color-mix(in srgb,var(--st) var(--heremix),var(--panel));
  color:var(--ink);border-color:var(--st);box-shadow:inset 0 0 0 1px var(--st)}
.jumpbtn.here::after{content:"";position:absolute;left:18%;right:18%;bottom:-9px;height:4px;
  border-radius:4px;background:var(--st)}
.jumpbtn.here .jumpn{background:var(--st);color:var(--on-st)}

/* Same colour language as the section headers, so a chip and its block are
   obviously the same thing. */
.jumpbtn.doubt,.jumpbtn.question{border-left-color:var(--q)}
.jumpbtn.doubt .jumpn,.jumpbtn.question .jumpn{background:var(--q-soft);color:var(--q)}
.jumpbtn.know{border-left-color:var(--note)}
.jumpbtn.know .jumpn{background:var(--note-soft);color:var(--note)}
.jumpbtn.todo    {border-left-color:var(--todo)}
.jumpbtn.todo .jumpn{background:var(--todo-soft);color:var(--todo)}
.jumpbtn.doing   {border-left-color:var(--doing)}
.jumpbtn.doing .jumpn{background:var(--doing-soft);color:var(--doing)}
.jumpbtn.paused  {border-left-color:var(--paused)}
.jumpbtn.done    {border-left-color:var(--accent)}
.jumpbtn.here .jumpn.jumpn{background:var(--st);color:var(--on-st)}
/* r196: each wears its colour whole, tint and outline, like its cards. */
.jumpbtn:is(.doubt,.question){--st:var(--q);--stsoft:var(--q-soft)}
.jumpbtn.know{--st:var(--note);--stsoft:var(--note-soft)}
.jumpbtn.todo{--st:var(--todo);--stsoft:var(--todo-soft)}
.jumpbtn.doing{--st:var(--doing);--stsoft:var(--doing-soft)}
.jumpbtn.paused{--st:var(--paused);--stsoft:var(--paused-soft)}
.jumpbtn.done{--st:var(--accent);--stsoft:var(--accent-soft)}
.jumpbtn:is(.know,.doubt,.question,.todo,.doing,.paused,.done):not(.here){
  background:var(--stsoft);border-color:color-mix(in srgb,var(--st) 60%,var(--line));border-left-color:var(--st)}
.jumpbtn:is(.know,.doubt,.question,.todo,.doing,.done):not(.here) .jumpn{background:var(--st);color:var(--on-st)}
/* r572: On Hold's second count — tasks waiting on ANOTHER task. Nothing to act on,
   so smaller, hollow and in the paused grey, never the filled badge of what is yours.
   After the tone rules, and out-ranking them, so neither the tone nor .here's fill reaches it. */
.jumpns{display:inline-flex;align-items:center;gap:4px}
.jumpbtn .jumpn.jumpsub.jumpsub.jumpsub{font-size:11px;font-weight:600;padding:0 5px;min-width:16px;
  line-height:16px;background:transparent;color:var(--muted);
  border:1px solid color-mix(in srgb,var(--muted) 70%,transparent)}

/* r314: under the pointer a view chip answered nothing — the tint above
   outranks .jumpbtn:hover. It now deepens halfway to "here" and lifts, without
   the ring and the bar that say you are on it. (hover:hover) keeps a tap on a
   phone from leaving a chip stuck lit; the keyboard gets the same cue. */
.jumpbtn,button.primary{transition:background-color .12s,border-color .12s,box-shadow .12s,transform .12s}
@media (hover:hover){
  .jumpbtn:not(.here):hover{background:color-mix(in srgb,var(--st,var(--muted)) 22%,var(--stsoft,var(--panel-2)));
    border-color:var(--st,var(--muted));transform:translateY(-2px);
    box-shadow:0 4px 10px color-mix(in srgb,var(--st,var(--muted)) 30%,transparent)}
  .jumpbtn.here:hover{box-shadow:inset 0 0 0 2px var(--st)}
  button.primary:hover:not(:disabled){background:color-mix(in srgb,var(--accent) 82%,var(--ink));
    border-color:color-mix(in srgb,var(--accent) 82%,var(--ink));
    box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 40%,transparent)}
}
.jumpbtn:focus-visible,button.primary:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
button.primary:active:not(:disabled),.jumpbtn:active{transform:translateY(1px);box-shadow:none}
@media (prefers-reduced-motion:reduce){
  .jumpbtn,button.primary{transition:none}
  .jumpbtn:not(.here):hover,.jumpbtn:active,button.primary:active:not(:disabled){transform:none}
}

/* A heading scrolled to must clear the header AND the bar above it, or the
   thing you jumped to lands underneath them. Measured, not guessed: the header
   wraps to three rows on a phone. */
.sect, #closed, #marks{scroll-margin-top:var(--stickyh,110px)}

@media (max-width:640px){
  .jump{gap:6px;padding:8px 0}
  /* Four side by side do not fit a phone with the count beside the label —
     Archive fell off the end — so the count goes under it. */
  .jumpbtn{flex-direction:column;gap:3px;padding:6px 4px;font-size:15px;
    min-height:50px;min-width:0}
  .jumpn{font-size:13px;padding:0 6px;min-width:18px}
}

/* Between full width and a phone the separators tighten. Labels stay: when the
   nav does not fit, whole groups fold into More (fitNav) — icons without their
   names were guessed at, and a screen scrolled off the end was not seen at all. */
@media (max-width:1240px){
  .navsep{margin:0 6px}
}

/* The awkward band: too narrow for the nav AND the summary, too wide for the
   nav to have moved to its own row yet. The SUMMARY goes — it is a restatement
   of numbers the page itself is showing, and navigation you cannot see is a
   screen you forget exists. */
@media (max-width:900px) and (min-width:721px){
  header .pill{display:none}
  /* The board's tray (r242) keeps Folder's word; Play is ▶ alone, as on a phone. */
  header .playbtn .playword{display:none}
  .headacts{padding:3px;gap:4px}
  /* ...and One at a time is ▶ and its count: the header overflowed here even before. */
  header .focusgo .fgword{display:none}
}

/* Phone: the nav is its own row, every link with its word, and what does not
   fit that row folds into More, where it is listed with its name too. */
@media (max-width:720px){
  header{padding:8px 12px;gap:8px}
  header{flex-wrap:wrap}
  nav{gap:2px;width:100%;order:3;padding-bottom:2px}
  .navsep{margin:0 5px}
  /* THE BAR IS TWO ROWS THAT DO NOT MOVE (r766): the logo, the board and Find,
     then the nav. What belongs to the screen (the board's buttons, the counts)
     comes BELOW the nav: above it, it sat empty in the logo's row, then wrapped
     to a row of its own once its data came in and pushed the nav down. Screens
     with no nav (home, /focus) keep theirs beside the logo. */
  header:has(> nav .nvl) > :not(h1):not(nav):not(.navfind):not(#_){order:4}
  /* ...and an empty pill is a line tall already, or the bar grows as it fills. */
  header .pill:empty::before{content:"\200b"}
  .nvl{padding:5px 8px}
  .nvi{width:16px;height:16px}
  .navmenu{left:8px !important;right:8px;min-width:0}
  .navfind .nvt{display:none}
  .findpanel{left:8px;right:8px;width:auto;max-height:75vh}
  .findq{font-size:16px}              /* iOS zooms under 16px */
  .findline,.findaka{padding-left:0}
  .navmenu .nvl{font-size:16px;padding:12px 10px}
}

/* THE MOTHER PAGE. One card per board, and the card has to answer three things
   from across the room: does it want me, is it moving, what is it for. */
.bcard{background:var(--panel);border:1px solid var(--line);border-radius:12px;
  border-left:5px solid var(--line);padding:16px 18px;margin:14px 0;
  box-shadow:var(--shadow)}
.bcard.needs{border-color:color-mix(in srgb,var(--q) 45%,var(--line));
  border-left-color:var(--line)}
.bhead{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.btitle{font-size:17px;font-weight:700;color:var(--ink);text-decoration:none}
.btitle:hover{color:var(--accent)}
.kind{font-size:13px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--muted);border:1px solid var(--line);border-radius:999px;padding:2px 9px 2px 7px;
  cursor:help;display:inline-flex;align-items:center;gap:5px}
.kind .nvi{width:13px;height:13px}
.kind.sub{font-weight:600;border-style:dashed}
/* A board's traits (r312): marks only, the word on hover. */
.traits{display:inline-flex;align-items:center;gap:3px;color:var(--muted);cursor:help}
.trait{width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center;
  border-radius:5px;background:var(--panel-2)}
.trait .nvi{width:12px;height:12px}
.trait.mono{font-size:11px;font-weight:750;line-height:1}
/* A board's mark: its own icon, or its initial on a tile tinted by its kind. */
.bmark{width:34px;height:34px;border-radius:9px;flex:none;object-fit:contain;display:block}
.bmark.mono{display:inline-flex;align-items:center;justify-content:center;
  font-size:17px;font-weight:750;color:var(--muted);background:var(--panel-2);
  border:1px solid var(--line)}
/* A KIND IS A PAIR OF COLOURS (r804): the state already owns amber, purple and
   blue (the stripe, paintStripe), so a course in amber or a game in purple read
   as a board running or waiting on you. Each kind is two hues the stripe never
   uses, as a gradient: tool teal into lime, game pink into orange, website lime
   into pink, course coral into sun, library silver into cyan. */
:root{--kt1:#0b8a7a;--kt2:#4d7c0f;--kg1:#c2256f;--kg2:#c2530c;--kw1:#4d7c0f;--kw2:#be185d;
  --kc1:#c93a2b;--kc2:#9a6a00;--kl1:#56627a;--kl2:#0e7490}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --kt1:#2ee6c8;--kt2:#b6f04a;--kg1:#ff6fb1;--kg2:#ff9a4a;--kw1:#c6f432;--kw2:#ff6fb1;
  --kc1:#ff8a7a;--kc2:#ffd166;--kl1:#c8d0e0;--kl2:#35d6ee}}
:root[data-theme="dark"]{--kt1:#2ee6c8;--kt2:#b6f04a;--kg1:#ff6fb1;--kg2:#ff9a4a;
  --kw1:#c6f432;--kw2:#ff6fb1;--kc1:#ff8a7a;--kc2:#ffd166;--kl1:#c8d0e0;--kl2:#35d6ee}
.k-tool{--k1:var(--kt1);--k2:var(--kt2)}
.k-game{--k1:var(--kg1);--k2:var(--kg2)}
.k-website{--k1:var(--kw1);--k2:var(--kw2)}
.k-course{--k1:var(--kc1);--k2:var(--kc2)}
.k-library{--k1:var(--kl1);--k2:var(--kl2)}
.bmark.mono:is(.k-tool,.k-game,.k-website,.k-course,.k-library){color:var(--panel);
  border-color:transparent;background:linear-gradient(135deg,var(--k1),var(--k2))}
.board{display:inline-flex;align-items:center}
.bmark.head{width:20px;height:20px;border-radius:5px;font-size:13px;margin:0 2px 0 6px}
/* A phone header has no room for it: it pushed the focus button onto a row of its own. */
@media (max-width:720px){ .bmark.head{display:none} }
.wstate{font-size:14px;color:var(--muted)}
.wstate.live{color:var(--live);font-weight:600}
.wstate.warn{color:var(--doing);font-weight:600}
.wstate.stuck{color:var(--danger);font-weight:700}
.babout{font-size:14.5px;color:var(--muted);margin-top:7px;line-height:1.5;max-width:70ch}

.hnums{display:flex;gap:8px;flex-wrap:wrap;margin-top:13px}
.hn{display:inline-flex;align-items:baseline;gap:6px;font-size:14px;color:var(--muted);
  background:var(--panel-2);border:1px solid var(--line);border-radius:8px;padding:5px 11px}
.hn b{font-size:16px;font-weight:700;color:var(--ink)}
/* "same call ×N" (r500, repeatsMark): muted, then the looping alert's amber. */
.repeats{display:inline-flex;align-items:center;font-size:13px;color:var(--muted);
  border:1px dashed var(--line);border-radius:8px;padding:2px 8px;white-space:nowrap}
.hnums .repeats{font-size:14px;padding:5px 11px}
.repeats.loop{color:var(--ink);border:1px solid var(--doing);background:var(--doing-soft);
  font-weight:600}
/* r308: a board's views, in the board's own colours (.jumpbtn): label first, the
   count in a filled pill, and the whole chip opens that view. */
a.hn{align-items:center;gap:8px;color:var(--ink);font-weight:600;font-size:14.5px;
  text-decoration:none;border-left-width:4px;padding:4px 6px 4px 10px}
a.hn b{font-size:14px;padding:0 8px;border-radius:999px;min-width:22px;text-align:center}
a.hn.todo{--st:var(--todo);--stsoft:var(--todo-soft)}
a.hn.doubt{--st:var(--q);--stsoft:var(--q-soft)}
a.hn.know{--st:var(--note);--stsoft:var(--note-soft)}
a.hn.doing{--st:var(--doing);--stsoft:var(--doing-soft)}
a.hn:is(.todo,.doubt,.know,.doing){background:var(--stsoft);
  border-color:color-mix(in srgb,var(--st) 60%,var(--line));border-left-color:var(--st)}
a.hn:is(.todo,.doubt,.know,.doing) b{background:var(--st);color:var(--on-st)}
a.hn:hover{border-color:var(--st)}
a.hn.zero{background:var(--panel-2);border-color:var(--line);border-left-color:var(--st)}
a.hn.zero b{background:var(--line);color:var(--ink)}
details.bmore{margin-top:11px}
details.bmore .whybody{white-space:normal;border-left-color:var(--line);padding-left:0;
  border-left:0}
.btable{margin-top:4px}
.btable table{font-size:14.5px}
.btable th,.btable td{padding:6px 12px;white-space:normal;vertical-align:top}
.btable th{width:1%;white-space:nowrap;color:var(--ink);font-weight:600}
.btable th a{color:inherit}
/* It has no header row: .stattable greys its first row as one. */
.stattable.btable tr:first-child th{color:var(--ink);font-size:inherit;text-align:left}
.btable td{color:var(--muted)}
.btable tr:last-child th,.btable tr:last-child td{border-bottom:0}
.btable tr.cangap th,.btable tr.cangap td{color:var(--q)}

.bcan{display:flex;gap:6px;flex-wrap:wrap;margin-top:11px}
.canchip{font-size:13.5px;color:var(--muted);border:1px dashed var(--line);
  border-radius:999px;padding:3px 10px;cursor:help}
.canchip.cangap{color:var(--q);border-color:currentColor}  /* a game board with no Play */
.bacts{display:flex;gap:7px 16px;flex-wrap:wrap;margin-top:14px;align-items:center;
  border-top:1px solid color-mix(in srgb,var(--sec,var(--line)) 30%,var(--line));padding-top:13px}
/* r794: two groups, GO THERE and RUN IT; the worker's start or stop ends the row. */
.bgo,.brun{display:flex;gap:7px;flex-wrap:wrap;align-items:center}
.brun{margin-left:auto}
.iconed{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
@media (max-width:720px){
  .brun{margin-left:0;width:100%}
  .brun > :last-child{margin-left:auto}
}
.iconed .nvi{width:15px;height:15px;flex:none;stroke-width:1.6}
.bgo .btnlink:not(.primarylink) .nvi{color:var(--sec,var(--muted))}
.btnlink.quiet{border-color:transparent;background:transparent;color:var(--muted)}
.btnlink.quiet:hover,.btnlink.quiet.on{color:var(--ink);border-color:var(--line)}

/* A BOARD CARD'S BORDER TAKES ITS STRIPE'S COLOUR (r804): the stripe's state
   (paintStripe: amber running, purple On Hold, blue queued, none idle). Its
   BACKGROUND stays plain: the wash r804 laid over the card, breathing from the
   left, was too much (r822, "we might have over done it"). The kind has its own
   colours, on its chip and its initial tile (.k-*). */
.bcard.stripe.st-run{--stc:var(--runc)}
.bcard.stripe.st-held{--stc:var(--q)}
.bcard.stripe.st-idle{--stc:var(--todo)}
.bcard.stripe:is(.st-run,.st-held,.st-idle){
  border-top-color:color-mix(in srgb,var(--stc) 38%,var(--line));
  border-right-color:color-mix(in srgb,var(--stc) 18%,var(--line));
  border-bottom-color:color-mix(in srgb,var(--stc) 22%,var(--line))}

.bbody{display:flex;gap:10px 22px;align-items:flex-start;flex-wrap:wrap}
/* A long word (a Drive id, a URL) breaks rather than widening a phone's page:
   the flex item's min-width:auto held it at its longest word (r872). */
.bbody .babout{flex:1 1 380px;min-width:0;overflow-wrap:anywhere}
.bbody > .babout + .hnums{margin-left:auto;justify-content:flex-end;margin-top:9px}
/* The kind chip in its pair: a gradient ring, the word in the same gradient. */
.bhead .kind:is(.k-tool,.k-game,.k-website,.k-course,.k-library){border-color:transparent;
  background:linear-gradient(var(--panel),var(--panel)) padding-box,
    linear-gradient(90deg,var(--k1),var(--k2)) border-box}
.bhead .kind:is(.k-tool,.k-game,.k-website,.k-course,.k-library) > span{
  background:linear-gradient(90deg,var(--k1),var(--k2));-webkit-background-clip:text;
  background-clip:text;color:transparent}
.bhead .kind:is(.k-tool,.k-game,.k-website,.k-course,.k-library) > svg{color:var(--k1)}
/* ITS COUNTS ARE THE PANEL'S FIGURES (r794): the number large over what it
   counts, a button tinted in that view's colour, filling toward its foot; a
   zero is outlined only. The label stays first in the markup (tests read it). */
.bbody > .hnums a.hn{flex-direction:column-reverse;align-items:flex-start;gap:0;min-width:78px;
  padding:5px 12px 7px;border-radius:10px;border:1px solid color-mix(in srgb,var(--st) 55%,transparent);
  background:linear-gradient(transparent 20%,color-mix(in srgb,var(--st) 30%,transparent));
  font-weight:500;font-size:13.5px;color:var(--muted);position:relative;
  transition:border-color .15s,transform .15s,box-shadow .15s}
.bbody > .hnums a.hn b{background:none;padding:0;min-width:0;text-align:left;
  font-size:28px;line-height:1.05;font-weight:700;color:var(--st);font-variant-numeric:tabular-nums}
.bbody > .hnums a.hn:hover{border-color:var(--st);color:var(--ink);transform:translateY(-1px);
  box-shadow:0 6px 16px -8px color-mix(in srgb,var(--st) 70%,transparent)}
.bbody > .hnums a.hn.zero{background:transparent;border-color:var(--line-2)}
.bbody > .hnums a.hn.zero b{background:none;color:var(--muted)}
.bbody > .hnums a.hn .subn{position:absolute;top:6px;right:7px}
@media (max-width:720px){.bbody > .babout + .hnums{margin-left:0;justify-content:flex-start}}
button.stopbtn{background:var(--danger);border-color:var(--danger);color:var(--on-st);
  font-weight:700}
/* A board the plan paused is offered Resume AND Close up Shop (r951): the two and
   when the pause lifts join the actions row they are appended to. */
.shopboth{display:contents}
.shopboth > .hint{align-self:center;font-size:13px}
.primarylink{background:var(--accent);border-color:var(--accent);color:var(--on-st);
  font-weight:600}
.primarylink:hover{color:var(--on-st)}

/* DRAG TO ORDER (r338): the grip is the only handle, so the card still scrolls. */
.bcard{position:relative;padding-left:40px}
.bgrip{touch-action:none;cursor:grab;display:flex;align-items:center;justify-content:center;
  position:absolute;left:0;top:0;bottom:0;width:30px;padding:0;margin:0;border:0;
  border-right:1px solid var(--line);border-radius:0;background:transparent;color:var(--muted)}
.bgrip .nvi{width:18px;height:22px;stroke-width:2.6;stroke-linecap:round}
.bgrip:hover,.bgrip:focus-visible{color:var(--ink);background:var(--panel-2)}
/* What a drag shows (r401): the card lifted under the finger, the others gliding
   aside, a dashed slot where it lands, and each card's place in its grip. */
#boards{position:relative}
.bcard{transition:transform .18s ease}
.bcard.dragging{transition:none;z-index:3;border-color:var(--accent);
  box-shadow:0 18px 44px rgba(0,0,0,.5),0 0 0 2px var(--accent)}
.bcard.settling{z-index:3;border-color:var(--accent)}
.bcard.dragging .bgrip,.bcard.settling .bgrip{cursor:grabbing;color:var(--accent);
  background:color-mix(in srgb,var(--accent) 14%,transparent)}
.bslot{position:absolute;left:0;right:0;z-index:1;pointer-events:none;border-radius:12px;
  border:2px dashed var(--accent);background:color-mix(in srgb,var(--accent) 7%,transparent)}
body.boarddrag{user-select:none;-webkit-user-select:none;cursor:grabbing}
.bpos{position:absolute;top:11px;left:3px;right:3px;text-align:center;font-size:12.5px;
  font-weight:700;line-height:20px;font-variant-numeric:tabular-nums;color:var(--muted);
  border-radius:999px}
.bcard.dragging .bpos,.bcard.settling .bpos{background:var(--accent);color:var(--on-st)}
.bcard.placed .bpos{animation:bplaced 1.2s ease}
@keyframes bplaced{0%,40%{background:var(--accent);color:var(--on-st)}}
@media (prefers-reduced-motion:reduce){
  .bcard{transition:none}
  .bcard.placed .bpos{animation:none}
}

/* SHOW ONLY (r828): home's filter over the lineup, the board's view chips. A
   filtered lineup is a reading, not the order: its grips stand down. */
.jump.bfilter{margin:0 0 14px}
#boards.filtered .bgrip{cursor:default}
#boards.filtered .bgrip .nvi{visibility:hidden}
#boards.filtered .bgrip:hover{background:transparent;color:var(--muted)}

/* SUB BOARDS (r336): a main board's subs ride inside its card, one compact row each. */
.subboards{margin-top:13px;border-left:3px solid var(--line);padding-left:12px}
.subhead{font-size:12.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--muted);margin-bottom:6px}
.subrow{display:flex;align-items:center;gap:8px 12px;flex-wrap:wrap;padding:8px 10px;
  margin-top:6px;background:var(--panel-2);border:1px solid var(--line);border-radius:9px;
  border-left:4px solid var(--line)}
.subname{display:flex;align-items:center;gap:8px;min-width:0}
.subrow .btitle{font-size:15.5px}
.bmark.small{width:24px;height:24px;border-radius:6px;font-size:13px}
.subrow .hnums{margin-top:0}
.subrow a.hn{font-size:13.5px;padding:2px 5px 2px 8px}
.subrow a.hn b{font-size:13px}
.subacts{display:flex;gap:6px;margin-left:auto}
.subrow details.bmore{flex:1 0 100%;min-width:0;margin-top:0}   /* its own last line, full width;
   min-width:0, or its table held the row wider than a phone (r872) */
.subacts button.small{padding:2px 9px;font-size:13.5px}

/* PARKED BOARDS (r769): the foot of Home. Set apart by a dashed edge and a quieter
   ground, so a board there reads as put away, not as one more card. */
.parkband{margin:22px 0 14px;padding:12px 14px 14px;border:1px dashed var(--line);
  border-radius:12px;background:var(--panel-2)}
.parkhead{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}
.parkhead{flex-wrap:wrap}
.parkhead > span:not(.hint){white-space:nowrap}
.parkhead .hint{text-transform:none;letter-spacing:0;font-weight:400;margin-left:4px}
.parkhead .nvi,.parkbtn .nvi{width:15px;height:15px;fill:none;stroke:currentColor;
  stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
.parkrow{display:flex;align-items:center;gap:8px 12px;flex-wrap:wrap;padding:8px 10px;
  margin-top:8px;background:var(--panel);border:1px solid var(--line);border-radius:9px;
  border-left:4px solid var(--line);opacity:.86}
.parkrow:hover,.parkrow:focus-within{opacity:1}
.parkrow .btitle{font-size:15.5px}
.parkrow .hnums{margin-top:0}
.parkrow a.hn{font-size:13.5px;padding:2px 5px 2px 8px}
.parkbtn{display:inline-flex;align-items:center;gap:5px}
.parkbtn.small{padding:2px 9px;font-size:13.5px}
.bacts .btnlink.on{border-color:var(--accent);color:var(--accent)}
.splitform{margin-top:12px;padding:13px 14px;border:1px dashed var(--accent);
  border-radius:10px;background:var(--accent-soft)}
.splithead{font-weight:700;color:var(--ink);margin-bottom:3px}
.splitrow{display:flex;gap:10px;flex-wrap:wrap;margin-top:10px}
.splitfield{display:flex;flex-direction:column;gap:3px;font-size:13px;color:var(--muted);
  flex:1 1 170px;min-width:0}
.splitfield input{font-size:15px;width:100%;box-sizing:border-box}
.splittags{display:flex;gap:6px;flex-wrap:wrap;margin-top:11px}
.splittag{display:inline-flex;align-items:center;gap:6px;font-size:14px;cursor:pointer;
  border:1px solid var(--line);border-radius:999px;padding:3px 10px 3px 7px;
  background:var(--panel)}
.splittag:has(input:checked){border-color:var(--accent);color:var(--accent)}
.splitacts{display:flex;gap:8px;margin-top:12px}
@media (max-width:720px){ .splitfield input{font-size:16px} }   /* iOS zooms under 16px */

@media (max-width:640px){
  .subrow .wstate{flex:1 1 auto}    /* the state and the buttons share the last line */
  .bcard{padding:13px 14px 13px 34px;border-radius:10px}
  .bcard.stripe{--stripr:10px}
  .bgrip{width:24px}
  .bpos{left:1px;right:1px;font-size:12px}
  .bslot{border-radius:10px}
  .btitle{font-size:16px}
  .hn{padding:4px 9px}
  .hn b{font-size:15px}
}

/* What a session has actually done, on its card — so ending one is a decision
   rather than a guess from a turn count. */
.worked{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-top:9px}
.btnlink.small{padding:2px 9px;font-size:13.5px}
.handover{margin-top:11px;padding:11px 13px;border-radius:9px;
  background:var(--accent-soft);border:1px solid transparent;
  border-left:4px solid var(--accent);font-size:14.5px;line-height:1.55;
  white-space:pre-wrap}
.handover b{display:block;font-size:13px;letter-spacing:.05em;text-transform:uppercase;
  color:var(--accent);margin-bottom:5px}

/* ALERTS. Above everything, on every screen — including screens about another
   board, which is the entire reason the channel exists. */
.alerts{display:flex;flex-direction:column;gap:9px;margin:14px 0 6px}
.alert{border-radius:10px;padding:9px 15px;border:1px solid var(--line);
  border-left:5px solid var(--muted);background:var(--panel)}
.alert.critical{border-left-color:var(--danger);background:var(--q-soft)}
.alert.warn{border-left-color:var(--doing);background:var(--doing-soft)}
.alert.note{border-left-color:var(--accent)}
.alerthead{display:flex;align-items:center;gap:9px}
.alerthead.opens{cursor:pointer}
.alerthead.opens:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:6px}
.alertlvl{font-size:13px;font-weight:800;letter-spacing:.08em;flex:none;
  padding:2px 8px;border-radius:999px;background:var(--line);color:var(--ink)}
.alert.critical .alertlvl{background:var(--danger);color:var(--on-st)}
.alert.warn .alertlvl{background:var(--doing);color:var(--on-st)}
.alert.note .alertlvl{background:var(--accent);color:var(--on-st)}
/* In a board's Notifications (r238) a note wears that view's pink. */
.boardnotes{margin:0 0 12px}
.boardnotes .alert.note{border-left-color:var(--note);background:var(--note-soft)}
.boardnotes .alert.note .alertlvl{background:var(--note)}
.alertwhere{font-size:13.5px;font-weight:700;color:var(--muted);text-decoration:none;flex:none;
  border:1px dashed var(--line);border-radius:999px;padding:2px 9px}
a.alertwhere:hover{color:var(--ink);border-style:solid}
.alertwhere.here{border-style:solid}
/* Shut, the summary is one line and gives way to everything else on it. */
.alerttitle{font-size:14.5px;font-weight:600;color:var(--ink);flex:1 1 auto;min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.alert.open .alerttitle{white-space:normal}
.alertwhen{font-size:13.5px;color:var(--muted);white-space:nowrap;flex:none;
  font-variant-numeric:tabular-nums}
.alertwhen b{color:var(--ink);font-weight:700}
.alert:not(.open) .alertwhen > span{display:none}      /* "raised 13:06 ·" is for the open one */
.alerthead button{flex:none}
.alertchev{flex:none;color:var(--muted);font-size:15px;transition:transform .22s ease}
.alert.open .alertchev{transform:rotate(180deg)}
.alertbody{display:grid;grid-template-rows:0fr;transition:grid-template-rows .22s ease}
.alert.open .alertbody{grid-template-rows:1fr}
.alertbody > *{min-height:0;overflow:hidden}
.alertdetail{font-size:14.5px;color:var(--muted);line-height:1.55;max-width:85ch;
  padding-top:6px;opacity:0;transition:opacity .22s ease}
.alert.open .alertdetail{opacity:1}
@media (prefers-reduced-motion: reduce){
  .alertbody,.alertdetail,.alertchev{transition:none}
}
/* A phone has no room for the summary beside four chips, so it takes a line of
   its own — and that line is the FIRST one (r562). It used to be `order:5`, which
   put the sentence that says what is wrong under the chips, the clock and its own
   Got it button: three rows of furniture before the news. The chips keep their
   row below it, with Got it at its foot, which is where a card's actions belong
   on a phone everywhere else on this board. */
@media (max-width: 720px){
  .alerthead{flex-wrap:wrap;row-gap:5px}
  .alerttitle{order:-1;flex-basis:100%}
  .alertwhen{margin-left:auto}
}

/* ===================================================================
   THE RUNS SCREEN
   Every session is its own agent — a name, a kind, what it has loaded, what it
   may take, what it has closed and what it cost — so a live one gets a card of
   its own and an ended one a line you can scan. The border says what it is
   DOING; the badge says what it IS. Two signals, two places.
   =================================================================== */
.quick.headline{display:block}
.hl-top{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.hl-top b{font-size:15px}
#roster{margin-top:10px}
#roster:empty{display:none}
#meterhint{margin-top:8px}
.hn.roster{align-items:center}

/* The kind is a fact about a session's rails (decided at spawn), so it reads as
   a stamp, and the one kind that may push is the one you cannot miss. */
.skind{font-size:13px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  border:1px solid var(--line);color:var(--muted);border-radius:999px;padding:1px 8px;
  cursor:help;white-space:nowrap;flex:none}
.skind.k-coordinator{background:var(--q);border-color:transparent;color:var(--on-st)}

.sstate{font-size:13.5px;font-weight:600;border-radius:999px;padding:1px 9px;
  white-space:nowrap;flex:none;border:1px solid var(--line);color:var(--muted)}
.sstate.working{background:var(--doing);border-color:transparent;color:var(--on-st)}
.sstate.starting,.sstate.budget{border-color:var(--doing);color:var(--doing)}
.sstate.waiting{border-style:dashed;border-color:var(--accent);color:var(--accent)}
.sstate.stopping,.sstate.failed,.sstate.killed,.sstate.timeout{border-color:var(--danger);
  color:var(--danger)}
.sstate.done{border-color:var(--accent);color:var(--accent)}
/* One barren session is unremarkable, so it is marked, not alarmed. */
.sstate.barren{border-style:dashed;font-weight:400}

.card.agent{border-left-width:5px;padding:13px 15px}
.card.agent.working,.card.agent.starting{border-left-color:var(--doing);
  background:var(--doing-soft)}
.card.agent.waiting{border-left-color:var(--accent)}
.card.agent.stopping{border-left-color:var(--danger)}
.agenthead{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.agenthead .dot{width:9px;height:9px;border-radius:99px;flex:none;background:var(--muted)}
.card.agent.working .dot,.card.agent.starting .dot{background:var(--doing)}
.card.agent.waiting .dot{background:var(--accent)}
.card.agent.stopping .dot{background:var(--danger)}
.agentname{font:600 15px/1.3 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--ink);
  overflow-wrap:anywhere}
.card.agent .hnums{margin-top:11px}
.card.agent .say{margin-top:8px}
.worked .sep{margin-left:10px}
/* A session's own commits (r532), read off the checkout by its Session trailer.
   The subject is one line: a card full of wrapped commit messages is unscannable. */
.worked .cmt{font-size:14px;max-width:min(100%,54ch);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.worked .cmt code{font-size:12.5px;padding:0 4px;margin-right:3px}
.tag.rail{border-color:var(--q);color:var(--q);font-weight:600}
.btnlink.onnow{background:var(--doing);border-color:transparent;color:var(--on-st);font-weight:600}
.btnlink.agentlink{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}

/* Output is read from the bottom: that is where the session is now. */
.detail.tail{cursor:pointer;font:13.5px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;
  overflow-wrap:anywhere}
.detail.tail .all{display:none}
.detail.tail .more{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  font-size:13.5px;opacity:.75}
.detail.tail.full .all{display:block}
.detail.tail.full .peek,.detail.tail.full .more{display:none}

.sessday{font-size:13px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  color:var(--muted);margin:18px 0 6px}
.sessrow{background:var(--panel);border:1px solid var(--line);border-left:4px solid var(--line);
  border-radius:9px;padding:9px 12px;margin-bottom:6px}
.sessrow.st-done{border-left-color:var(--accent)}
.sessrow.st-budget{border-left-color:var(--doing)}
.sessrow.st-failed,.sessrow.st-killed,.sessrow.st-timeout{border-left-color:var(--danger)}
.sesstop{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.sessrow .agentname{font-size:15px}
.sessnums{display:flex;gap:11px;flex-wrap:wrap;font-size:14px;color:var(--muted);
  font-variant-numeric:tabular-nums}
.sessnums .cost{color:var(--accent);font-weight:600}
.sessrow .meta{margin-top:5px}
.sessrow .reason{font-style:italic}
.sessrow details.why{margin-top:6px}
.sessrow .handover{margin-top:8px}
@media (max-width:720px){
  .card.agent{padding:12px}
  .sesstop .grow{display:none}
  .sessnums{flex:1 1 100%;gap:9px}
  .btnlink.small,.subacts button.small{min-height:30px;display:inline-flex;align-items:center}
}

/* --- one at a time: everything waiting on you, full screen --- */
/* One item, large. The card text is 12.5–14px because a card is one of seven; here
   there is one, and a taste call deserves to be read at reading size. */
.focusgo{flex:none;white-space:nowrap}
.homelinks{display:flex;gap:8px;flex:none}
.homelinks > .btnlink{flex:none;white-space:nowrap;padding:6px 12px;font-size:15px}
#every + #lede{margin-top:28px}  /* stats: one board's figures start here */
/* The board's checkout, from inside the board (home cards have their own). */
header .folderbtn{flex:none;background:transparent;cursor:pointer;min-height:0;
  display:inline-flex;align-items:center;gap:6px}
/* The board's actions, one group (r242): a tray, so they read as belonging together
   and apart from the nav. */
.headacts{display:flex;align-items:center;gap:6px;flex:none;padding:4px;
  border:1px solid var(--line-2);border-radius:12px;background:var(--panel-2)}
.headacts:not(:has(> :not([hidden]))){display:none}
header .headacts .folderbtn{background:var(--panel)}
/* ONE HEADER, PANEL OR BOARD (r895). Since r885 you press between the two, and
   the tray made Board's header 13px taller: the pair dropped 6px, the page 13px.
   The tray is now a fixed box that takes no more than the nav's row (32px: it
   overhangs it by 1px each side), its buttons one height inside it. On a phone
   its row and the counts pill's are one height too (below). tests/header_steady.py */
header .headacts{--acth:34px;box-sizing:border-box;height:var(--acth);padding:2px;gap:4px;
  margin-block:-1px}
header .headacts > *,header .headacts .actsmore > button{box-sizing:border-box;
  height:calc(var(--acth) - 6px);min-height:0;padding-block:0}
/* A link does not centre its words the way a button does. Never on a button: a
   flex button drops the spaces between One at a time's words and its count. */
header .headacts > a{display:inline-flex;align-items:center}
header .headacts > [hidden]{display:none}
/* The phone's last row holds the pill on Panel, the tray on Board: one height,
   38px, so the tray's buttons stay a thumb's size (32px) and the pill is centred
   in the same room. */
@media (max-width:720px){
  header .headacts{--acth:38px;margin-block:0}
  header > .pill{margin-block:calc((38px - 1lh) / 2 - 3px)}
}
.playbtn[hidden],.repobtn[hidden]{display:none}  /* .btnlink's display beats the attribute */
/* Play and its ▾ (r916, playSplit): one control, two halves. */
.playsplit{display:inline-flex;align-items:stretch;flex:none}
.playsplit[hidden]{display:none}
.playsplit > :first-child:has(+ .playpick){border-top-right-radius:0;border-bottom-right-radius:0}
.playsplit > .playpick{border-top-left-radius:0;border-bottom-left-radius:0;margin-left:-1px;
  padding-inline:7px;cursor:pointer}
header .headacts > .playsplit > button{height:100%;min-height:0;padding-block:0}
.actsmenu > .playsplit{display:flex;width:100%}
.actsmenu > .playsplit > :first-child{flex:1;justify-content:flex-start}
.playmenu{min-width:240px}
.playrow{display:flex;gap:6px;align-items:stretch}
.playrow .playgo{flex:1;display:flex;align-items:center;gap:6px;text-align:left;
  justify-content:flex-start}
.playrow .playgo em{margin-left:auto;padding-left:10px;font-style:normal;font-size:12.5px;
  color:var(--muted)}
.playrow .playlink{display:inline-flex;align-items:center;white-space:nowrap}
html.focusing,html.focusing body{overflow:hidden}
.focus{position:fixed;inset:0;z-index:90;background:var(--bg);overflow:auto;
  overscroll-behavior:contain;font-size:18px;line-height:1.6}
.focus-bar{position:sticky;top:0;z-index:1;display:flex;gap:8px;align-items:center;
  padding:10px 20px;padding-top:max(10px, env(safe-area-inset-top));
  background:var(--panel);border-bottom:1px solid var(--line)}
.focus-bar .grow{flex:1}
.focus-pos{font-size:15px;font-weight:700;color:var(--muted)}
.focus-bar button{font-size:15px;padding:7px 14px;min-height:40px}
.focus-bar .focus-x{font-size:24px;line-height:1;padding:4px 14px}
.focus-body{max-width:920px;margin:0 auto;padding:32px 24px 96px}
.focus-kind{font-size:15px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
  color:var(--q)}
.focus-kind.know{color:var(--note)}
.focus-head{font-size:clamp(22px, 2.6vw, 32px);line-height:1.35;font-weight:650;
  margin:10px 0 12px;white-space:pre-wrap}
.focus .meta{font-size:15px;margin:0 0 18px}
/* Across every board (/focus): which board the item is on, first in its meta. */
.focus .focusboard{display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:var(--ink);font-weight:650}
.focus .focusboard .bmark.head{margin:0}
.focus-ctx{white-space:pre-wrap;margin:0 0 16px;padding-left:14px;
  border-left:3px solid var(--line)}
.focus .shots{gap:12px;margin:20px 0}
.focus .shot,.focus .shot .cap{max-width:min(440px, 100%)}
.focus .shot img{max-width:min(440px, 100%);max-height:300px}
.focus .shot .cap{font-size:15px;white-space:normal}
.focus .viewbar{margin:14px 0}
.focus-answer{margin-top:26px}
.focus .qbox{padding:16px 18px}
.focus .qbox .lbl{font-size:14px}
.focus textarea{font-size:17px;min-height:96px}
.focus .opts-row{gap:10px}
.focus .opts-row button,.focus .notebox button{font-size:16px;padding:10px 18px;min-height:46px}
.focus .dec{font-size:16px}
/* The choices, stacked, each carrying its own words: the thing to read and the
   thing to press are the same object. Then the free-text answer under them. */
.focus .opts-row:has(.choice){flex-direction:column;align-items:stretch}
.focus .opts-row .choice{order:0;display:flex;gap:14px;align-items:baseline;text-align:left;
  white-space:normal;line-height:1.4}
.focus .opts-row .choice b{flex:none;min-width:1.4em;color:var(--q)}
.focus .opts-row:has(.choice) textarea{order:1;min-width:0}
.focus .opts-row:has(.choice) .mine{order:2;align-self:flex-start}
.focus .focus-choices{margin:4px 0 12px}
.focus .optgroups{margin:4px 0 12px}
.focus .optgroup + .optgroup{margin-top:22px}
.focus .optstem{font-size:17px;color:var(--ink)}
.focus .asks{margin:4px 0 12px}
.focus .askq + .askq{margin-top:22px}
.focus .askstem{font-size:17px}
.focus .askinfo{font-size:15px}
.focus button.askopt{font-size:16px;padding:10px 12px;min-height:46px}
.focus .asked-bg{margin-top:22px}
/* The headline already asks it; the box need not ask again. */
.focus .qbox > .lbl,.focus .qbox > .lbl + div:not(.asks){display:none}
.focus-clear{max-width:920px;margin:18vh auto 0;padding:0 24px;text-align:center}
/* TO REVIEW, one at a time (r587): the same overlay, scoring a close. Five scores
   side by side, each its number over its word, coloured as the card's scale
   (.revpick.sN above); Skip after them. */
.focus-kind.done{color:var(--accent)}
.sect-top .reviewgo{margin-left:auto;font-size:14px;padding:5px 12px}
/* The walk to score, on To score's head in Notif (r882): the violet the scores wear. */
.sect.mark .reviewgo{background:var(--q);border-color:var(--q);color:var(--on-st)}
/* FIND IN THE ARCHIVE (r878): a search bar under the Archive head, its top five
   below it in the Archive's green, each opening its card in the list. */
.archfind{margin:0 0 12px;display:flex;flex-direction:column;gap:6px}
.archfindrow{display:flex;align-items:center;gap:8px;padding:0 12px;border:1px solid var(--line);
  border-radius:10px;background:var(--panel)}
.archfindrow:focus-within{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-soft)}
.archfindicon{color:var(--accent);font-size:20px;line-height:1}
.archfindrow .archfindq,.archfindrow .archfindq:focus{flex:1;min-width:0;border:0;background:none;
  color:var(--ink);font:inherit;font-size:16px;padding:10px 0;outline:none;box-shadow:none}
.archfindout{display:flex;flex-direction:column;gap:4px}
.archfindout.busy{opacity:.55}
.archfindnone{color:var(--muted);font-size:14px;padding:4px 12px}
a.archhit{display:grid;grid-template-columns:auto auto 1fr auto;align-items:baseline;gap:10px;
  padding:8px 12px;border-radius:8px;border-left:3px solid var(--accent);background:var(--accent-soft);
  color:var(--ink);text-decoration:none}
a.archhit:hover,a.archhit:focus{background:var(--panel-2)}
.archhitn{color:var(--accent);font-weight:700;font-size:13px}
.archhitref{color:var(--accent);font-size:14px;min-width:3.2em}
.archhittt{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.archhitwhen{color:var(--muted);font-size:13px;white-space:nowrap}
@media (max-width:720px){
  a.archhit{grid-template-columns:auto 1fr;row-gap:2px}
  .archhitn{display:none}
  .archhittt{grid-column:1/-1;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;
    -webkit-box-orient:vertical}
  .archhitwhen{grid-row:1;grid-column:2;justify-self:end}
  .archhitref{grid-row:1;grid-column:1}
}
.focus .revcommits{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.focus .revasked{margin:0 0 16px;font-size:16px}
.focus .revasked summary{cursor:pointer;color:var(--muted);margin-bottom:8px}
.focus .revscores{display:grid;grid-template-columns:repeat(5, minmax(0, 1fr)) auto;gap:10px}
.focus .revscores .revpick{display:flex;flex-direction:column;align-items:center;gap:2px;
  font-size:15px;padding:10px 6px;min-height:64px;line-height:1.2}
.focus .revscores .revpick b{font-size:22px}
.focus .revscores .revskip{align-self:stretch}
/* Archive's second count: yours to act on, so filled — in On Hold's purple. */
.jumpbtn .jumpn.jumprev.jumprev.jumprev{font-size:11px;font-weight:700;padding:0 5px;
  min-width:16px;line-height:16px;background:var(--q);color:var(--on-st, #fff)}
@media (max-width:720px){
  .focus{font-size:16px}
  .focus-bar{padding:8px 12px}
  .focus-bar button{font-size:15px;padding:6px 10px}
  .focus-body{padding:20px 16px 72px}
  .focus textarea{font-size:16px}          /* below 16px iOS zooms on focus */
  .focus .revscores{grid-template-columns:repeat(5, minmax(0, 1fr));gap:6px}
  .focus .revscores .revpick{font-size:12.5px;padding:8px 2px}
  .focus .revscores .revskip{grid-column:1 / -1}
  .focusgo{padding:6px 10px;font-size:15px}
  header .folderbtn{padding:3px 10px;font-size:14px}
  header .playbtn .playword{display:none}   /* ▶ alone, or Folder wraps to a row of its own */
}

/* --- Markdown (app.js markdown()) ---
   Rendered text is not pre-wrap: the renderer has already turned each newline
   into a break or a block. Spacing is small because it sits inside cards. */
.md{white-space:normal;overflow-wrap:anywhere}
.md > :first-child{margin-top:0}
.md > :last-child{margin-bottom:0}
.md .mdp{margin:0 0 .55em}
.md .mdh{font-weight:700;color:var(--ink);margin:.7em 0 .3em;line-height:1.3}
.md .mdh1{font-size:1.2em}
.md .mdh2{font-size:1.1em}
.md .mdh3,.md .mdh4{font-size:1em}
.md .mdlist{margin:.2em 0 .6em;padding-left:1.4em}
.md .mdlist .mdlist{margin:.15em 0 .2em}
.md li{margin:.12em 0}
.md li::marker{color:var(--muted)}
.md strong{color:var(--ink);font-weight:650}
.md .mdlabel{color:var(--accent)}
.md code{font:.9em/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;background:var(--panel-2);
  border:1px solid var(--line-2);border-radius:4px;padding:0 .3em}
.md .mdpre{margin:.3em 0 .7em;padding:8px 10px;background:var(--panel-2);border:1px solid var(--line);
  border-radius:6px;overflow:auto;white-space:pre}
.md .mdpre code{background:none;border:0;padding:0}
/* A path or a command is written out whole (app.js codeSpan): it wraps, never clips. */
.md code,.md a.mdpath{overflow-wrap:anywhere;word-break:break-word}
.md a.mdpath{color:var(--accent);text-decoration:underline dotted;text-underline-offset:2px;cursor:pointer}
.md a.mdpath:hover{text-decoration-style:solid}
.md code.copy{cursor:copy}
.md code.copy:hover{border-color:var(--accent)}
.md .mdprebox{position:relative}
.md .mdcopy{position:absolute;top:5px;right:5px;padding:0 8px;font-size:13px;line-height:1.7;opacity:.75}
.md .mdprebox:hover .mdcopy,.md .mdcopy:focus{opacity:1}
/* On a phone a command scrolled sideways is a command half read: it wraps, and
   its copy button — a full touch target — sits under it instead of over it. */
@media (max-width:720px){
  .md .mdpre{white-space:pre-wrap;overflow-wrap:anywhere}
  .md .mdprebox{display:flex;flex-direction:column;margin-bottom:.7em}
  .md .mdprebox .mdpre{margin-bottom:4px}
  .md .mdcopy{position:static;align-self:flex-end;opacity:1}
}
.md .mdquote{margin:.3em 0 .7em;padding:0 0 0 10px;border-left:3px solid var(--line);color:var(--muted)}
.md .mdhr{border:0;border-top:1px solid var(--line);margin:.8em 0}
.md .mdtable{overflow-x:auto;margin:.3em 0 .7em}
.md table{border-collapse:collapse;font-size:.95em}
.md th,.md td{border:1px solid var(--line);padding:3px 8px;text-align:left;vertical-align:top}
.md th{background:var(--panel-2);color:var(--ink)}
.md a.mdlink{overflow-wrap:anywhere}
/* A headline that is Markdown keeps its clamp; its blocks sit tight in it. */
.title.q.md .mdp,.title.q.md .mdlist{margin-bottom:.2em}

/* What the coordinator found when Simon asked for a question to be clarified.
   It sits between the question and the answer box, because that is where it is
   needed: read before answering. */
.clarif{margin-top:8px;padding:9px 11px;border-radius:8px;background:var(--accent-soft);
  border:1px solid var(--accent)}
.clarif .lbl{font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:var(--accent);
  font-weight:700;margin-bottom:4px}
.clarif .md{font-size:15px;color:var(--ink)}
.clarifrow{display:flex;gap:7px;align-items:center;flex-wrap:wrap;margin-top:6px}
/* THE DISCUSSION on a card (r104): numbered steps, each one clearly one turn.
   The left rule carries the colour of who spoke — the agent asks, the
   coordinator clarifies, Simon answers — so the alternation is readable at a
   glance, before a word of it is read. */
.thread{margin-top:8px;padding:8px 10px;border-radius:8px;background:var(--panel);
  border:1px solid var(--line)}
.thread > .lbl{font-size:13px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);font-weight:700;margin-bottom:6px}
.turn{border-left:3px solid var(--line);padding:0 0 0 9px;margin:0 0 9px}
.turn:last-child{margin-bottom:0}
.turn.question{border-left-color:var(--doing)}
.turn.clarification{border-left-color:var(--todo)}
.turn.answer{border-left-color:var(--accent)}
.turn.question .twho b{color:var(--doing)}
.turn.clarification .twho b{color:var(--todo)}
.turn.answer .twho b{color:var(--accent)}
.twho{display:flex;gap:6px;align-items:baseline;flex-wrap:wrap;font-size:13.5px;
  color:var(--muted);margin-bottom:2px}
.twho b{color:var(--ink)}
.twho .pmark{align-self:center;margin-right:-2px}
.tnum{display:inline-flex;align-items:center;justify-content:center;min-width:17px;
  height:17px;border-radius:9px;background:var(--line);color:var(--ink);
  font-size:13px;font-weight:700;padding:0 4px}
.tat{margin-left:auto}
.turn .tbody{font-size:15px;color:var(--ink)}
.thold{margin-bottom:9px}
.thold > summary{font-size:13.5px;color:var(--muted);cursor:pointer;margin:0 0 6px;
  text-transform:none;letter-spacing:0;font-weight:600}
.focus .thread{padding:14px 16px}
.focus .turn .tbody{font-size:15px}
.clarifrow .hint{font-size:14px;color:var(--muted)}
.focus-head.md{white-space:normal}
.focus-head.md > :not(:first-child),.focus-head.md.long{font-size:18px;font-weight:450;
  line-height:1.55}
.focus-head.md .mdlist{padding-left:1.6em}
.focus-ctx.md{white-space:normal}
.focus .clarif{padding:16px 18px;margin:0 0 18px}
.focus .clarif .lbl{font-size:14px}
.focus .clarif .md{font-size:17px}

/* --- procedures (/procedures) --- */
.procabout{margin-top:4px}
.procform{display:flex;flex-direction:column;gap:8px;margin-top:10px}
.procin{display:flex;flex-direction:column;gap:3px}
.procin input,.procin select,.procin textarea{width:100%}
.procform > button{align-self:flex-start}
/* r633: a choice is a row of radio chips, the picked one filled; a bool one checkbox line */
.procpicks{display:flex;flex-wrap:wrap;gap:6px}
.procpick{display:inline-flex;align-items:center;gap:6px;padding:5px 11px 5px 8px;
  border:1px solid var(--line);border-radius:999px;cursor:pointer;font-size:14.5px}
.procpick:has(input:checked){border-color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent)}
.procin input[type=radio],.procin input[type=checkbox]{width:auto;margin:0;padding:0;accent-color:var(--accent)}
.procbool{flex-direction:row;align-items:center;gap:8px;cursor:pointer;font-size:14.5px}
.procbool input[type=checkbox]{width:17px;height:17px}
.procsep{margin-top:6px;padding-top:8px;border-top:1px solid var(--line)}
@media (max-width:720px){ .procpick{padding:8px 13px 8px 10px} }
/* r678: a hue per question (--c, set by procedures.html from the status palette) on
   its label, its focus ring and its picked chip, so the form stops reading grey. */
.procform .procin{border-left:3px solid var(--c,var(--line));padding-left:10px}
.procform .procin > .hint{color:var(--c,var(--muted));font-weight:650}
.procform .procin input:focus,.procform .procin textarea:focus,.procform .tagbox:focus-within{
  border-color:var(--c,var(--accent));box-shadow:0 0 0 2px var(--c-soft,transparent);outline:none}
.procform .procpick:has(input:checked){border-color:var(--c,var(--accent));background:var(--c-soft,var(--accent-soft))}
.procform .procpick input{accent-color:var(--c,var(--accent))}
.procbool input[type=checkbox]{accent-color:var(--c,var(--accent))}
.proc > .head .title{font-size:17px;background:linear-gradient(90deg,var(--accent),var(--live) 45%,var(--q));
  -webkit-background-clip:text;background-clip:text;color:transparent}
.proc{border-top:3px solid transparent;border-image:linear-gradient(90deg,var(--accent),var(--live),var(--q),var(--note)) 1}
/* the kind of project, with the mark Home gives a board of that kind */
.procpick.iconic svg{width:17px;height:17px;stroke-width:1.6}
.procpick .kind-website{color:var(--todo)} .procpick .kind-game{color:var(--note)}
.procpick .kind-tool{color:var(--doing)}   .procpick .kind-library{color:var(--live)}
.procpick .kind-course{color:var(--q)}
.procother{margin-top:6px;max-width:420px}
/* the stack: chips in a box that looks like one field */
.tagbox{display:flex;flex-wrap:wrap;gap:6px;align-items:center;padding:5px 8px;min-height:40px;
  border:1px solid var(--line);border-radius:8px;background:var(--panel-2);cursor:text}
.tagbox input{flex:1;min-width:160px;width:auto !important;border:0 !important;background:transparent !important;
  box-shadow:none !important;padding:4px 2px}
.tagbox .chip{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 10px;border-radius:999px;
  font-size:14px;font-weight:600;color:var(--c);background:var(--c-soft);border:1px solid var(--c)}
.tagbox .chipx{border:0;background:transparent;color:inherit;padding:0 6px;font-size:15px;line-height:1;cursor:pointer;min-height:0}
ol.steps{margin:6px 0 0;padding-left:1.4em;font-size:14.5px;color:var(--muted)}
ol.steps.ticks{list-style:none;padding-left:0}
ol.steps.ticks li{margin:3px 0}
ol.steps.ticks .tick{display:inline-block;width:1.3em;color:var(--muted)}
ol.steps.ticks li.ticked{color:var(--ink)}
ol.steps.ticks li.ticked .tick{color:var(--accent);font-weight:700}
.stepnote{margin-left:1.3em;white-space:pre-wrap}
.procanswer{display:flex;gap:8px;align-items:flex-start;margin-top:8px}
.procanswer textarea{flex:1;min-height:40px}
.tailtext{font:13.5px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace}
/* r359: the view bar — Runs, then one per procedure. The board's view buttons,
   not sticky (a view here is short) and wrapping, so a phone shows every one. */
.jump.procjump{position:static;flex-wrap:wrap;row-gap:14px;margin-bottom:16px}
.procjump .jumpbtn{flex:1 1 auto}
.procq,.procresult{margin-top:6px;font-size:15px;line-height:1.55;color:var(--ink)}
.procq p,.procresult p{margin:0 0 .7em}
.procq p:last-child,.procresult p:last-child{margin-bottom:0}
.procresult{color:var(--ink-2)}
.stepnote.md{white-space:normal}
/* An input is often a URL longer than a phone: it ends in an ellipsis, whole in its title. */
.procrun .meta .tag{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Home's Procedures band: its own block between the summary and the boards,
   one tile per procedure, so starting one reads as a thing the page offers. */
.procband{margin:14px 0 4px;background:var(--panel);border:1px solid var(--line);
  border-left:5px solid var(--accent);border-radius:12px;padding:14px 18px;box-shadow:var(--shadow)}
.procband-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.procband-title{display:inline-flex;align-items:center;gap:8px;font-size:15px;font-weight:700;
  color:var(--ink);text-decoration:none}
.procband-title:hover{color:var(--accent)}
.procband-title .nvi{width:17px;height:17px;color:var(--accent);stroke-width:1.5}
.procstate{font-size:14px;font-weight:650;border-radius:999px;padding:2px 10px;text-decoration:none}
.procstate.live{color:var(--doing);background:var(--doing-soft)}
.procstate.asks{color:var(--q);background:var(--q-soft)}
.proctiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:10px;margin-top:12px}
.proctile{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:10px;
  border:1px solid var(--line);background:var(--panel-2);color:var(--ink);text-decoration:none}
.proctile:hover{border-color:var(--accent)}
.proctile:hover .procgo{color:var(--accent)}
.procicon{flex:none;width:38px;height:38px;border-radius:9px;display:inline-flex;
  align-items:center;justify-content:center;background:var(--accent-soft);color:var(--accent)}
.procicon .nvi{width:20px;height:20px;stroke-width:1.5}
.procwords{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.procwords b{font-size:15px}
.procwords span{font-size:14px;color:var(--muted);line-height:1.45;display:-webkit-box;
  -webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.procgo{flex:none;font-size:14px;font-weight:650;color:var(--muted)}
@media (max-width:720px){
  .procband{padding:12px 14px;border-radius:10px}
  .procband-head .hint{order:5;flex-basis:100%;margin-top:-4px}
  .proctiles{grid-template-columns:1fr}
  .proctile{min-height:56px}
}
@media (max-width:720px){
  .head > .headtag{order:2;align-self:flex-start;margin-top:5px}
}

/* ===================================================================
   PERSONAS (r174) — the cast, each one reviewable
   =================================================================== */
.pmark{flex:none;vertical-align:-3px;margin-right:5px}
.shot .shotby{position:absolute;top:5px;left:5px;margin:0;border-radius:5px;
  box-shadow:0 0 0 1px rgba(255,255,255,.18)}
.shot.doc .shotby{top:auto;left:auto;bottom:6px;right:6px}   /* the name sits top-left */
.madeby{display:inline-flex;align-self:center}
.madeby .pmark{margin:0}
.mdlabel .pmark{vertical-align:-3px;margin-right:4px}
.tag .pmark{margin:-1px 4px -1px -4px}
.persona .pname .pmark{vertical-align:-7px;margin-right:8px}
.persona .pname{font:600 16px/1.3 system-ui,sans-serif}
.persona .pslug{color:var(--muted);font-size:14px}
.persona .pmeta{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-top:8px}
.precord{margin-top:12px}
div.hint.precord{border-top:1px solid var(--line-2);padding-top:8px}
/* r306: the record is a table. It scrolls sideways on a phone with its first column
   held still, so a row never loses its name. */
/* separate, not collapse: a collapsed border belongs to the table, and the sticky
   cell paints over it as the row scrolls under. */
.ptable table{font-size:14.5px;border-collapse:separate;border-spacing:0}
.ptable th,.ptable td{padding:6px 10px;vertical-align:middle}
.ptable tr > th:first-child{position:sticky;left:0;z-index:1;background:var(--panel);
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:14px}
.ptable tr:first-child th:first-child{font-family:inherit;font-size:13.5px}
.ptable tr:last-child th,.ptable tr:last-child td{border-bottom:0}
.ptable td.preopen{color:var(--q);font-weight:700}
.ptable td.pgreat{color:var(--accent);font-weight:700}
.ptable td.pago{color:var(--muted)}
.ptable .pwho{display:inline-flex;align-items:center;gap:6px;color:var(--ink);
  font:600 15px/1.3 system-ui,sans-serif;text-decoration:none}
.ptable .pwho .pmark{margin:0}
.pcast{margin:18px 0 22px}
.pies{display:grid;gap:12px;grid-template-columns:repeat(2,minmax(0,1fr))}
/* What a close costs, board by board (r981, closeCostBars in stats.html): a
   simple close pale, a complex job dark, one neutral hue (the boards own --sN). */
.ccbars{margin:14px 0;padding:14px 16px;border:1px solid var(--line);border-radius:12px;
  background:var(--card)}
.cchead{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 16px;margin-bottom:10px}
.cchead .pietotal{margin-left:auto}
.cccols{border-top:0;padding-bottom:2px}
.cccol{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--muted)}
.ccsw{display:inline-block;width:14px;height:10px;border-radius:3px;flex:none}
.ccsw.simple,.ccbar.simple i{background:color-mix(in srgb,var(--ink) 30%,transparent)}
.ccsw.job,.ccbar.job i{background:color-mix(in srgb,var(--ink) 78%,transparent)}
.ccrow{display:grid;grid-template-columns:minmax(0,220px) 1fr 1fr;gap:4px 14px;
  align-items:center;padding:5px 0;border-top:1px solid var(--line)}
.ccname{display:flex;align-items:center;gap:8px;min-width:0;font-size:14px}
.ccname a{color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ccname .piedot{flex:none}
.ccbar{display:flex;align-items:center;gap:8px;min-width:0}
.ccbar i{display:block;height:12px;border-radius:3px;flex:none}
.ccv{font-size:13px;font-variant-numeric:tabular-nums;white-space:nowrap}
.ccbar.none .ccv{color:var(--muted);font-style:italic}
@media (max-width:720px){
  .ccrow{grid-template-columns:1fr;gap:3px}
  .cccols{display:flex;flex-wrap:wrap;gap:4px 14px}
  .cccols > :first-child{display:none}
  .cchead .pietotal{margin-left:0}
}
.piefig{background:var(--panel);border:1px solid var(--line);border-radius:10px;
  padding:12px 16px 14px}
.pietitle{font-size:15.5px;font-weight:700}
.pietotal{font-size:14px;color:var(--muted);margin-bottom:6px}
.piebox{position:relative;max-width:230px;margin:0 auto}
.piebox .utip{min-width:130px;white-space:nowrap}
.piebox canvas{display:block}
/* /personas' two donuts of one cast (r800): big, centred, and one legend under
   both that lights a persona in each (lightTogether in app.js). */
.piefig .donut{justify-content:center}
.piefig .piedisc{width:190px;height:190px}
.piefig .piehole b{font-size:28px}
.piefig .piehole span{font-size:13.5px;max-width:110px}
.pielegend.shared{flex-direction:row;flex-wrap:wrap;gap:4px 16px;margin:12px 8px 0}
/* A row is never wider than the legend: the long "other: a, b, c…" row wraps its
   names instead of widening /personas past a 390 phone (r914). */
.pielegend.shared .pieitem{margin:0;font-size:14.5px;flex:0 1 auto;max-width:100%}
.pielegend.shared .piename{flex:0 1 auto;white-space:normal;overflow-wrap:anywhere}
.pielegend.shared.hot .pieitem:not(.on){opacity:.45}
@media (max-width:720px){
  .pies{gap:8px}
  .piefig{padding:10px 10px 12px}
  .piefig .piedisc{width:140px;height:140px}
  .piefig .piehole b{font-size:21px}
  .piefig .piehole span{max-width:80px}
}
.prow{display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:4px 0}
.prow .plabel{flex:0 0 92px;font-size:14px;color:var(--muted);
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.prow.total .plabel{color:var(--ink);font-weight:600}
.prow .nums{flex:1;min-width:0}
.ppromo{border-top:1px solid var(--line-2);margin-top:4px;padding-top:8px}
.plearned .nums{display:flex;flex-wrap:wrap;gap:6px}
.plearned .tag.pbad{text-decoration:line-through;color:var(--q)}
/* Strikes (r779): three pips, red when given; an OUT persona's row is edged red. */
.pstrikes{border-top:1px solid var(--line-2);margin-top:4px;padding-top:8px}
.pstrikes.out{border-left:4px solid var(--danger);padding-left:8px}
.strikepips{display:inline-flex;gap:4px;align-items:center}
.strikepip{width:12px;height:12px;border-radius:50%;border:2px solid var(--danger);opacity:.45}
.strikepip.on{background:var(--danger);opacity:1}
.strikelist{flex-basis:100%;display:flex;flex-direction:column;gap:4px}
.finding.strike.retired{text-decoration:line-through;opacity:.6}
.strikepardon{padding:2px 10px;font-size:13px;margin-left:6px}
.strikegive{display:flex;gap:8px;margin-top:4px}
.strikegive input{flex:1;min-width:0}
.strikebtn{color:var(--danger);border-color:var(--danger)}
.cardstrike{margin-top:8px}
.strikereplace{padding:3px 14px;font-size:14px}
.ppromo button{padding:3px 14px;font-size:14px}
.finding .fnum{color:var(--muted);font-size:13px;margin-right:4px}
.finding .tag{margin:0 5px}
.finding.retired{text-decoration:line-through;text-decoration-color:var(--line)}
details.pforgot{margin-top:8px}
@media (max-width:720px){
  .prow .plabel{flex-basis:100%}
  .prow .nums{margin-top:0}
  .strikegive input{font-size:16px}     /* under 16px iOS zooms on focus */
}

/* /lexicon's colour chart: the board's own card classes, side by side. */
details.colours{margin:0 0 18px;padding:11px 13px;background:var(--panel);
  border:1px solid var(--line);border-radius:11px}
details.colours > summary{margin:0 0 4px;padding:0;text-transform:none;letter-spacing:0;
  font-weight:700;font-size:15.5px;color:var(--ink)}
.chart{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:8px;
  margin-top:10px}
.chart .card{margin:0}
.chart .detail{border-left:0;padding-left:0;max-height:none;white-space:normal}
.chart .meta{margin-top:0}
.chart .meta b{color:var(--ink);font-size:15px}

/* THE COSTLIEST TICKETS on /stats (r398): three a day, the title free to wrap —
   a table would push the dollars off a phone's edge. */
.stattable.costly{padding:4px 0}
.costly-day{padding:10px 14px 2px;font-size:13.5px;font-weight:600;color:var(--muted)}
.costly-row{display:grid;grid-template-columns:1fr auto;gap:2px 12px;
  padding:7px 14px 9px;border-bottom:1px solid var(--line-2)}
.costly-row:last-child{border-bottom:0}
.costly-t{color:var(--ink);text-decoration:none;overflow:hidden;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.costly-t:hover b{text-decoration:underline}
.costly-usd{font-weight:700;font-variant-numeric:tabular-nums;text-align:right}
.costly-h{grid-column:1 / -1;font-size:13.5px;color:var(--muted)}

/* SESSION BY SESSION on /stats (r991, windowBand): one row a 5-hour plan window.
   A close's cost is one neutral ink against a tick at the median (the boards own
   --sN); a window that spent and closed nothing is red and hatched, one over
   twice the median runs amber. The left edge says the same at a glance. */
.winkey{display:flex;flex-wrap:wrap;gap:4px 16px;margin:10px 2px;font-size:13px;color:var(--muted)}
.winkey span{display:inline-flex;align-items:center;gap:6px}
.winsw{display:inline-block;width:14px;height:10px;border-radius:3px;
  background:color-mix(in srgb,var(--ink) 45%,transparent)}
.winsw.tick{width:3px;height:14px;border-radius:1px;background:var(--ink)}
.winsw.costly{background:var(--doing)}
.winsw.barren{background:repeating-linear-gradient(135deg,var(--danger) 0 3px,transparent 3px 6px);
  box-shadow:inset 0 0 0 1px var(--danger)}
.winlist{border:1px solid var(--line);border-radius:12px;background:var(--panel);overflow:hidden}
.winrow{border-top:1px solid var(--line-2);border-left:4px solid transparent}
.winrow:first-child{border-top:0}
.winrow.barren{border-left-color:var(--danger)}
.winrow.costly{border-left-color:var(--doing)}
.winrow.open{border-left-color:var(--live)}
.winsum{display:grid;grid-template-columns:minmax(0,180px) 80px 88px 84px 128px 128px minmax(0,1fr);
  gap:4px 12px;align-items:center;padding:7px 14px 7px 10px;cursor:pointer;list-style:none;
  margin:0;text-transform:none;letter-spacing:0;font-weight:400;font-size:14px;color:var(--ink)}
.winsum::-webkit-details-marker{display:none}
.winsum:hover{background:var(--panel-2)}
.winwhen{display:flex;flex-direction:column;min-width:0}
.winwhen b{font-size:14.5px;white-space:nowrap}
.winwhen b::before{content:"\25B8";display:inline-block;width:10px;margin-right:4px;
  text-align:center;color:var(--muted);transition:transform .15s}
.winrow[open] .winwhen b::before{transform:rotate(90deg)}
.winwhen span{font-size:12.5px;color:var(--muted);padding-left:14px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.winn,.winusd{font-size:13px;color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
.winn b,.winusd b{font-size:15px;color:var(--ink)}
.winrow.barren .winn:nth-child(2) b{color:var(--danger)}
.winbar{display:flex;align-items:center;gap:8px;min-width:0}
.wintrack{position:relative;flex:1;min-width:40px;height:12px}
.wintrack i{position:absolute;left:0;top:0;bottom:0;border-radius:3px;
  background:color-mix(in srgb,var(--ink) 45%,transparent)}
.wintrack s{position:absolute;top:-3px;bottom:-3px;width:2px;margin-left:-1px;background:var(--ink)}
.winrow.costly .wintrack i{background:var(--doing)}
.winbar .ccv{min-width:96px}
.winpicks.none{font-style:italic}
.winpickall{margin:12px 2px 0;font-size:14px;color:var(--muted)}
.winpickall b{color:var(--ink);font-size:15px}
.wintrack,.winbar.none > i{max-width:420px}
.winbar.none > i{flex:1;height:12px;border-radius:3px}
.winrow.barren .winbar.none > i{background:repeating-linear-gradient(135deg,
  color-mix(in srgb,var(--danger) 70%,transparent) 0 3px,transparent 3px 7px);
  box-shadow:inset 0 0 0 1px var(--danger)}
.winrow.barren .winbar .ccv{color:var(--danger);font-weight:600}
.winbar.none .ccv{color:var(--muted);font-style:italic}
.winbody{padding:2px 14px 10px 28px;font-size:14px}
.wintk{display:grid;grid-template-columns:1fr auto;gap:2px 12px;padding:5px 0;
  border-top:1px solid var(--line-2)}
.wintkb{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--muted);
  white-space:nowrap}
.winlead{grid-column:2 / -1;display:flex;flex-wrap:wrap;gap:2px 18px;font-size:13px;
  color:var(--muted)}
.winlead:empty{display:none}
.winlead span{display:inline-flex;flex-wrap:wrap;align-items:center;gap:0 5px}
.winbdn{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
.winlead b{color:var(--ink);font-weight:600;white-space:nowrap}
.winbds{display:grid;grid-template-columns:minmax(0,max-content) auto auto;gap:0 22px;
  margin:4px 0 10px;font-size:13.5px;color:var(--muted);font-variant-numeric:tabular-nums;
  justify-content:start}
.winbd{display:contents}
.winbd > span{padding:3px 0}
.winbd b{color:var(--ink);font-size:14px}
.winbdh > span{font-size:12px;text-transform:uppercase;letter-spacing:.04em}
.winbdn a{color:var(--ink);overflow:hidden;text-overflow:ellipsis}
@media (max-width:720px){
  .winlead{grid-column:1 / -1}
  .winsum{grid-template-columns:repeat(3,auto) 1fr;gap:4px 12px;padding:9px 12px 10px 8px}
  .winwhen{grid-column:1 / 4}
  .winusd{grid-column:4;grid-row:1;text-align:right;align-self:start}
  .winpicks{grid-column:4;text-align:right}
  .winbar{grid-column:1 / -1}
  .winbody{padding:2px 12px 10px 14px}
  .wintk{grid-template-columns:1fr}
}

/* HOW FULL THE PLAN IS (r553) — home's plan band, between the summary and the
   boards. One block per MACHINE reporting, one row per window. It sits where
   Simon reads before deciding what to start: a weekly window at 80% is the fact
   that changes what a morning is spent on. The ceiling is drawn ON the bar, so
   "the board stops at 90" is a line you can see the bar approaching rather than
   a number in a sentence. */
.plan{margin:14px 0 4px;background:var(--panel);border:1px solid var(--line);
  border-left:5px solid var(--accent);border-radius:12px;padding:12px 18px;
  box-shadow:var(--shadow)}
.planhost + .planhost{margin-top:12px;padding-top:10px;border-top:1px solid var(--line-2)}
/* ONE grid per machine, its rows on subgrid (r590): each row sized its own `auto`
   reset column, so "resets 01:10 PM" left the 5-hour bar longer than the week's
   "resets Wed 06:00 AM", and the ceiling marks stood at different places. */
.planhost{display:grid;grid-template-columns:8.5rem 1fr 3.2rem auto;column-gap:10px}
.planhead{grid-column:1 / -1;display:flex;align-items:baseline;gap:2px;flex-wrap:wrap;margin-bottom:7px}
.planhead b{font-size:15px}
/* Not the tag card's .warn box (above): a word in the line, not a boxed alert. */
.planhead .hint.warn{color:var(--doing);margin:0;padding:0;background:none;border:0;
  font-size:inherit}
.planstop{margin-left:8px;background:var(--doing-soft);color:var(--doing);font-weight:700;
  border-radius:999px;padding:1px 10px;font-size:13px}
.planrow{grid-column:1 / -1;display:grid;grid-template-columns:subgrid;row-gap:10px;
  align-items:center;padding:3px 0}
.planrow.scoped{opacity:.72}                 /* a per-model window gates nothing */
.planwhat{color:var(--muted);font-size:13.5px}
.planrow .bar{position:relative;height:9px;border-radius:99px;background:var(--line);
  overflow:visible}
.planrow .bar i{display:block;height:100%;border-radius:99px;background:var(--accent)}
.planrow .bar.near i{background:var(--doing)}
.planrow .bar.stop i{background:var(--danger)}
/* The ceiling mark: a hairline standing across the bar where the worker stops. */
.planrow .bar .ceil{position:absolute;top:-3px;bottom:-3px;width:2px;
  background:var(--ink-2);opacity:.55;border-radius:2px}
.planpct{font-variant-numeric:tabular-nums;text-align:right}
.planpct.near{color:var(--doing)}
.planpct.stop{color:var(--danger)}
.planwhen{color:var(--muted);font-size:13px;white-space:nowrap}
/* On a phone the label and the reset move under the bar rather than squeezing
   it to nothing: the bar is the part that is read at a glance. */
@media (max-width:720px){
  .plan{padding:10px 12px}
  .planhost{grid-template-columns:1fr 3.2rem}
  .planrow{row-gap:4px}
  .planwhat{grid-column:1 / -1}
  .planwhen{grid-column:1 / -1;font-size:12.5px}
}

/* THE DOCTRINE SCREEN (r656): three bands, strings under the cards. The SVG sits
   behind them (z-index), so a card's opaque panel is what a string passes under. */
.dopts{align-items:center;gap:10px;flex-wrap:wrap;margin-top:10px}
.dnote{margin:14px 0 0;padding:10px 14px;border-radius:10px;background:var(--doing-soft);
  color:var(--ink);border:1px solid var(--line)}
.dgraph{position:relative}
.dstrings{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:visible}
.dstr{fill:none;stroke:var(--line);stroke-width:1.6;transition:stroke .15s,opacity .15s}
.dstr.bad{stroke:var(--danger);stroke-dasharray:5 4}
.dstr.lit{stroke:var(--accent);stroke-width:2.6}
.dstr.dim{opacity:.18}
.dband{position:relative;z-index:1;margin-bottom:34px}
.dband .sect{margin-top:22px}
.dcards{display:flex;flex-wrap:wrap;gap:14px;justify-content:center}
.dcard{position:relative;flex:0 1 250px;min-width:0;background:var(--panel);border:1px solid var(--line);
  border-radius:10px;padding:10px 12px;box-shadow:var(--shadow);cursor:pointer;
  transition:opacity .15s,border-color .15s}
.dband[data-layer="tactics"] .dcard{flex-basis:190px}
.dcard.dim{opacity:.32}
.dcard.lit{border-color:var(--accent)}
.dcard.pinned{box-shadow:0 0 0 2px var(--accent)}
.dcard.dangles{border-color:var(--danger)}
.dctop{display:flex;align-items:center;gap:8px;margin-bottom:4px}
.did{font-size:13px;color:var(--muted);letter-spacing:.02em}
.dmark{font-size:12px;font-weight:700;padding:0 8px;border-radius:999px}
.dmark.added{background:var(--accent-soft);color:var(--accent)}
.dmark.changed{background:var(--doing-soft);color:var(--doing)}
.dmark.struck{background:var(--paused-soft);color:var(--danger)}
.dcard.added{border-left:4px solid var(--accent)}
.dcard.changed{border-left:4px solid var(--doing)}
.dcard.struck .dtitle{text-decoration:line-through;color:var(--muted)}
.dtitle{font-size:14.5px;line-height:1.35;font-weight:600;color:var(--ink)}
.dbody summary{font-size:13px;color:var(--muted);margin-top:6px;cursor:pointer}
.dtext{white-space:pre-wrap;font-size:13.5px;line-height:1.45;color:var(--ink-2);margin-top:4px}
.dlinks{display:none;font-size:13px;color:var(--muted);margin-top:6px}
.dref{color:var(--todo);font-weight:600}
.dbad{font-size:13px;color:var(--danger);font-weight:600;margin-top:6px}
.dhint{font-size:12.5px;color:var(--muted);margin-top:4px;font-style:italic}
.dnone{color:var(--muted);font-size:14px;padding:6px 0}
/* The decisions under a line (r681): what served it, what doubts it. */
.ddec{margin-top:8px;padding-top:6px;border-top:1px dashed var(--line);font-size:13px}
.ddlbl{display:block;color:var(--muted);margin-bottom:3px}
.ddrefs{display:flex;flex-wrap:wrap;gap:4px 8px}
.dtick{color:var(--todo);font-weight:600;text-decoration:none}
.dtick:hover{text-decoration:underline}
.dtick.open{color:var(--danger)}
.ddmore{color:var(--muted)}
/* The Commissar's verdicts (r672), under the tactics: a ruling a row. */
.dverdicts .dvlist,.dmarks .dvlist,.dscans .dvlist{display:flex;flex-direction:column;gap:8px}
.dverdict,.dscan{background:var(--panel);border:1px solid var(--line);border-left:4px solid var(--line);
  border-radius:10px;padding:8px 12px}
.dverdict.upheld{border-left-color:var(--accent)}
.dverdict.struck{border-left-color:var(--danger)}
.dverdict.referred{border-left-color:var(--doing)}
/* Scanned (r718): Simon's COMPLEX tickets as the Commissar read them. */
.dscan.upheld{border-left-color:var(--accent)}
.dscan.struck{border-left-color:var(--danger)}
.dscan.due{border-left-color:var(--q)}
.dvtop{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;font-size:13px;color:var(--muted)}
.dvwhat{color:var(--ink);letter-spacing:.03em}
.dvat{margin-left:auto}
.dvwhy{white-space:pre-wrap;font-size:13.5px;line-height:1.45;color:var(--ink-2);margin-top:4px}
.dheld.on{color:var(--doing);font-weight:600}
/* Marked for review (r674): both verdicts on a mark, and yours to give. */
.drev{background:var(--panel);border:1px solid var(--line);border-left:4px solid var(--line);
  border-radius:10px;padding:8px 12px}
.drev.due{border-left-color:var(--q)}
.drev.upheld{border-left-color:var(--accent)}
.drev.struck{border-left-color:var(--danger)}
.dmwho{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;font-size:13.5px;margin-top:6px}
.dmname{min-width:80px;color:var(--muted);font-size:13px}
.dmv.upheld{color:var(--accent)}
.dmv.struck{color:var(--danger)}
.dmwhy{color:var(--ink-2)}
.dmwait{color:var(--muted)}
.dmitem{color:var(--ink);font-weight:600}
.dmagree{font-size:13px;margin-top:6px}
.dmagree.no{color:var(--danger)}
.dmagree.yes{color:var(--accent)}
.dmjudge{margin-top:8px}
.dmjudge .dmwhyin{flex:1;min-width:160px}
@media (max-width:720px){ .dmjudge .dmwhyin{font-size:16px;min-width:100%} }
/* ...and not ornament: it stays on a narrow phone, where .quick .opts .hint goes. */
@media (max-width:400px){ .quick .opts .dheld.on{display:inline} }
/* A phone: no strings, the cites said on each card, and tappable. */
@media (max-width:720px){
  .dstrings{display:none}
  .dlinks{display:block}
  .dcard{flex:1 1 100%}
  .dband[data-layer="tactics"] .dcard{flex-basis:100%}
  .dcards{gap:10px}
}

/* THE PANEL (r734): a board's home, a tile per part of it (r755, Tiles). Each
   part keeps one colour (--sec) and the nav's icon for its screen; its border is
   that colour, lighter, and the title and every figure are links. */
.panadd{display:flex;gap:8px;margin-top:8px}
.panadd textarea{flex:1;resize:none;font:inherit;font-size:15px}
@media (max-width:720px){.panadd textarea{font-size:16px}}
.panhero{display:flex;gap:14px;align-items:center}
/* The new-ticket card (r791): its own spot under the title card, headed like a
   tile and wearing the Add button's colour. No hover lift: it holds a textarea. */
.panticket{--sec:var(--accent);margin-bottom:12px;padding:12px 14px 14px;
  border-color:color-mix(in srgb,var(--sec) 38%,transparent);border-top:4px solid var(--sec);
  background:linear-gradient(color-mix(in srgb,var(--sec) 8%,var(--panel)),var(--panel) 80%)}
.panthead{display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap}
.panthead .pantitle{font-size:17px;font-weight:650;background:none}
.panthint{color:var(--muted);font-size:13.5px}
.panid{margin-bottom:12px}
.panicon{display:inline-grid;place-items:center;width:34px;height:34px;border-radius:10px;
  flex:none;color:var(--sec);background:color-mix(in srgb,var(--sec) 18%,transparent);
  transition:background .18s,color .18s}
.panicon .nvi{width:19px;height:19px;stroke-width:1.5}
.panicon.big{--sec:var(--accent);width:52px;height:52px;border-radius:14px}
.panicon.big .nvi{width:28px;height:28px}
/* The board's own mark in the hero (r848), the size the kind icon had. */
.bmark.panmark{width:52px;height:52px;border-radius:14px;font-size:26px}
.panname{font-size:22px;font-weight:700;line-height:1.2}
.panabout{color:var(--muted);font-size:14.5px;margin-top:2px}
/* The boards it is tied to (r768): a link each to that board's panel, wearing the
   same stripe as Home's rows, and the counts behind it. */
.panfam{display:flex;flex-direction:column;gap:8px;margin:12px 0 2px 66px}
.panfamrow{display:grid;grid-template-columns:auto 1fr;align-items:start;gap:8px 12px}
.panfamrow>.panlabel{margin:0;padding-top:11px}
.panfamlinks{display:flex;flex-wrap:wrap;gap:8px}
.panboard{--stripew:4px;--stripr:9px;--stripex:-1px;--stripey:-1px;position:relative;isolation:isolate;
  display:inline-flex;align-items:center;gap:8px;padding:6px 12px 6px 10px;border-radius:9px;
  border:1px solid var(--line);background:var(--panel-2);color:var(--ink);
  text-decoration:none;font-size:14.5px;transition:transform .15s,border-color .15s}
.panboard:hover{transform:translateY(-1px);border-color:var(--accent)}
.panbicon{display:inline-grid;place-items:center;width:24px;height:24px;border-radius:7px;flex:none;
  color:var(--accent);background:color-mix(in srgb,var(--accent) 16%,transparent)}
.panbicon .nvi{width:15px;height:15px;stroke-width:1.6}
.panbname{font-weight:650}
.panboard em{font-style:normal;font-size:13px;color:var(--muted)}
.panboard em b{font-weight:700;color:var(--ink)}
.panboard em.q b{color:var(--q)}
.panboard em.doing b{color:var(--doing)}
.panboard .agdots{display:none}
@media (max-width:720px){.panfam{margin-left:0}.panfamrow{grid-template-columns:1fr}
  .panboard{font-size:15px}}

.pantiles{display:flex;flex-direction:column;gap:12px;margin-top:12px}
.panrow{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
#pan-work,#pan-stats,.panrow[data-n="3"] #pan-lexicon{grid-column:span 2}
/* The week's cost is the tallest tile: the shelf and the doctrine stack beside it.
   A doctrine that is QUOTED (r783) is the tall one instead, in the same place:
   beside the week, with the shelf under the week. */
.panrow #pan-stats{grid-row:span 2}
.panrow:has(#pan-stats) #pan-programs,.panrow:has(#pan-stats) #pan-doctrine{grid-column:span 2}
/* With Assets (r894) the shelf and the assets share the half under the week. */
.panrow:has(#pan-assets) #pan-programs{grid-column:span 1}
.panrow:has(#pan-assets) #pan-programs .panfig{min-width:0;padding-inline:10px}
.panrow:has(.panverses) #pan-stats{grid-row:auto}
.panrow #pan-doctrine:has(.panverses){grid-row:span 2}
/* THE DOCTRINE AS SCRIPTURE (r783): each line a verse, in a book face, its
   number set small in the tile's colour, a quiet gloss under it. */
.panverses{position:relative;display:flex;flex-direction:column;gap:14px;margin:6px 0 4px;flex:1;
  justify-content:space-evenly;
  padding:4px 4px 0 0}
.panverses::before{content:"\201C";position:absolute;right:-6px;top:-62px;font:
  700 110px/1 Georgia,serif;color:color-mix(in srgb,var(--sec) 16%,transparent);pointer-events:none}
.panverse{position:relative;display:block;padding-left:30px;color:var(--ink);text-decoration:none;
  border-radius:8px;transition:color .15s}
.panverse q{font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  font-style:italic;font-size:17px;line-height:1.42;quotes:"\201C" "\201D"}
.panverse .vnum{position:absolute;left:0;top:1px;width:22px;text-align:right;
  font-family:Georgia,serif;font-size:15px;font-weight:700;color:var(--sec)}
.panverse .vgloss{display:block;margin-top:3px;font-size:13.5px;line-height:1.4;color:var(--muted)}
.panverse:hover q{color:var(--sec)}
.pantile{--sec:var(--muted);position:relative;min-width:0;border-radius:12px;padding:14px 16px 16px;
  border:1px solid color-mix(in srgb,var(--sec) 38%,transparent);border-top:4px solid var(--sec);
  background:linear-gradient(color-mix(in srgb,var(--sec) 10%,var(--panel)),var(--panel) 70%);
  transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease}
/* A tile that holds only figures puts them at its foot, level with its neighbours'. */
.pantile.foot{display:flex;flex-direction:column}
.pantile.foot .pantop{align-self:flex-start}
.pantile.foot .panfigs:last-child{margin-top:auto;padding-top:12px}
.pantile:hover{transform:translateY(-2px);border-color:color-mix(in srgb,var(--sec) 75%,transparent);
  border-top-color:var(--sec);box-shadow:0 10px 26px -12px color-mix(in srgb,var(--sec) 55%,transparent)}
.pantile[data-sec=work]{--sec:var(--todo)}
.pantile[data-sec=workers]{--sec:var(--live)}
.pantile[data-sec=stats]{--sec:var(--doing)}
.pantile[data-sec=tags]{--sec:var(--note)}
.pantile[data-sec=personas]{--sec:var(--q)}
.pantile[data-sec=doctrine]{--sec:var(--accent)}
.pantile[data-sec=lexicon]{--sec:var(--s2)}
.pantile[data-sec=contexts]{--sec:var(--s7)}
.pantile[data-sec=programs]{--sec:var(--s8)}
.pantile[data-sec=assets]{--sec:var(--s1)}
/* ASSETS (r894): each one a row wearing its kind's colour and icon, as on /assets. */
.panassets{display:flex;flex-direction:column;gap:6px;margin-top:12px}
.panasset{display:flex;align-items:center;gap:9px;padding:4px 10px 4px 5px;border-radius:9px;
  color:var(--ink);text-decoration:none;border:1px solid color-mix(in srgb,var(--k) 30%,transparent);
  background:color-mix(in srgb,var(--k) 7%,transparent)}
.panasset:hover{border-color:var(--k)}
.paskind{flex:none;display:grid;place-items:center;width:26px;height:26px;border-radius:8px;
  color:var(--k);background:color-mix(in srgb,var(--k) 16%,transparent)}
.paskind .nvi{width:16px;height:16px}
.pastext{flex:1;min-width:0;font-weight:650;font-size:14.5px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.pashow{flex:none;font-size:12.5px;color:var(--muted)}
/* Upkeep was the one gray tile, and chores are what most needs the colour (r786). */
.pantile[data-sec=upkeep]{--sec:var(--s3)}
/* QUICK ACTIONS (r803): a row of its own, above the week. A button each, tinted
   like a figure, the icon in the tile's rose (amber is the week's, just under
   it); a starred one wears the star's amber, as on its own tab. */
.pantile[data-sec=quick]{--sec:var(--s5)}
.panrow #pan-quick{grid-column:1/-1}
.pantop.plain .pantitle{background:none}
.pantop.plain:hover .panicon{background:color-mix(in srgb,var(--sec) 18%,transparent);color:var(--sec)}
.panquick{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
.qbtn{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;border-radius:10px;
  font:inherit;font-size:15px;color:var(--ink);text-decoration:none;cursor:pointer;
  border:1px solid color-mix(in srgb,var(--sec) 55%,transparent);
  background:linear-gradient(transparent 20%,color-mix(in srgb,var(--sec) 26%,transparent));
  transition:border-color .15s,transform .15s,box-shadow .15s}
.qbtn .nvi{width:17px;height:17px;color:var(--sec)}
.qbtn:hover:not(:disabled),.qbtn:focus-visible{border-color:var(--sec);outline:none;
  transform:translateY(-1px);box-shadow:0 6px 16px -8px color-mix(in srgb,var(--sec) 70%,transparent)}
.qbtn.star{position:relative;padding-right:22px}
.qbtn.star::after{content:"\2605";position:absolute;right:7px;top:3px;font-size:10px;color:var(--s4)}
.qbtn:disabled{opacity:.5;cursor:default}
.pantile .pannote a{color:var(--ink);text-decoration-color:var(--sec)}
@media (max-width:720px){.qbtn{min-height:44px;flex:1 1 auto;justify-content:center}}

/* The title is the link: no arrow, an underline that draws itself on hover. */
.pantop{display:inline-flex;align-items:center;gap:10px;color:var(--ink);text-decoration:none;
  font-size:17px;font-weight:650;line-height:1.3;border-radius:10px}
.pantitle{background:linear-gradient(var(--sec),var(--sec)) 0 100%/0 2px no-repeat;
  transition:background-size .22s ease;padding-bottom:1px}
.pantop:hover .pantitle,.pantop:focus-visible .pantitle{background-size:100% 2px}
.pantop:hover .panicon,.pantop:focus-visible .panicon{background:var(--sec);color:var(--panel)}
.pantop:focus-visible{outline:2px solid var(--sec);outline-offset:3px}

/* A figure is the way to what it counts, drawn as a button (r764). Its tint is
   the tile's own gradient turned upside down: the tile fades from its colour at
   the top, a button fills with it toward the bottom, so the eye lands on what
   can be pressed. A zero is only outlined, since nothing is behind it. */
.panfigs{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
.panfigs + .panfigs{margin-top:8px}
.panfig{display:block;min-width:74px;padding:6px 12px 7px;border-radius:10px;color:var(--ink);
  text-decoration:none;border:1px solid color-mix(in srgb,var(--sec) 55%,transparent);
  background:linear-gradient(transparent 20%,color-mix(in srgb,var(--sec) 30%,transparent));
  transition:border-color .15s,transform .15s,box-shadow .15s}
.panfig:hover,.panfig:focus-visible{border-color:var(--sec);outline:none;transform:translateY(-1px);
  box-shadow:0 6px 16px -8px color-mix(in srgb,var(--sec) 70%,transparent),
             inset 0 -24px 26px -18px color-mix(in srgb,var(--sec) 45%,transparent)}
.panfig.zero{background:transparent;border-color:var(--line-2)}
.panfig.zero b{color:var(--muted)!important}
.panfig b{display:block;font-size:34px;font-weight:700;line-height:1.05;
  font-variant-numeric:tabular-nums;color:var(--ink)}
.panfig span{font-size:13.5px;color:var(--muted)}
.panfig:hover span{color:var(--ink)}
.panfigs :where(.panfig:first-child:not(.sm)) b{color:var(--sec)}
.panfigs .panfig.todo b{color:var(--todo)}
.panfigs .panfig.doing b{color:var(--doing)}
.panfigs .panfig.q b{color:var(--q)}
.panfig.sm{display:flex;align-items:baseline;gap:5px;min-width:0;padding:3px 10px}
.panfig.sm b{display:inline;font-size:17px;font-weight:650}
.pannote{font-size:14px;color:var(--muted);margin-top:8px;line-height:1.45}
.panlabel{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);margin:14px 0 6px}
.pantile .tagacts{margin-top:10px}
a.panmore{display:inline-block;margin-top:10px;font-size:14px;color:var(--ink);text-decoration:none;
  padding:5px 10px;border-radius:8px;border:1px solid color-mix(in srgb,var(--sec) 40%,transparent);
  transition:background .15s}
a.panmore:hover{background:color-mix(in srgb,var(--sec) 16%,transparent)}
/* What is due, as a list you read: a name is the way to it, never a button. */
.pandue{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-direction:column;gap:4px}
.pandue a{display:block;position:relative;padding-left:15px;color:var(--ink);text-decoration:none;
  font-size:14.5px;line-height:1.35}
.pandue a::before{content:"";position:absolute;left:0;top:.5em;width:7px;height:7px;
  border-radius:50%;background:var(--doing)}
.pandue em{margin-left:6px;white-space:nowrap}
.pandue a:hover span{text-decoration:underline;text-decoration-color:var(--sec)}
.pandue em{font-style:normal;font-size:12.5px;color:var(--muted)}

/* ONE BOARD'S WEEK (r764, weekCost in app.js): the share, then a bar a day for
   what a session, a simple close and a complex job cost (r900), the every-board
   figure a dashed line. Three across; in a narrow box (a phone, the panel's
   tile) the session takes a row and the two closes share the next. */
.wkcost{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:14px 18px;margin-top:12px;
  --wk:var(--sec,var(--doing));container-type:inline-size}
.wkunit{grid-column:span 2}
@container (max-width:640px){
  .wkunit{grid-column:span 3}
  .wkshare + .wkunit{grid-column:1/-1}
}
.wkshare{grid-column:1/-1}
.wkshare,.wkunit{display:block;min-width:0;color:var(--ink);text-decoration:none}
.wkunit{padding-top:10px;border-top:1px solid var(--line-2)}
a.wkshare:hover .wktop span,a.wkunit:hover .wktop span{text-decoration:underline;
  text-decoration-color:var(--wk)}
.wktop{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.wktop b{font-size:30px;font-weight:700;line-height:1.05;color:var(--wk);font-variant-numeric:tabular-nums}
.wktop span{font-size:14px;color:var(--ink)}
.wkhint{font-size:12.5px;color:var(--muted);margin-top:6px;line-height:1.35}
.wkbar{height:10px;border-radius:999px;margin-top:8px;background:var(--line-2);overflow:hidden}
.wkbar i{display:block;height:100%;border-radius:999px;background:var(--wk)}
.wkbars{position:relative;display:flex;align-items:flex-end;gap:4px;height:46px;margin-top:8px;
  border-bottom:1px solid var(--line-2)}
.wkbars i{flex:1;border-radius:3px 3px 0 0;background:color-mix(in srgb,var(--wk) 55%,transparent)}
.wkbars i.today{background:var(--wk)}
.wkcell{display:inline-flex;align-items:center;gap:8px;--wk:var(--doing)}
.wkcell .wkbar{width:80px;margin:0;height:8px}
.wkcell > span:last-child{min-width:3ch;text-align:right}
.statband > .wkcost{--wk:var(--doing)}
.wkcost.wide .wkunit{grid-column:1/-1}
.wkcost.wide .wkbars{gap:1px;height:56px}
.wkcost.wide .wkbars i{border-radius:2px 2px 0 0}
.wkbars em{position:absolute;left:0;right:0;border-top:1.5px dashed var(--ink);opacity:.55;pointer-events:none}

/* The sessions up, and the cast: each in its own colour. */
.panwho{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.panwho .pmark.idle{opacity:.45}
.panwho .pmark.busy{box-shadow:0 0 0 2px var(--sec);border-radius:5px}
.panwho.names{gap:6px}
.pchip{display:inline-flex;align-items:center;gap:5px;font-size:13.5px;font-weight:600;
  color:var(--c);padding:2px 8px 2px 3px;border-radius:999px;
  background:color-mix(in srgb,var(--c) 14%,transparent);
  border:1px solid color-mix(in srgb,var(--c) 40%,transparent)}
a.pchip{text-decoration:none;transition:background .15s,border-color .15s,transform .15s}
a.pchip:hover,a.pchip:focus-visible{background:color-mix(in srgb,var(--c) 26%,transparent);
  border-color:var(--c);transform:translateY(-1px)}

/* A donut with its total in the hole, and a legend that names each slice
   (donut() in app.js). A slice and its legend row light together (r788). */
.donut{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.piedisc{position:relative;width:112px;height:112px;flex:none}
.piesvg{width:100%;height:100%;display:block;overflow:visible}
.pieslice{transition:stroke-width .18s,opacity .18s}
.pieslice.go{cursor:pointer}
.pieslice.on{stroke-width:22}
.donut.hot .pieslice:not(.on){opacity:.28}
.pietrack{fill:none;stroke:var(--line-2);stroke-width:16}
.piehole{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;
  justify-content:center;pointer-events:none}
.piehole b{font-size:20px;font-weight:700;line-height:1;font-variant-numeric:tabular-nums;
  transition:color .18s}
.donut.hot .piehole b{color:var(--c)}
.piehole span{font-size:12px;color:var(--muted);max-width:64px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.pielegend{flex:1;min-width:120px;display:flex;flex-direction:column;gap:1px}
.pieitem{display:flex;align-items:center;gap:6px;font-size:13.5px;min-width:0;
  padding:2px 6px;margin:0 -6px;border-radius:7px;color:inherit;text-decoration:none;
  transition:background .18s,opacity .18s}
.pieitem.on{background:color-mix(in srgb,var(--c) 20%,transparent)}
.donut.hot .pieitem:not(.on){opacity:.45}
.piedot{width:10px;height:10px;border-radius:3px;background:var(--c);flex:none;transition:transform .18s}
.pieitem.on .piedot{transform:scale(1.3)}
.piename{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink)}
.pieitem .pmark + .piename{color:var(--c);font-weight:600}
.pieitem.on .piename{font-weight:700}
.pieitem em{font-style:normal;color:var(--muted);font-variant-numeric:tabular-nums}
.pieitem.on em{color:var(--ink)}

/* Doctrine's lines and the newest words, each a way in. */
.panlines{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:2px 16px;margin-top:8px}
a.panline{display:flex;gap:8px;padding:5px 8px;margin:0 -8px;border-radius:8px;color:var(--ink);
  text-decoration:none;font-size:14.5px;line-height:1.4;transition:background .15s}
a.panline b{color:var(--sec);flex:none}
a.panline:hover{background:color-mix(in srgb,var(--sec) 14%,transparent)}
.panwords{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:6px}
a.panword{display:block;padding:6px 9px;border-radius:8px;text-decoration:none;color:var(--ink);
  border:1px solid color-mix(in srgb,var(--sec) 30%,transparent);transition:background .15s}
a.panword:hover{background:color-mix(in srgb,var(--sec) 14%,transparent)}
a.panword b{display:block;font-size:14.5px}
a.panword span{display:block;font-size:13px;color:var(--muted);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}

@media (prefers-reduced-motion:reduce){.pantile,.pantile:hover{transition:none;transform:none}}
@media (max-width:720px){
  .panfig b{font-size:28px}
  .panname{font-size:19px}
  .panrow{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .pantile{grid-column:span 2;padding:12px 13px 14px}
  .panrow #pan-stats{grid-row:auto}
  #pan-upkeep,#pan-workers,.panrow:has(#pan-stats) #pan-programs,
  .panrow:has(#pan-stats) #pan-doctrine{grid-column:auto}
  /* Quoted, the doctrine takes the width, and so does the shelf it leaves. */
  .panrow:has(#pan-stats) #pan-doctrine:has(.panverses),
  .panrow:has(#pan-stats):has(.panverses) #pan-programs{grid-column:span 2;grid-row:auto}
  .panverse q{font-size:17px}
  .panfig{min-width:0;padding:5px 10px 6px}
  .wktop b{font-size:24px}
  .wkunit .wktop{flex-direction:column;gap:0}
  .panrow[data-n="3"] #pan-lexicon{grid-column:span 2}
}

/* PAGES FADE (r766, pageReveal/pageLeaves in app.js): a screen's content fades
   in once it has drawn and out when a link leaves it.
   HIDDEN FROM THE FIRST PAINT (r766, reopened): the rule used to wait for
   html:has(script[src="/app.js"]), and that tag is the last in the body, so a
   page painted its first boxes at full strength, then faded them OUT when the
   parser reached it, then in again. tools/transition_film.py filmed it. The only
   page without app.js, login.html, is born .pgshown.
   THE BAR STAYS (r766, reopened twice): the nav, the board picker and Find are
   the same bar on every screen with a board, so fading them emptied the header
   to its logo on each click and redrew it, the picker changing shape as the
   board list came in. Between two such screens the header is handed over
   (headKeep in app.js, web/headkeep.js) and html.pgkeep leaves it alone: only
   the buttons that belong to the screen fade. Anywhere else (home, /focus) the
   whole header but its bar and logo fades, as they differ. The :not(#_)
   outranks button.primary's own transition (r314), so its hover cues are
   repeated here. */
html:not(.pgshown) :is(main, header > :not(h1):not(nav):not(.navfind):not(#_)),
html:not(.pgshown):not(.pgkeep) :is(header > nav, header > .navfind, header h1 > :not(.wordmark)){opacity:0}
main, header > :not(h1):not(#_), header h1 > :not(.wordmark){transition:opacity .24s ease,background-color .12s,
  border-color .12s,box-shadow .12s,transform .12s}
html.pgout :is(main, header > :not(h1):not(nav):not(.navfind):not(#_)),
html.pgout:not(.pgkeep) :is(header > nav, header > .navfind, header h1 > :not(.wordmark)){opacity:0;transition-duration:.15s}
@media (prefers-reduced-motion:reduce){
  html:not(.pgshown) :is(main, header > :not(h1):not(#_), header h1 > :not(.wordmark)){opacity:1}
  main, header > :not(h1):not(#_), header h1 > :not(.wordmark){transition:none}
}

/* /UPKEEP (r786): the chores, made fun to look at. Each routine its own colour
   (--sec, set per card from CHORE in upkeep.html) and icon; a bar that fills as
   its clock runs out and goes striped once it is due; one hero with a ring of
   how much is fresh and the press that queues everything due. */
.uphero{margin:6px 0 14px}
.upheroin{--sec:var(--accent);display:grid;grid-template-columns:auto 1fr auto;gap:22px;align-items:center;
  padding:18px 22px;border-radius:16px;border:1px solid color-mix(in srgb,var(--sec) 40%,transparent);
  background:radial-gradient(120% 140% at 0 0,color-mix(in srgb,var(--sec) 20%,var(--panel)),var(--panel) 62%)}
.upheroin.due{--sec:var(--doing)}
.upheroin h2{margin:0 0 4px;text-transform:none;font-size:22px;font-weight:700;letter-spacing:-.01em}
.upheroin .hint{margin:0;max-width:62ch}
.upring{--pct:0;width:92px;height:92px;border-radius:50%;display:grid;place-content:center;text-align:center;
  background:radial-gradient(closest-side,var(--panel) 76%,transparent 78%),
    conic-gradient(var(--accent) calc(var(--pct)*1%),color-mix(in srgb,var(--doing) 55%,transparent) 0)}
.upring b{font-size:22px;line-height:1}
.upring span{font-size:12px;color:var(--muted)}
.upchips{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.upchip{display:inline-flex;align-items:center;gap:6px;padding:3px 10px 3px 7px;border-radius:999px;
  font-size:13px;color:var(--ink);text-decoration:none;border:1px solid color-mix(in srgb,var(--sec) 60%,transparent);
  background:color-mix(in srgb,var(--sec) 16%,transparent)}
.upchip .nvi{width:14px;height:14px;color:var(--sec)}
.upchip.queued{opacity:.6;background:none}
.upchip:hover{background:color-mix(in srgb,var(--sec) 30%,transparent)}
.upall{display:inline-flex;align-items:center;gap:8px;font-size:15px;padding:10px 18px;border-radius:12px;
  white-space:nowrap}
.upall .nvi{width:14px;height:14px;fill:currentColor}

.upgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
.upcard{--sec:var(--muted);position:relative;min-width:0;display:flex;flex-direction:column;gap:8px;
  padding:14px 16px 14px;border-radius:14px;border:1px solid color-mix(in srgb,var(--sec) 35%,transparent);
  border-top:4px solid var(--sec);
  background:linear-gradient(color-mix(in srgb,var(--sec) 11%,var(--panel)),var(--panel) 65%);
  transition:transform .18s ease,box-shadow .18s ease}
.upcard:hover{transform:translateY(-2px);box-shadow:0 12px 28px -14px color-mix(in srgb,var(--sec) 60%,transparent)}
.upcard.fresh{background:linear-gradient(color-mix(in srgb,var(--sec) 5%,var(--panel)),var(--panel) 50%)}
.uphead{display:flex;align-items:center;gap:12px}
.upicon{flex:none;display:grid;place-content:center;width:38px;height:38px;border-radius:11px;
  color:var(--sec);background:color-mix(in srgb,var(--sec) 18%,transparent)}
.upicon .nvi{width:20px;height:20px}
.upcard.due .upicon{background:var(--sec);color:var(--panel)}
.uptitle{flex:1;min-width:0;display:flex;flex-direction:column}
.uptitle b{font-size:17px;font-weight:650}
.uptitle span{font-size:12.5px;color:var(--muted)}
.upstamp{flex:none;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  padding:3px 9px;border-radius:999px;border:1px solid currentColor}
.upstamp.d{color:var(--doing);background:var(--doing-soft);transform:rotate(-3deg)}
.upstamp.f{color:var(--accent);border-color:transparent;background:var(--accent-soft)}
.upstamp.q{color:var(--live);background:var(--live-soft);text-transform:none;letter-spacing:0}
.upstamp.q .mdlink{color:inherit;font-weight:700}
.upbar{height:8px;border-radius:99px;background:color-mix(in srgb,var(--sec) 14%,transparent);overflow:hidden}
.upbar i{display:block;height:100%;border-radius:inherit;background:var(--sec);transition:width .5s ease}
.upcard.due .upbar i{background:repeating-linear-gradient(-45deg,var(--sec) 0 7px,
  color-mix(in srgb,var(--sec) 60%,var(--panel)) 7px 14px);background-size:20px 20px;
  animation:upstripe 1.2s linear infinite}
@keyframes upstripe{to{background-position:20px 0}}
@media (prefers-reduced-motion:reduce){.upcard.due .upbar i{animation:none}.upcard:hover{transform:none}}
.upwhen{font-size:12.5px;color:var(--muted);margin-top:-3px}
.upcard.due .upwhen{color:var(--doing);font-weight:600}
.upabout{line-height:1.45}
.uplast{font-size:13px;color:var(--muted);border-left:2px solid color-mix(in srgb,var(--sec) 50%,transparent);
  padding-left:9px}
.upcard .why{margin:0}
.upacts{display:flex;gap:10px;align-items:center;margin-top:auto;padding-top:4px}
.upcard .upacts .primary{background:var(--sec);border-color:var(--sec);color:var(--panel)}
@media (max-width:720px){
  .upheroin{grid-template-columns:auto 1fr;padding:16px}
  .upall{grid-column:1/-1;justify-content:center}
  .upring{width:76px;height:76px}
  .upgrid{grid-template-columns:1fr}
}

/* THE SIDE DOCK (r836, sideDock in app.js): a tab on the right edge of every
   screen, the plan's 5-hour window at a glance; open, a panel slides out beside
   it. Room for more sections later (.docksec). Under the menus and Find (40). */
/* ONE HEIGHT, OPEN OR SHUT (r871): the tab is the handle just pressed, so it must
   not move. The drawer is always laid out, only its WIDTH is shut to 0, and the
   tab stretches to the taller of the two: the dock is the same box either way,
   and opening slides the drawer out sideways from behind the tab. */
.sidedock{position:fixed;right:0;top:50%;transform:translateY(-50%);z-index:30;
  display:flex;flex-direction:row-reverse;align-items:stretch;pointer-events:none;
  --dockw:264px;--dockt:.3s cubic-bezier(.2,.8,.2,1)}
.sidedock > *{pointer-events:auto}
.docktab{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:4px;width:40px;
  padding:9px 0 8px;border:1px solid var(--line);border-right:0;border-radius:12px 0 0 12px;
  background:var(--panel);color:var(--ink);box-shadow:var(--shadow);cursor:pointer;
  font:inherit}
.sidedock{--dk:var(--accent)}
.sidedock.near{--dk:var(--doing)}
.sidedock.stop{--dk:var(--danger)}
.sidedock.none{--dk:var(--muted)}
.docktab:hover{border-color:var(--dk)}
.docklbl{font-size:11px;color:var(--muted);letter-spacing:.02em}
.docktab b{font-size:13px;font-variant-numeric:tabular-nums;color:var(--dk)}
.dockgauge{position:relative;width:6px;height:34px;border-radius:99px;background:var(--line);
  overflow:hidden}
.dockgauge i{position:absolute;left:0;right:0;bottom:0;border-radius:99px;background:var(--dk)}
.dockdrawer{width:0;margin-right:-1px;overflow:hidden;visibility:hidden;
  border-radius:12px 0 0 12px;box-shadow:var(--shadow)}
.dockbody{box-sizing:border-box;width:var(--dockw);min-height:100%;padding:12px 14px;
  background:var(--panel);border:1px solid var(--line);border-left:4px solid var(--dk);
  border-right:0;border-radius:12px 0 0 12px}
.sidedock.open .dockdrawer{width:var(--dockw);visibility:visible}
.sidedock.open .docktab{border-radius:0;border-left-color:transparent;box-shadow:none}
/* Shutting, the drawer stays visible until it has slid home. The first draw
   of a page is not animated (.moves lands after it): a dock kept open does not
   slide out on every screen. */
.sidedock.moves .dockdrawer{transition:width var(--dockt),visibility 0s linear .3s}
.sidedock.moves.open .dockdrawer{transition:width var(--dockt),visibility 0s}
.sidedock.moves .docktab{transition:border-radius var(--dockt),border-color var(--dockt),
  box-shadow var(--dockt)}
@media (prefers-reduced-motion:reduce){
  .sidedock.moves .dockdrawer,.sidedock.moves.open .dockdrawer,
  .sidedock.moves .docktab{transition:none}
}
.docksec + .docksec{margin-top:12px;padding-top:10px;border-top:1px solid var(--line-2)}
.dockhead{font-weight:700;font-size:14px;margin-bottom:6px}
.dockrow + .dockrow{margin-top:10px}
.dockhost{font-size:12.5px;color:var(--muted);margin-bottom:2px}
.dockline{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.dockpct{font-size:24px;line-height:1.1;font-variant-numeric:tabular-nums;color:var(--accent)}
.dockpct.near{color:var(--doing)}
.dockpct.stop{color:var(--danger)}
.dockhint{font-size:12.5px;color:var(--muted);line-height:1.35}
.dockbar{position:relative;height:8px;margin:6px 0 5px;border-radius:99px;background:var(--line)}
.dockbar i{display:block;height:100%;border-radius:99px;background:var(--accent)}
.dockbar.near i{background:var(--doing)}
.dockbar.stop i{background:var(--danger)}
.dockbar u{position:absolute;top:-3px;bottom:-3px;width:2px;background:var(--ink-2);
  opacity:.55;border-radius:2px}
@media (max-width:720px){
  .sidedock{top:auto;bottom:max(14px,env(safe-area-inset-bottom));transform:none}
  .docktab{width:36px;padding:7px 0 6px}
  .dockgauge{height:24px}
}
@media print{.sidedock{display:none}}

/* THE ASSET LIBRARY (r863, assets.html): one card per shared asset, grouped by
   kind. A kind is a colour (--k, --ks) on the card's stripe, its icon tile, its
   section head and its key in the legend; the uses are chips told apart by
   SHAPE as well: declared filled, a lease dashed. */
.t-todo{--k:var(--todo);--ks:var(--todo-soft)}
.t-doing{--k:var(--doing);--ks:var(--doing-soft)}
.t-q{--k:var(--q);--ks:var(--q-soft)}
.t-live{--k:var(--live);--ks:var(--live-soft)}
.t-note{--k:var(--note);--ks:var(--note-soft)}
.t-paused{--k:var(--paused);--ks:var(--paused-soft)}
.aslegend:empty{display:none}
.aslegin{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;margin:14px 0 4px}
.askey{display:inline-flex;align-items:center;gap:6px;padding:5px 11px 5px 9px;min-height:0;
  border-radius:99px;border:1px solid color-mix(in srgb,var(--k) 55%,transparent);
  background:var(--ks);color:var(--k);font:inherit;font-size:14px;font-weight:600;cursor:pointer}
.askey:hover{border-color:var(--k)}
.askey.on{background:var(--k);color:var(--on-st);border-color:var(--k)}
.askey.off{opacity:.5}
.ashows{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap;margin-left:auto}
.aspair{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;margin-right:8px}
.askindh{display:flex;align-items:center;gap:8px;margin:0 0 10px;font-size:16px;color:var(--k)}
.ascols{columns:300px;column-gap:14px;margin-top:14px}
.ascols > .ascard{break-inside:avoid;margin-bottom:14px}
.asgone{margin-top:14px;padding:12px 16px;border:1px dashed var(--line);border-radius:12px}
.ascard{background:var(--panel);border:1px solid var(--line);border-left:5px solid var(--k);
  border-radius:12px;padding:14px 16px;box-shadow:var(--shadow);min-width:0}
.ashead{display:flex;align-items:center;gap:11px}
.astile{flex:none;display:grid;place-items:center;width:38px;height:38px;border-radius:10px;
  background:var(--ks);color:var(--k)}
.astile .nvi{width:21px;height:21px}
.astitle{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.astitle b{font-size:16px;overflow-wrap:anywhere}
.asslug{font-size:12.5px;color:var(--muted);background:none;border:0;padding:0}
.askind{flex:none;font-size:12px;font-weight:600;letter-spacing:.03em;text-transform:uppercase;
  color:var(--k)}
.asabout{margin:10px 0 0;color:var(--ink-2);font-size:14.5px;line-height:1.5}
.asfacts{display:grid;grid-template-columns:auto 1fr;gap:5px 12px;margin-top:11px;
  padding:9px 11px;border-radius:9px;background:var(--panel-2);font-size:13.5px}
.asfact{display:contents}
.asfk{color:var(--muted);gap:6px}
.asfk .nvi{width:14px;height:14px}
.asfv{min-width:0;overflow-wrap:anywhere;color:var(--ink)}
code.asfv{font-size:13px;background:none;border:0;padding:0}
.asuses{margin-top:12px;padding-top:10px;border-top:1px solid var(--line-2)}
.ashd{font-size:12.5px;font-weight:600;letter-spacing:.03em;text-transform:uppercase;
  color:var(--muted);margin-bottom:6px}
.asuse{display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px;padding:5px 0}
.asuse + .asuse{border-top:1px dashed var(--line-2)}
.asuse.here{margin:0 -8px;padding:5px 8px;border-radius:8px;
  background:color-mix(in srgb,var(--k) 12%,transparent)}
.asboard{font-weight:600;color:var(--ink);text-decoration:none}
.asboard:hover{text-decoration:underline}
.aschips{display:inline-flex;gap:5px;flex-wrap:wrap}
.aswhen{flex-basis:100%;font-size:12.5px;color:var(--muted)}
.aslog{margin-top:10px;padding-top:10px;border-top:1px solid var(--line-2)}
.aslogrow{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px;padding:3px 0;font-size:13px}
.aslogat{color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}
.aslogboard{font-weight:600;color:var(--ink)}
.aslogwhat{min-width:0;overflow-wrap:anywhere}
.aschip{display:inline-flex;align-items:center;gap:4px;padding:1px 8px 1px 6px;border-radius:99px;
  font-size:12.5px;font-weight:600;border:1.5px solid var(--accent);white-space:nowrap}
.aschip .nvi{width:12px;height:12px}
.aschip.as-declared{background:var(--accent);color:var(--on-st)}
.aschip.as-lease{border-style:dashed;border-color:var(--live);color:var(--live);background:var(--live-soft)}
.aschip.idle{opacity:.6;background:transparent}
.asempty{padding:22px;border:1px dashed var(--line);border-radius:12px;margin-top:16px}
@media (max-width:720px){
  .ascols{columns:1}
  .ashows{margin-left:0}
  .ascard{padding:12px 13px}
}

/* MARKED FOR REVIEW in Notif (r880, markCard in board.html): a mark to judge,
   in the violet judging wears (the scores, Score one at a time). Its picture on
   the left when the ticket has one, what it says on the right, the Commissar's
   verdict, then yours. On a phone the picture goes on top. */
.markcard{display:grid;grid-template-columns:220px 1fr;gap:14px;margin:0 0 12px;padding:12px;
  background:var(--panel);border:1px solid var(--line);border-left:4px solid var(--q);
  border-radius:12px;box-shadow:var(--shadow)}
.markcard.nopic{grid-template-columns:1fr}
.markpic{aspect-ratio:16/10;border-radius:8px;overflow:hidden;background:#0b0c12;cursor:zoom-in}
.markpic img{display:block;width:100%;height:100%;object-fit:cover;object-position:top center}
.markbody{display:flex;flex-direction:column;gap:8px;min-width:0}
.marktop{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.markkind{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--q)}
.markitem{font-size:13px}
.marktitle{font-size:15px;line-height:1.35}
.marknote{font-size:14px;color:var(--ink-2);max-height:7.5em;overflow:hidden;
  -webkit-mask-image:linear-gradient(#000 70%,transparent)}
.marknote > :first-child{margin-top:0}
.marknote.full{max-height:none;-webkit-mask-image:none}
.markmore{align-self:flex-start;margin-top:-2px;font-size:13px;padding:2px 10px}
.markmore[hidden]{display:none}
.markwho{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;font-size:13.5px}
.markname{color:var(--muted);font-weight:600}
.markv{font-size:12px;padding:1px 8px;border-radius:999px}
.markv.upheld{background:var(--accent-soft);color:var(--accent)}
.markv.struck{background:color-mix(in srgb,var(--danger) 18%,transparent);color:var(--danger)}
.markagainst{color:var(--muted)}
.markwhy{flex-basis:100%;color:var(--ink-2);cursor:pointer;display:-webkit-box;
  -webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.markwhy.full{display:block;cursor:auto}
.markwait{color:var(--muted)}
.markjudge{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.markjudge .markbtn{min-height:36px;padding:6px 18px;font-weight:650}
.markjudge .markbtn.upheld{border-color:var(--accent);color:var(--accent)}
.markjudge .markbtn.struck{border-color:var(--danger);color:var(--danger)}
.markjudge .markwhyin{flex:1;min-width:160px}
@media (max-width:720px){
  .markcard{grid-template-columns:1fr}
  .markjudge .markbtn{flex:1}
  .markjudge .markwhyin{flex-basis:100%}
}

/* LIVRABLES (r857, livTile in board.html): finished work to look at, drawn
   apart from notices (pink, prose) and On Hold (purple, questions) by SHAPE and
   COLOUR: picture-first tiles, cyan. A MOSAIC OF CELLS (r978): the columns
   follow the screen (160px at least: six on a desktop, the page stops at 1200,
   two on a phone), every row is --livrow tall, and a tile spans the cells
   livSpan gave it (data-w, data-h, 3x3 at most), dense so small ones fill the
   holes. contain:size keeps a tile's words from stretching its row; they
   scroll inside it. The pictures fill what the words leave, from their top. */
.livgrid{--livrow:320px;display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));
  grid-auto-rows:minmax(var(--livrow),auto);grid-auto-flow:row dense;gap:12px;margin:0 0 18px}
.livtile{display:flex;flex-direction:column;background:var(--panel);border:1px solid var(--line);
  border-top:3px solid var(--live);border-radius:12px;overflow:hidden;box-shadow:var(--shadow);
  min-width:0}
.livtile:not(.open){contain:size}
.livtile[data-w="2"]{grid-column:span 2}
.livtile[data-w="3"]{grid-column:span 3}
.livtile[data-h="2"]{grid-row:span 2}
.livtile[data-h="3"]{grid-row:span 3}
.livpic{position:relative;flex:1 1 0;min-height:96px;background:#0b0c12;overflow:hidden;
  display:grid;gap:2px;grid-template-columns:1fr;grid-auto-rows:1fr}
.livpic[data-n="2"]{grid-template-columns:1fr 1fr}
.livpic[data-n="3"],.livpic[data-n="4"]{grid-template-columns:1fr 1fr}
.livpic[data-n="3"] > .livshot:first-child{grid-row:span 2}
.livpic[data-n="5"],.livpic[data-n="6"]{grid-template-columns:repeat(3,1fr)}
.livpic[data-n="5"] > .livshot:first-child{grid-row:span 2}
.livshot{position:relative;min-height:0;overflow:hidden;cursor:zoom-in}
.livshot img{display:block;width:100%;height:100%;object-fit:cover;object-position:top center}
.livpic.fig{cursor:default;display:flex;align-items:center;justify-content:center;
  padding:14px;background:linear-gradient(160deg,var(--live-soft),var(--panel-2))}
/* with words to read, a figure fills what they leave, 110px at least;
   pictures give the words up to half the tile */
.livtile:has(.livanswers) > .livpic.fig{min-height:110px}
.livtile:not(.side):has(.livanswers) > .livpic:not(.fig) + .livbody{max-height:55%}
.livtile.side{flex-direction:row}
.livtile.side > .livpic{flex:1 1 0;min-height:0}
.livtile.side > .livbody{flex:1 1 0;min-width:0}
.livfig{font-size:28px;font-weight:750;line-height:1.15;color:var(--live);text-align:center;
  text-wrap:balance;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.livkind,.livmore{position:absolute;top:8px;padding:2px 8px;border-radius:999px;
  font-size:12px;font-weight:700;background:rgba(10,11,16,.78);color:#fcfcff}
.livkind{left:8px}
.livmore{right:8px}
.livcap{position:absolute;left:0;right:0;bottom:0;padding:18px 12px 8px;font-size:18px;
  font-weight:750;color:#fcfcff;background:linear-gradient(transparent,rgba(10,11,16,.85))}
.livbody{display:flex;flex-direction:column;gap:8px;padding:10px 12px 12px;flex:0 1 auto;
  min-height:0;overflow:hidden}
/* only the answer gives way when a tile is short of room: it scrolls */
.livbody > :not(.livanswers){flex-shrink:0}
.livtitle{color:var(--ink);text-decoration:none;font-weight:650;font-size:14.5px;line-height:1.35;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.livtitle:hover{color:var(--live)}
/* the notice answering it, read here (r968); it scrolls in its tile (r978) */
.livanswers{flex:0 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:8px}
.livans{margin:0;font-size:13.5px;line-height:1.45;color:var(--ink);white-space:pre-line}
.livmeta{display:flex;align-items:center;gap:10px;font-size:13px;color:var(--muted);flex-wrap:wrap}
.livref{font-weight:700;color:var(--live)}
.livby{display:inline-flex;align-items:center;gap:5px}
.livacts{display:flex;flex-wrap:wrap;gap:8px;margin-top:auto}
.livacts > button{flex:1 1 auto;min-height:36px;white-space:nowrap}
button.primary.livseen{background:var(--live);border-color:var(--live);color:var(--on-st)}
.notebox.livask{display:flex;flex-direction:column;align-items:stretch;gap:6px;margin:0}
.notebox.livask > button{align-self:flex-end}
.livask[hidden]{display:none}
.livask textarea{width:100%;box-sizing:border-box;min-height:64px}
/* a column: the note box's own flex (a row's, 100% basis on a phone) would stand it
   full height and push Send out of the tile */
.notebox.livask > *{flex:0 0 auto}
/* The ticket opened in the tile (r934, livOpen): the tile takes the whole row,
   its picture and actions a column on the left, the ticket's card beside them. */
.livmeta .livopen{margin-left:auto;color:var(--live);font-weight:650}
.livtile.open{grid-column:1/-1;grid-row:auto;display:grid;grid-template-columns:minmax(260px,340px) 1fr;
  grid-template-rows:auto 1fr}
.livtile.open > .livpic{grid-column:1;grid-row:1;align-self:start;flex:none;aspect-ratio:16/10}
/* the change field open: the tile's row grows to hold it rather than cut it */
.livtile:has(> .livbody > .livask:not([hidden])){contain:none}
.livtile.open > .livbody{grid-column:1;grid-row:2;align-self:start}
.livtile.open > .livcard{grid-column:2;grid-row:1/span 2;padding:10px 12px 12px 0;min-width:0}
.livcard > .card{margin:0}
@media (max-width:720px){
  .livgrid{--livrow:350px;grid-template-columns:1fr 1fr;gap:10px}
  .livtile[data-w="3"]{grid-column:span 2}
  .livtile.open{display:flex;flex-direction:column}
  .livtile.open > .livcard{padding:0 8px 8px}
  .livmeta .livopen{min-height:36px}
  .livacts > button{min-height:44px}
  .notebox.livask > button{align-self:stretch;min-height:44px}
  .livask textarea{font-size:16px}
}
/* Home's foot: Shut down Atelier (r928), the reverse of the desktop icon. Apart
   from the boards, with the danger colour on its edge: it stops all of them. */
.offband{display:flex;align-items:center;gap:12px;margin:22px 0 8px;padding:10px 12px;
  border:1px solid var(--line);border-left:3px solid var(--danger);border-radius:8px;
  background:var(--panel)}
.offband > button{flex:none;white-space:nowrap}
.offband > .hint{min-width:0}
@media (max-width:720px){
  .offband{flex-direction:column;align-items:stretch}
  .offband > button{min-height:44px}
}
/* A board's website (r970): its Stop ends a server, so it reads as one. */
.playsplit > .sitestop{color:var(--danger)}
