
/* The second voice: IBM Plex Mono (Ian chose it 2026-08-05 for being calmer than
   JetBrains Mono). Humanist rather than coder-forward, and its x-height is 0.516em
   against JetBrains' 0.550em, which is most of why the stamped uppercase labels stop
   shouting. Self-hosted, immutable, kit-independent (see the /font/ route: /brand/
   resolves through brand/<kit>/, so a font parked there would silently fall back to
   SF Mono on a kit switch). Two real static weights, 18KB total, subset to the Latin
   plus punctuation, arrows and symbols this UI prints.
   No size-adjust: the advance is 0.600em, identical to the ui-monospace fallback, so
   the swap cannot reflow a table - and Plex's x-height is already at or below the
   fallback's, so scaling it down would only make the 10.5px labels harder to read.
   The SemiBold face is declared 600 700 deliberately: --w-bold is 700, and without
   that range a 700 request would be SYNTHESISED from Regular - the exact faux-bold
   bug found on the video title cards. */
@font-face{
font-family:"IBM Plex Mono";
src:url("/font/plexmono-400.woff2") format("woff2");
font-weight:400 500;font-style:normal;font-display:swap;
}
@font-face{
font-family:"IBM Plex Mono";
src:url("/font/plexmono-600.woff2") format("woff2");
font-weight:600 700;font-style:normal;font-display:swap;
}

/* Quiet Instrument. Twelve neutral steps with fixed jobs, one accent, four status
   hues, and colour used for nothing except state. Step jobs follow Radix's contract:
   1-2 page, 3 component, 4 hover, 5 selected, 6 border, 7 interactive border, 8 ring,
   9 solid, 10 solid hover, 11 secondary text, 12 primary text.
   The hex block is the fallback and is what a browser without light-dark() renders. */
:root{
--n1:#fcfcfd;--n2:#f8f9fa;--n3:#f1f3f5;--n4:#eceef0;--n5:#e6e8eb;--n6:#dfe3e6;
--n7:#d7dbdf;--n8:#c1c8cd;--n9:#8b949e;--n10:#7e868c;--n11:#687076;--n12:#11181c;
/* One accent hue. --a-solid is for FILLS, --a11 for INK: keeping them apart is what
   fixes white-on-pale-blue buttons in dark mode (measured at 2.15:1 before). */
--a2:#f5f8ff;--a3:#edf2fe;--a6:#bcd3ff;--a8:#7aa6ff;--a9:#1a6aff;--a10:#1558d6;--a11:#0f45ad;
--a-solid:#1a6aff;--on-accent:#ffffff;--a-lead:#7aa6ff;
/* Four status hues, four steps each: 2 wash, 3 chip, 9 signal, 11 ink. */
--ok2:#f3faf5;--ok3:#e4f6e9;--ok9:#2f9e44;--ok11:#1e6f30;
--wait2:#fdfaf0;--wait3:#fdf3d9;--wait9:#a37700;--wait11:#7d5b00;
--risk2:#fdf7f2;--risk3:#fdf0e7;--risk9:#b5480d;--risk11:#963c0a;
--stop2:#fdf6f5;--stop3:#fdeceb;--stop9:#d93025;--stop11:#a51d15;
/* The signal bus: one class on a row drives its gutter, wash and ink. The default is
   a neutral gutter, so the channel is always engraved and only lights up when there
   is something to say. */
--sig:var(--n5);--sig-bg:transparent;--sig-fg:var(--n11);
--gutter:2px;--gutter-strong:3px;
/* Five surfaces, not one. */
--s-well:#e9ebef;--s-page:#f3f5f7;--s-card:#ffffff;--s-raise:#ffffff;--s-chrome:#00008b;
--edge-top:rgb(255 255 255 / 0);
--chrome-fg:rgb(255 255 255 / .68);--chrome-fg-strong:#ffffff;--hair-chrome:rgb(255 255 255 / .12);
--chrome-grad:linear-gradient(135deg,#00008b 0%,#1a6aff 100%);
/* Two voices. The mono is self-hosted and immutable; see the @font-face below. */
--font:"Inter",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
--mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
--num:tabular-nums slashed-zero;
/* Nine steps with three decisive gaps: 15>18, 18>30, 30>34. The old scale had
   eleven sizes inside a 5px band, which is most of why this read as flat. */
--fs-0:.65625rem;--fs-1:.6875rem;--fs-2:.75rem;--fs-3:.8125rem;--fs-4:.875rem;
--fs-5:.9375rem;--fs-6:1.125rem;--fs-7:1.875rem;--fs-8:2.125rem;
--lh-0:1.05;--lh-1:1.18;--lh-2:1.32;--lh-3:1.5;--lh-4:1.6;
--tr-readout:-.03em;--tr-title:-.019em;--tr-body:0;--tr-mono:-.008em;--tr-label:.085em;--tr-micro:.11em;
--w-body:400;--w-data:500;--w-mid:600;--w-bold:700;
--hairline:var(--n6);--hair:var(--n6);--hair-quiet:var(--n5);--hair-strong:var(--n8);--hairline-strong:var(--n8);
--shadow-sm:0 1px 2px rgb(15 23 42 / .06);--shadow-md:0 2px 8px rgb(15 23 42 / .08);
--shadow-lg:0 12px 32px rgb(15 23 42 / .18);--ring:0 0 0 3px rgb(26 106 255 / .32);
--shadow-overlay:0 0 0 1px var(--hairline),var(--shadow-lg);
/* Shape is a RULE, not a habit: 0 data, 4 control, 10 panel, 999 state. */
--r-flat:0;--r-tick:1px;--r-ctl:8px;--r-panel:12px;--r-state:9999px;--r-overlay:12px;
--r1:var(--r-tick);--r2:var(--r-ctl);--r3:var(--r-panel);
--dur0:70ms;--dur1:110ms;--dur2:160ms;--dur3:240ms;
--ease:cubic-bezier(.2,0,0,1);--ease-in:cubic-bezier(.05,.7,.1,1);--ease-panel:cubic-bezier(.32,.72,0,1);
--cell:6px 12px;--cell-data:5px 10px;--cell-comfy:10px 14px;
--tap-min:30px;--tap:44px;
/* legacy aliases, so every existing rule picks up the new ramp unchanged. The last
   three were referenced in this stylesheet and never declared. */
--fg:var(--n12);--muted:var(--n11);--line:var(--hairline);--bg:var(--s-page);
--card:var(--s-card);--surface:var(--s-card);--chrome:var(--s-chrome);
--accent:var(--a11);--accent-strong:var(--a11);--warn:var(--wait11);--warnbg:var(--wait3);--ok:var(--ok9);
--ok-soft:var(--ok2);--risk1:var(--risk2);
}
/* The brand gradient is an IMAGE, so it cannot ride light-dark() the way every colour
   here does - that silently invalidates the declaration. It is switched by the same two
   signals the theme toggle uses instead: the OS preference, and the data-theme the
   toggle stamps on the root, which has to win in both directions. */
@media (prefers-color-scheme: dark){:root{--chrome-grad:none}}
:root[data-theme="dark"]{--chrome-grad:none}
:root[data-theme="light"]{--chrome-grad:linear-gradient(135deg,#00008b 0%,#1a6aff 100%)}
/* Dark mode is the same stylesheet: one function per colour, one attribute to flip. */
@supports (color: light-dark(#000, #fff)){
:root{
color-scheme:light dark;
--n1:light-dark(oklch(.994 .002 250),oklch(.178 .006 250));
--n2:light-dark(oklch(.982 .003 250),oklch(.205 .006 250));
--n3:light-dark(oklch(.962 .004 250),oklch(.245 .007 250));
--n4:light-dark(oklch(.945 .005 250),oklch(.275 .008 250));
--n5:light-dark(oklch(.925 .006 250),oklch(.305 .009 250));
--n6:light-dark(oklch(.900 .007 250),oklch(.345 .010 250));
--n7:light-dark(oklch(.865 .008 250),oklch(.400 .011 250));
--n8:light-dark(oklch(.805 .010 250),oklch(.490 .012 250));
--n9:light-dark(oklch(.640 .014 250),oklch(.560 .013 250));
--n10:light-dark(oklch(.595 .014 250),oklch(.610 .013 250));
--n11:light-dark(oklch(.510 .014 250),oklch(.730 .011 250));
--n12:light-dark(oklch(.240 .012 250),oklch(.955 .004 250));
--a3:light-dark(oklch(.960 .020 262),oklch(.268 .045 262));
--a6:light-dark(oklch(.870 .062 262),oklch(.375 .078 262));
--a8:light-dark(oklch(.735 .120 262),oklch(.500 .120 262));
--a9:light-dark(#1a6aff,oklch(.640 .165 262));
--a10:light-dark(#1558d6,oklch(.690 .150 262));
--a11:light-dark(#0f45ad,oklch(.790 .100 262));
--ok9:light-dark(oklch(.520 .110 155),oklch(.700 .105 155));
--ok3:light-dark(oklch(.960 .022 155),oklch(.270 .045 155));
--wait9:light-dark(oklch(.545 .105 78),oklch(.760 .105 78));
--wait3:light-dark(oklch(.965 .030 78),oklch(.275 .045 78));
--risk9:light-dark(oklch(.545 .130 48),oklch(.740 .120 48));
--risk3:light-dark(oklch(.960 .030 48),oklch(.278 .050 48));
--stop9:light-dark(oklch(.535 .175 25),oklch(.700 .150 25));
--stop3:light-dark(oklch(.958 .022 25),oklch(.280 .055 25));
--a2:light-dark(oklch(.980 .010 262),oklch(.232 .030 262));
/* Fills only. White on --a-solid passes 4.5:1 in BOTH modes; white on --a11 in dark
   is 2.15:1, which is the bug button.primary shipped with. */
--a-solid:light-dark(#1a6aff,oklch(.560 .170 262));
--a-lead:light-dark(oklch(.735 .120 262),oklch(.700 .120 262));
--ok2:light-dark(oklch(.978 .012 155),oklch(.226 .030 155));
--ok11:light-dark(oklch(.430 .095 155),oklch(.820 .090 155));
--wait2:light-dark(oklch(.980 .016 78),oklch(.232 .030 78));
--wait11:light-dark(oklch(.455 .092 78),oklch(.845 .085 78));
--risk2:light-dark(oklch(.978 .016 48),oklch(.234 .034 48));
--risk11:light-dark(oklch(.462 .120 48),oklch(.830 .095 48));
--stop2:light-dark(oklch(.976 .014 25),oklch(.236 .036 25));
--stop11:light-dark(oklch(.470 .165 25),oklch(.820 .110 25));
/* The dark ladder is monotonic and visible: well .172 < page .205 < card .243 <
   raise .272, chrome darkest at .148. The old card/page delta was .017, below the
   threshold you can see, which is why every panel read as the same flat rectangle. */
--s-well:light-dark(#e9ebef,oklch(.172 .006 250));
--s-page:light-dark(#f3f5f7,oklch(.205 .006 250));
--s-card:light-dark(oklch(1 0 0),oklch(.243 .007 250));
--s-raise:light-dark(oklch(1 0 0),oklch(.272 .008 250));
--s-chrome:light-dark(oklch(.225 .016 258),oklch(.148 .008 250));
/* The depth trick: in light a white card on grey needs nothing; in dark a 4.5% white
   top line is what lifts a panel, with no blur anywhere. */
--edge-top:light-dark(rgb(255 255 255 / 0),rgb(255 255 255 / .045));
--card:var(--s-card);
--surface:var(--s-raise);
--chrome:var(--s-chrome);
--shadow-overlay:0 0 0 1px var(--hairline),0 6px 12px -3px rgb(0 0 0 / .10),0 18px 44px rgb(0 0 0 / .30);
}
:root[data-theme="dark"]{color-scheme:dark}
:root[data-theme="light"]{color-scheme:light}
}
/* The brand art and the screenshots are fixed assets; no auto-darkening. */
.thumbs,.brandart{color-scheme:only light}
*{box-sizing:border-box}
body{margin:0;font-family:var(--font);background:var(--bg);color:var(--fg);font-size:14px;line-height:1.5}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline}
header{background:var(--chrome);color:#fff;padding:12px 20px;display:flex;align-items:center;gap:18px}
header .brand{font-weight:700;font-size:15px}
header nav a{color:#cbd5e1;font-weight:600;font-size:13px}
header nav a:hover{color:#fff}
header .who{margin-left:auto;font-size:12px;color:#94a3b8;display:flex;align-items:center;gap:10px}
main{max-width:1040px;margin:0 auto;padding:22px 20px 60px}
h1{font-size:20px;margin:0 0 4px}
h2{font-size:15px;margin:26px 0 8px;padding-bottom:5px;border-bottom:1px solid var(--line)}
p.sub{color:var(--muted);margin:0 0 16px}
table{width:100%;border-collapse:collapse;background:var(--card);border:1px solid var(--line);border-radius:8px;overflow:hidden}
th,td{text-align:left;padding:8px 11px;border-bottom:1px solid var(--line);vertical-align:top}
th{background:#f3f4f6;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
tr:last-child td{border-bottom:none}
.pill{display:inline-block;padding:1px 8px;border-radius:999px;font-size:11px;font-weight:600;border:1px solid var(--line);background:#f3f4f6;color:#374151}
.pill.est{background:#fef3c7;border-color:#fde68a;color:#92400e}
.pill.ok{background:#d1fae5;border-color:#a7f3d0;color:#065f46}
.pill.pub{background:#dbeafe;border-color:#bfdbfe;color:#1e40af}
.pill.bad{background:#fee2e2;border-color:#fecaca;color:#991b1b}
.filters{margin:0 0 14px;display:flex;gap:8px;flex-wrap:wrap}
.filters a{padding:4px 11px;border:1px solid var(--line);border-radius:999px;background:var(--surface);font-weight:600;font-size:12px}
.filters a.on{background:var(--accent);color:#fff;border-color:var(--accent)}
.muted{color:var(--muted)}
.val{white-space:pre-wrap;word-break:break-word;max-width:420px}
form.inline{display:flex;gap:6px;align-items:center;margin:0}
input[type=text],select,textarea{font-family:inherit;font-size:13px;padding:5px 8px;border:1px solid var(--line);border-radius:6px;background:var(--surface);color:var(--fg);min-width:180px}
button{font-family:inherit;font-size:13px;font-weight:600;padding:5px 11px;border:1px solid var(--line);border-radius:6px;background:var(--surface);color:var(--fg);cursor:pointer}
button.primary{background:var(--accent);border-color:var(--accent);color:#fff}
button.small{padding:3px 8px;font-size:12px}
.warn{background:var(--warnbg);border:1px solid #fde68a;color:var(--warn);border-radius:8px;padding:12px 14px;margin:0 0 18px}
.warn strong{color:#92400e}
.warn .vals{margin-top:8px;font-size:13px}
.warn .vals code{background:var(--surface);border:1px solid var(--wait3);border-radius:4px;padding:1px 6px}
.card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:14px 16px;margin:0 0 16px}
.actrow{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.gate{max-width:380px;margin:80px auto;background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:26px}
.gate h1{margin-bottom:14px}
.gate input{width:100%;min-width:0;margin:0 0 12px;padding:10px;font-size:15px}
.gate button{width:100%;padding:10px}
.err{color:#b91c1c;font-size:13px;min-height:18px;margin-top:8px}
.chain{list-style:none;margin:0;padding:0}
.chain li{padding:4px 0;border-bottom:1px dashed var(--line)}
.chain li:last-child{border-bottom:none}
code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(178px,1fr));gap:12px;margin:0 0 18px}
.stat{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:13px 16px;position:relative;overflow:hidden}
.stat:before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--line)}
.stat.good:before{background:#10b981}
.stat.hot:before{background:#f59e0b}
.stat b{display:block;font-size:25px;line-height:1.15;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.stat b a{color:inherit}
.stat em{display:block;font-size:11.5px;color:var(--muted);font-style:normal;margin-top:3px}
.stat span{display:block;font-size:12.5px;color:var(--fg);font-weight:600;margin-top:2px}
.stat.hot b{color:#92400e}
.search{width:100%;margin:0 0 18px;padding:9px 12px;font-size:14px;border:1px solid var(--line);border-radius:8px;background:var(--surface);box-sizing:border-box}
section h2 .count{font-weight:400;color:var(--muted);font-size:13px}
details.fam{margin:22px 0 0}
details.fam>summary{cursor:pointer;list-style:none;display:flex;align-items:baseline;gap:8px;font-size:15px;font-weight:600;padding-bottom:5px;border-bottom:1px solid var(--line);margin-bottom:8px}
details.fam>summary::-webkit-details-marker{display:none}
details.fam>summary:before{content:"▸";color:var(--muted);font-size:11px;transition:transform .12s;display:inline-block}
details.fam[open]>summary:before{transform:rotate(90deg)}
details.fam>summary .count{font-weight:400;color:var(--muted);font-size:13px}
details.fam>summary:hover{color:var(--accent)}
.namecell a{font-weight:600;font-size:14px}
.namecell .meta{display:block;font-size:11.5px;color:var(--muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;margin-top:2px}
.prog{display:inline-flex;gap:2px;vertical-align:middle}
.prog i{display:inline-block;width:11px;height:11px;border-radius:2px;background:#e5e7eb}
.prog i.on{background:#10b981}
.progn{font-size:12px;color:var(--muted);margin-left:8px;font-variant-numeric:tabular-nums}
.attn .pill{margin-right:4px}
a.pill{cursor:pointer}
.crumb{font-size:12px;color:var(--muted);margin:0 0 2px}
.links{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 18px}
.lnk{padding:5px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);font-size:13px;font-weight:600}
.lnk:hover{border-color:var(--accent);text-decoration:none}
.story{padding:14px 16px}
.story .desc{margin:0;font-size:14.5px;line-height:1.55}
.story .meta{margin:8px 0 0;font-size:12.5px;color:var(--muted)}
ol.stages{list-style:none;display:flex;flex-wrap:wrap;gap:6px;margin:0 0 18px;padding:0}
ol.stages li{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--muted);background:var(--card);border:1px solid var(--line);border-radius:999px;padding:4px 11px}
ol.stages li b{width:8px;height:8px;border-radius:50%;background:#d1d5db;display:inline-block}
ol.stages li.done{color:#065f46;background:#ecfdf5;border-color:#a7f3d0}
ol.stages li.done b{background:#10b981}
ol.stages li.wip{color:var(--wait9);background:var(--wait3);border-color:var(--wait9)}
ol.stages li.wip b{background:#f59e0b}
h2 .count{font-weight:400;color:var(--muted);font-size:12.5px}
td.num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
td .meta{display:block;font-size:11.5px;color:var(--muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;margin-top:2px}
details.grp{background:var(--card);border:1px solid var(--line);border-radius:8px;margin:0 0 8px}
details.grp summary{cursor:pointer;padding:10px 14px;font-weight:600;font-size:13.5px;list-style:none}
details.grp summary::-webkit-details-marker{display:none}
details.grp summary:before{content:"+ ";color:var(--muted)}
details.grp[open] summary:before{content:"- "}
details.grp table{border:none;border-radius:0;border-top:1px solid var(--line)}
details.grp .grpbody{padding:0 14px 12px}
details.grp .grpbody .card{margin:10px 0 0}
.progline{display:flex;align-items:center;gap:10px;flex-wrap:wrap;background:var(--card);border:1px solid var(--line);border-radius:8px;padding:10px 14px;margin:0 0 16px}
.progline .prog i.wip{background:#f59e0b}
.progline .progn{margin-left:0;font-weight:600;color:var(--fg)}
.progline .left{font-size:12.5px;color:var(--muted)}
.progline .left.ok{color:#065f46}
table.assets td{vertical-align:middle}
.acell b{font-size:13.5px}
.acell .vtitle{font-size:12.5px;color:var(--muted)}
.acell .vdesc{margin:5px 0 0;font-size:13px;line-height:1.5;max-width:62ch}
.acell .vdesc.none{color:var(--muted);font-style:italic}
.fname{font-weight:600;font-size:13px;white-space:nowrap}
.fname .meta{display:block;font-weight:400}
.ccell{white-space:nowrap}
.dcell{text-align:right;white-space:nowrap}
.btn.small{padding:3px 9px;font-size:11.5px;margin-left:4px}
.dlg{border:none;border-radius:14px;padding:0;max-width:560px;width:calc(100% - 32px);box-shadow:0 24px 60px rgba(15,23,42,.28)}
.dlg::backdrop{background:rgba(15,23,42,.45)}
.dlg-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-bottom:1px solid var(--line)}
.dlg-head b{font-size:14.5px}
.dlg-preview{background:#0f172a;display:flex;align-items:center;justify-content:center;min-height:150px}
.dlg-preview video{width:100%;max-height:290px;display:block}
.dlg-preview p{margin:0;padding:28px;color:#94a3b8;font-size:13px}
.dlg-note{margin:0;padding:12px 18px 0;font-size:12px;color:var(--muted)}
.dlg-opts{display:flex;flex-direction:column;gap:8px;padding:12px 18px 18px}
.dlg-opt{display:flex;flex-direction:column;gap:1px;padding:10px 14px;border:1px solid var(--line);border-radius:9px;background:var(--surface)}
.dlg-opt:hover{border-color:var(--accent);background:#f8faff;text-decoration:none}
.dlg-opt b{font-size:13.5px}
.dlg-opt span{font-size:11.5px;color:var(--muted)}
.daymark{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin:18px 0 6px;font-weight:600}
.events{margin-top:4px}
.ev{display:flex;gap:12px;align-items:baseline;padding:7px 12px;background:var(--card);border:1px solid var(--line);border-radius:7px;margin-bottom:5px;font-size:13.5px}
.evtime{font-family:ui-monospace,monospace;font-size:11.5px;color:var(--muted);min-width:38px}
.evwho{font-weight:600;min-width:96px}
.evwhat{flex:1}
.evdetail{display:block;font-size:12px;color:var(--muted);margin-top:2px;word-break:break-word}
.evdetail s{opacity:.6}
.filters .count{color:var(--muted);font-weight:400}
/* ---- adopted from demo-match ------------------------------------------------
   Four primitives its stylesheet has and this one did not, mapped onto the Hub's own
   tokens rather than copied with demo-match's variable names. Values are its real
   shipped ones; the names are ours, so dark mode keeps working (demo-match has none). */

/* An empty list should say so. A table that renders zero rows and no message reads as
   a bug even when it is the correct answer. */
.empty{text-align:center;color:var(--n11);padding:36px 16px;background:var(--s-card);
border:1px dashed var(--hairline);border-radius:var(--r-panel);font-size:var(--fs-3)}
.empty b{display:block;color:var(--n12);font-size:var(--fs-5);margin-bottom:4px}

/* The selection bar. On a forty-row table the action belongs with the selection, not
   a screen below it, so it sticks to the bottom while you scroll. Inverted against the
   page in both themes, which is what makes it read as a layer rather than a row. */
.bulk{position:sticky;bottom:16px;margin-top:14px;display:flex;align-items:center;gap:10px;
background:var(--n12);color:var(--s-card);padding:11px 14px;border-radius:var(--r-panel);
box-shadow:var(--shadow-lg);flex-wrap:wrap;z-index:15}
.bulk .n{font-weight:var(--w-bold);font-variant-numeric:var(--num)}
.bulk .bb{min-height:32px;padding:6px 12px;border-radius:var(--r-ctl);
border:1px solid rgb(255 255 255/.24);background:rgb(255 255 255/.12);color:inherit;
font:var(--w-mid) var(--fs-3)/1 var(--font);cursor:pointer}
.bulk .bb:hover{background:rgb(255 255 255/.22)}
.bulk .bb.go{background:var(--a-solid);border-color:var(--a-solid);color:var(--on-accent)}
.bulk .sp{margin-left:auto}

/* Confirmation after the fact. Every mutating action here is a form post that reloads
   the page, so "did that work?" was answered by reading the table again. The toast is
   restored from a one-shot query parameter on the redirect target. */
.toast{position:fixed;left:50%;bottom:26px;transform:translate(-50%,14px);
background:var(--n12);color:var(--s-card);padding:10px 16px;border-radius:var(--r-state);
font-size:var(--fs-3);box-shadow:var(--shadow-lg);opacity:0;pointer-events:none;
transition:opacity var(--dur2) var(--ease),transform var(--dur2) var(--ease);z-index:70;
display:flex;align-items:center;gap:9px;max-width:min(92vw,520px)}
.toast.on{opacity:1;transform:translate(-50%,0);pointer-events:auto}
.toast.err{background:var(--stop9);color:#fff}

/* An inline banner for state that belongs to the page rather than to a moment. */
.banner{display:flex;align-items:center;gap:12px;padding:10px 13px;border-radius:var(--r-panel);
margin-bottom:14px;font-size:var(--fs-3);flex-wrap:wrap;border:1px solid var(--hairline);
background:var(--s-card)}
.banner.warn{background:var(--wait2);border-color:var(--wait9);color:var(--wait11)}
.banner.ok{background:var(--ok2);border-color:var(--ok9);color:var(--ok11)}

/* ---- sortable headers, confirm dialog, nav badge ----------------------------- */

/* The arrow is drawn from borders rather than set as a glyph, so it never depends on a
   font and never shifts the header's height. It is visible AT REST on purpose: a
   sortable column that only shows its arrow once sorted is indistinguishable from a
   fixed one, so nobody discovers they can sort. */
th.sortable{cursor:pointer;user-select:none;white-space:nowrap}
th.sortable:hover{color:var(--n12)}
th.sortable .sarr{display:inline-block;position:relative;width:7px;height:11px;margin-left:6px;
vertical-align:middle;opacity:.42}
th.sortable:hover .sarr,th.sortable:focus-visible .sarr{opacity:.78}
th.sortable .sarr::before,th.sortable .sarr::after{content:"";position:absolute;left:0;
border-left:3.5px solid transparent;border-right:3.5px solid transparent}
th.sortable .sarr::before{top:0;border-bottom:4px solid currentColor}
th.sortable .sarr::after{bottom:0;border-top:4px solid currentColor}
th.sortable[aria-sort]{color:var(--a11)}
th.sortable[aria-sort] .sarr{opacity:1;color:var(--a11)}
th.sortable[aria-sort="ascending"] .sarr::after{opacity:0}
th.sortable[aria-sort="descending"] .sarr::before{opacity:0}

/* The confirm dialog reuses the Hub's own <dialog> shell rather than demo-match's
   fixed-position overlay, so it inherits the backdrop, the escape key and the focus
   trap the platform already gives us. */
.cfm{max-width:440px;padding:20px}
.cfm h2{display:block;margin:0 0 8px;padding:0;border:0;text-transform:none;
font:var(--w-mid) var(--fs-6)/1.25 var(--font);letter-spacing:var(--tr-title);color:var(--n12)}
/* The section marker and its uppercase belong to page headings, not to a dialog asking
   a question - a modal title reading like a table of contents entry reads as a bug. */
.cfm h2::before{display:none}
.cfm p{margin:0 0 16px;font-size:var(--fs-3);color:var(--n11);line-height:var(--lh-3)}
.cfmacts{display:flex;gap:8px;justify-content:flex-end;flex-wrap:wrap}
.cfmacts .btn.danger{background:var(--stop9);border-color:var(--stop9);color:#fff}
.cfmacts .btn.danger:hover{background:var(--stop11);border-color:var(--stop11)}

/* Rendered only when the count is above zero, so an empty queue does not leave a dot
   sitting in the navigation implying work that is not there. */
.navbadge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;
padding:0 5px;margin-left:6px;border-radius:var(--r-state);background:var(--stop9);color:#fff;
font:var(--w-bold) var(--fs-0)/1 var(--font);font-variant-numeric:var(--num)}

.copyblock{background:var(--s-well);border:1px solid var(--hairline);border-radius:var(--r-ctl);
padding:12px 14px;font:var(--w-body) var(--fs-2)/1.55 var(--mono);white-space:pre-wrap;overflow-x:auto;
max-height:340px;overflow-y:auto;margin:0 0 10px}
.btn{display:inline-block;padding:6px 14px;border:1px solid var(--line);border-radius:var(--r-state);background:var(--surface);font-size:12.5px;font-weight:600}
.btn:hover{border-color:var(--accent);text-decoration:none}
a.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}
.mkt{padding:4px 16px 14px}
.mktrow{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:11px 0;border-bottom:1px solid var(--line)}
.mktrow:last-of-type{border-bottom:none}
.mktrow b{font-size:13.5px}
.mktrow .meta{display:block;font-size:11.5px;color:var(--muted);margin-top:2px}
.thumbs{display:flex;gap:8px;flex-wrap:wrap;padding:2px 0 12px;border-bottom:1px solid var(--line)}
.thumbs a{position:relative;display:block;width:160px;border:1px solid var(--line);border-radius:5px;overflow:hidden;background:var(--bg)}
.thumbs a:hover{border-color:var(--accent)}
.thumbs img{display:block;width:100%;height:90px;object-fit:cover;object-position:center}
.thumbs span{position:absolute;left:0;bottom:0;background:rgba(17,24,39,.78);color:#fff;font-size:10px;font-weight:600;padding:1px 5px;border-radius:0 4px 0 0}
.identrow{display:grid;grid-template-columns:1fr 1fr;gap:10px 20px;padding:11px 0;border-bottom:1px solid var(--line)}
.identrow .wide{grid-column:1/-1}
.identrow .lbl{display:block;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);font-weight:600}
.identrow .val{display:block;font-size:13px;margin-top:2px}
.identrow .val.note{font-size:12px;color:var(--muted);line-height:1.5}
.identrow .terms{display:flex;flex-wrap:wrap;gap:4px;margin-top:4px;max-height:150px;overflow:auto}
.lnk.sm{font-size:11px;font-weight:600}
.identform{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap;padding:12px 0 2px;border-bottom:1px solid var(--line)}
.identform label{display:flex;flex-direction:column;gap:3px;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);font-weight:600}
.identform label.grow{flex:1;min-width:200px}
.identform input,.identform select{font:inherit;font-size:13px;text-transform:none;letter-spacing:0;color:var(--fg);padding:5px 8px;border:1px solid var(--line);border-radius:6px;background:var(--surface)}
.identform .hint{flex-basis:100%;margin:2px 0 0;font-size:11.5px;color:var(--muted);text-transform:none;letter-spacing:0;font-weight:400}


.intake{padding:12px 16px}
.intakehead{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding-bottom:10px;border-bottom:1px solid var(--hairline)}
.intakehead .rail{display:inline-flex;gap:3px}
.intakehead .rail i{display:inline-block;width:16px;height:6px;border-radius:2px;background:var(--n4)}
.intakehead .rail i.on{background:var(--a9)}
.intakeform{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap;padding-top:12px}
.intakeform label{display:flex;flex-direction:column;gap:3px;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);font-weight:600}
.intakeform label.grow{flex:1;min-width:210px}
.intakeform select,.intakeform input{font:inherit;font-size:13px;text-transform:none;letter-spacing:0;color:var(--fg);padding:5px 8px;border:1px solid var(--hairline);border-radius:var(--r2);background:var(--surface)}
.intakeform .hint{flex-basis:100%;margin:2px 0 0;font-size:11.5px;color:var(--muted);text-transform:none;letter-spacing:0;font-weight:400;line-height:1.5}

.scroller{overflow-x:auto;border:1px solid var(--hairline);border-radius:var(--r3);background:var(--card)}
table.track{border:none;border-radius:0;min-width:860px}
table.track.procstrip{min-width:0;width:100%}
table.track td{white-space:nowrap}
table.track td.next{white-space:normal;min-width:200px;font-size:12px}
.tick{color:var(--n8);font-weight:600}
.tick.on{color:var(--ok9)}
.site{font-size:12px}
.site.pending{color:var(--muted);text-decoration:underline dotted}

/* --- tracking: pipeline overview, state chips, progress strip --- */
.is-building{--sig:var(--a6);--sig-bg:var(--a2);--sig-fg:var(--a11)}
/* the pipeline overview: five clickable stage counts, tinted by stage */
.pipeline{display:flex;gap:8px;margin:0 0 18px;flex-wrap:wrap}
.pipe-seg{flex:1 1 128px;min-width:116px;display:flex;flex-direction:column;gap:1px;align-items:flex-start;
  background:var(--card);border:1px solid var(--line);border-top:3px solid var(--seg,var(--n7));
  border-radius:10px;padding:10px 13px;cursor:pointer;text-align:left;
  transition:box-shadow var(--dur1) var(--ease),transform var(--dur1) var(--ease)}
.pipe-seg:hover{box-shadow:var(--shadow-md);transform:translateY(-1px)}
.pipe-seg.on{box-shadow:var(--ring)}
.pipe-seg b{font-size:24px;line-height:1.1;font-variant-numeric:tabular-nums;letter-spacing:-.01em;color:var(--seg-ink,var(--n12))}
.pipe-seg span{font-size:11.5px;color:var(--muted)}
.pipe-seg.t-n{--seg:var(--n7);--seg-ink:var(--n11)}
.pipe-seg.t-a{--seg:var(--a6);--seg-ink:var(--a11)}
.pipe-seg.t-live{--seg:var(--a-solid);--seg-ink:var(--a11)}
.pipe-seg.t-wait{--seg:var(--wait9);--seg-ink:var(--wait11)}
.pipe-seg.t-ok{--seg:var(--ok9);--seg-ink:var(--ok11)}
/* the per-row state chip */
.bchip{display:inline-block;font-size:11px;font-weight:600;padding:2px 9px;border-radius:var(--r-state);
  border:1px solid transparent;line-height:1.5;white-space:nowrap}
.bchip.t-n{background:var(--n3);color:var(--n11);border-color:var(--n6)}
.bchip.t-a{background:var(--a2);color:var(--a11);border-color:var(--a6)}
.bchip.t-live{background:var(--a3);color:var(--a11);border-color:var(--a6)}
.bchip.t-wait{background:var(--wait3);color:var(--wait11);border-color:color-mix(in srgb,var(--wait9) 30%,transparent)}
.bchip.t-ok{background:var(--ok3);color:var(--ok11);border-color:color-mix(in srgb,var(--ok9) 30%,transparent)}
/* the six-step progress strip: one glance replaces six tick columns */
td.progcell{padding-top:7px;padding-bottom:7px}
.ptrack{display:inline-flex;gap:4px}
.pseg{width:19px;height:19px;border-radius:5px;display:inline-flex;align-items:center;justify-content:center;
  font-size:10.5px;font-weight:700;font-family:var(--mono);border:1px solid var(--n6);color:var(--n8);background:var(--n2)}
.pseg.is-done{background:var(--a-solid);border-color:var(--a-solid);color:var(--on-accent)}
.pseg.is-part{background:var(--wait3);border-color:var(--wait9);color:var(--wait11)}
.pseg.is-todo{background:var(--n2);border-color:var(--n6);color:var(--n8)}
.appfoot{max-width:1040px;margin:0 auto;padding:8px 20px 18px;font-size:11px;color:var(--muted);opacity:.75}
.computedline{display:inline-block;margin:0}
.inlineform{display:inline-block;margin:0 0 16px 8px;vertical-align:baseline}
td.next{font-size:12.5px;color:var(--muted);max-width:300px}
.actsearch{display:flex;gap:8px;align-items:center;margin:0 0 12px;flex-wrap:wrap}
.actsearch input[type=search]{flex:1 1 320px;min-width:220px;border:1px solid var(--line);border-radius:8px;padding:8px 11px;background:var(--card);color:var(--fg);font:inherit}
.modeform select{border:1px solid var(--line);border-radius:7px;padding:4px 8px;background:var(--card);color:var(--fg);font:inherit;font-size:12.5px}
.previewcard{margin:0 0 18px;border-left:3px solid var(--a-solid)}
.phasechip{display:inline-block;font:600 11px/1 var(--mono);padding:3px 6px;border-radius:5px;
background:var(--a3);color:var(--a11);border:1px solid var(--a6)}
.autogrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));gap:12px;margin:0 0 22px}
.autocard{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:14px 16px;
position:relative;overflow:hidden}
.autocard:before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--n6)}
.autocard.mode-automatic:before{background:var(--ok9)}
.autocard.mode-ask:before{background:var(--wait9)}
.autocard.mode-off:before{background:var(--n6)}
.autohead{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 6px}
.autohead h3{margin:0;font-size:14.5px;font-weight:650;letter-spacing:-.01em}
.autodial{margin-left:auto}
.autowhat{margin:0 0 8px;font-size:13px;line-height:1.55}
.autometa{margin:0 0 4px;font-size:11.5px;color:var(--muted);line-height:1.6}
.autometa b{color:var(--fg);font-weight:600}
.autolast{display:block;font-family:var(--mono);font-size:11px;color:var(--muted);margin-top:2px;
word-break:break-word}
.autoacts{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}
@media (max-width:520px){.phasechip{display:inline-block;font:600 11px/1 var(--mono);padding:3px 6px;border-radius:5px;
background:var(--a3);color:var(--a11);border:1px solid var(--a6)}
.autogrid{grid-template-columns:1fr}}
.usestep{display:flex;gap:12px;align-items:flex-start;margin:0 0 14px}
.usen{flex:0 0 24px;height:24px;border-radius:50%;background:var(--a-solid);color:var(--on-accent);
display:inline-flex;align-items:center;justify-content:center;font:700 12px/1 var(--mono);margin-top:2px}
.usestep .sub{margin:2px 0 4px}
.snippet{background:var(--n2);border:1px solid var(--line);border-radius:8px;padding:10px 12px;overflow-x:auto;font-size:12.5px;margin:8px 0 14px}
.snippet code{font-family:var(--mono);white-space:pre}
.prevlist{margin:6px 0 12px;padding-left:18px;font-size:13px;line-height:1.8}
td.actcell{white-space:nowrap}
.okword{color:var(--ok9);font-weight:600}
.warnword{color:var(--wait11);font-weight:600}
td.which{font-size:12px;line-height:1.7;max-width:520px}
.plegend{display:flex;flex-wrap:wrap;align-items:center;gap:6px 13px;margin:0 0 10px;font-size:11.5px;color:var(--muted)}
.plegend>span{font-weight:600;color:var(--fg)}
.plegend i{display:inline-flex;align-items:center;gap:5px;font-style:normal}
.plegend .pseg{width:16px;height:16px;font-size:9px}
.namecell .dct{font-family:var(--mono);font-size:11px}
td.num.ok{color:var(--ok9);font-weight:600}
td.num.gap{color:var(--risk9);font-weight:600}
.gap{color:var(--risk9)}
td.jira{font-size:12px;color:var(--muted)}
.rowacts{display:inline-flex;gap:7px;align-items:center}
.rowacts form{display:inline}

.linkbox{padding:11px 0;border-bottom:1px solid var(--hairline)}
.linkbox .lbl{display:block;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);font-weight:600}
.linkbox input{width:100%;margin-top:5px;font:inherit;font-size:12.5px;font-family:var(--mono);padding:7px 9px;border:1px solid var(--hairline-strong);border-radius:var(--r2);background:var(--surface);color:var(--fg)}
.linkbox .hint{display:block;margin-top:5px;font-size:11.5px;color:var(--muted);line-height:1.5}
.waitline{margin:2px 0 16px;font-size:13px}
.waitline summary{cursor:pointer;color:var(--muted);width:fit-content}
.waitline summary::marker{color:var(--accent-strong)}
.waitline[open] summary{color:var(--fg);margin-bottom:6px}
.waitline ul{margin:0;padding:0 0 0 20px;line-height:2}
.waitline li{list-style:disc}
.waitline form.inline{margin-left:10px}
label.linky{color:var(--accent-strong);font-size:12px;cursor:pointer;text-decoration:underline dotted;margin-left:10px}
button.linky{background:none;border:none;padding:0;color:var(--accent-strong);font:inherit;font-size:12px;cursor:pointer;text-decoration:underline dotted}
.findrow{display:flex;align-items:center;gap:10px;margin:0 0 14px}
.findrow input{font:inherit;font-size:14px;padding:8px 12px;border:1px solid var(--hairline-strong);border-radius:var(--r2);background:var(--surface);color:var(--fg);width:min(420px,100%)}
table.conns td.acell{max-width:640px}
table.conns .pill{margin-left:8px}
.pill.warn{background:var(--risk1);color:var(--risk9)}
.stgdet{margin:8px 0 0}
.stgs{list-style:none;margin:6px 0 0;padding:0;font-size:12.5px;line-height:2}
.stgs .tick{display:inline-block;width:16px;text-align:center}
.tick.wip{color:var(--accent-strong)}
.plannerbox{margin:0 0 14px}
.plannerbox textarea{font:inherit;font-size:14px;padding:8px 10px;border:1px solid var(--hairline-strong);border-radius:var(--r2);background:var(--surface);color:var(--fg);resize:vertical}
.planview{padding:16px;margin:0 0 16px}
.planview h3{margin:0 0 4px;font-size:14px}
.masspick{margin:0 0 14px}
.masspick select{font:inherit;padding:6px 10px;border:1px solid var(--hairline-strong);border-radius:var(--r2);background:var(--surface);color:var(--fg)}
.massbar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:10px 0}
.massval input{width:100%;font:inherit;font-size:13px;padding:5px 8px;border:1px solid var(--hairline);border-radius:var(--r2);background:var(--surface);color:var(--fg)}
.okbar{background:var(--ok-soft,rgba(46,160,67,.12));border:1px solid var(--hairline);border-radius:var(--r2);padding:8px 12px;font-size:13px;margin:0 0 10px}
.titlerow{display:flex;align-items:center;justify-content:space-between;gap:12px}
.newdemo{max-width:560px;display:flex;flex-direction:column;gap:14px;padding:18px}
.newdemo label{display:flex;flex-direction:column;gap:4px;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);font-weight:600}
.newdemo input,.newdemo select{font:inherit;font-size:14px;text-transform:none;letter-spacing:0;color:var(--fg);padding:8px 10px;border:1px solid var(--hairline-strong);border-radius:var(--r2);background:var(--surface)}
.newdemo .hint{font-size:11.5px;color:var(--muted);text-transform:none;letter-spacing:0;font-weight:400;line-height:1.5}
.newdemo button{align-self:flex-start}
.mktgen{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:14px;padding-top:13px;border-top:1px solid var(--line)}
.mktgen .meta{flex:1;min-width:240px;font-size:11.5px;color:var(--muted)}
.signrow{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:0 0 16px}
.signrow form.inline{margin:0}
details.shots{display:inline-block}
details.shots summary{cursor:pointer;font-size:12.5px;font-weight:600;padding:5px 12px;border:1px solid var(--line);border-radius:6px;background:var(--surface);list-style:none}
details.shots summary::-webkit-details-marker{display:none}
.shotlist{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}

/* --- type, motion, focus ------------------------------------------------- */
body{font-size:14px;line-height:1.4;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
h1{font-size:20px;line-height:1.25;letter-spacing:-.015em;font-weight:600;margin:0 0 4px}
h2{font-size:14px;line-height:1.25;letter-spacing:.01em;font-weight:600}
table{font-variant-numeric:tabular-nums}
code,.meta,.mono{font-family:var(--mono);font-variant-numeric:tabular-nums slashed-zero}
.stat b,.progn,.count{font-variant-numeric:tabular-nums}
@media (prefers-reduced-motion: no-preference){
  a,button,.btn,.pill,summary,input,select{transition:background-color var(--dur1) var(--ease),border-color var(--dur1) var(--ease),color var(--dur1) var(--ease),opacity var(--dur1) var(--ease)}
  .btn:active,button:active{transform:scale(.98)}
  @view-transition{navigation:auto}
  h1{view-transition-name:page-title}
  .stats{view-transition-name:stat-strip}
}
@media (prefers-reduced-motion: reduce){ @view-transition{navigation:none} }
:focus-visible{outline:2px solid var(--a8);outline-offset:2px;border-radius:var(--r1)}
:focus:not(:focus-visible){outline:none}

/* --- chrome -------------------------------------------------------------- */
header{border-bottom:1px solid light-dark(transparent,var(--hairline))}
header nav a{position:relative;padding:6px 2px;font-weight:500;opacity:.72}
header nav a:hover{opacity:1}
header nav a[aria-current="page"]{opacity:1}
header nav a[aria-current="page"]:after{content:"";position:absolute;left:0;right:0;bottom:-9px;height:2px;background:currentColor;border-radius:2px}
.themetoggle{background:none;border:1px solid transparent;color:inherit;opacity:.6;cursor:pointer;font-size:13px;padding:4px 7px;border-radius:var(--r2)}
.themetoggle:hover{opacity:1;border-color:rgb(255 255 255 / .22)}

/* --- density ------------------------------------------------------------- */
table th,table td{padding:var(--cell)}
table th{font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);font-weight:600;background:var(--n2);position:sticky;top:0;z-index:1}
table td{font-size:13px;border-bottom:1px solid var(--hairline)}
tbody tr:last-child td{border-bottom:none}
tbody tr:hover{background:var(--n3)}
.fields td,.fields th{padding:var(--cell-comfy);font-size:14px}

/* --- the progress rail: four states, blocked is not absence -------------- */
.prog i{width:12px;height:5px;border-radius:2px;background:var(--n4)}
.prog i.on{background:var(--a9)}
.prog i.now{background:var(--a9);box-shadow:0 0 0 1px var(--a8)}
.prog i.blocked{background:var(--wait9);background-image:repeating-linear-gradient(45deg,rgb(255 255 255 / .45) 0 2px,transparent 2px 5px)}
.waitpill{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;padding:2px 7px;border-radius:999px;background:var(--wait3);color:var(--wait9);border:1px solid transparent;white-space:nowrap}
.waitpill.risk{background:var(--risk3);color:var(--risk9)}
.pill.done{background:var(--ok3);color:var(--ok9);font-weight:600}
.waitpill em{font-style:normal;opacity:.75;font-variant-numeric:tabular-nums}

/* --- empty states: name the next action --------------------------------- */
.empty{padding:26px 0 30px;max-width:52ch}
.empty h3{font-size:15px;font-weight:600;margin:0 0 5px}
.empty p{margin:0 0 12px;color:var(--muted);font-size:13px;line-height:1.5}

/* --- the conflict decision surface -------------------------------------- */
.cf{background:var(--card);border:1px solid var(--hairline);border-radius:var(--r3);padding:12px 14px;margin:0 0 10px}
.cfhead{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.cfhead code{font-size:12px;background:var(--n3);padding:2px 7px;border-radius:var(--r1)}
.cfdemo{font-size:12px;font-weight:600}
.cfage{margin-left:auto;font-size:11.5px;color:var(--muted);font-variant-numeric:tabular-nums}
.cfwho{display:flex;flex-wrap:wrap;gap:4px 10px;margin:7px 0 0;font-size:11.5px}
.cfsides{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:10px 0 0}
.cfside{background:var(--n2);border:1px solid var(--hairline);border-radius:var(--r2);padding:8px 10px;min-width:0}
.cfside .lbl{display:block;font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-weight:600;margin-bottom:3px}
.cfside p{margin:0;font-size:12.5px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:11em;overflow:auto}
.cfside p b{font-weight:600;background:var(--wait3);color:var(--wait9);border-radius:2px;padding:0 2px}
.cfwhy{margin:9px 0 0;font-size:12px;color:var(--muted);line-height:1.5}
.cfown{display:flex;gap:8px;margin:8px 0 0;align-items:center}
.cfown input{flex:1;font:inherit;font-size:13px;padding:6px 9px;border:1px solid var(--hairline-strong);border-radius:var(--r2);background:var(--surface);color:var(--fg)}
.cfacts{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:11px;padding-top:10px;border-top:1px solid var(--hairline)}
.pill.hot{background:var(--risk3);color:var(--risk9)}
.sm{font-size:11.5px}
@media (max-width:640px){.cfsides{grid-template-columns:1fr}}

/* ==========================================================================
   PANEL ENGRAVING. The console reads as a machined front panel: mono carries
   every identifier, count and status, sans carries prose only, section heads
   are engraved labelled rules, and state is a signal channel down the left
   edge of a row rather than two lonely pills.
   This layer comes LAST so it overrides the legacy component rules above
   without deleting them; the token aliases keep those rules valid meanwhile.
   ========================================================================== */

/* 1. Accent fills repoint to --a-solid. This is the live WCAG fix. */
button.primary,.btn.primary,a.btn.primary,.filters a.on,.lnk.primary{
background:var(--a-solid);border-color:var(--a-solid);color:var(--on-accent)}

/* 2. Links become ink with a quiet underline; the accent belongs to controls.
   This is what stops the whole screen being grey with blue text, and it raises
   link contrast while keeping a non-colour cue. */
a{color:var(--n12);text-decoration:underline;text-decoration-color:var(--n8);
text-decoration-thickness:1px;text-underline-offset:2px}
a:hover{color:var(--a11);text-decoration-color:currentColor}
.btn,.lnk,.pill,.filters a,header nav a,.stat b a,.crumb a,details.fam>summary a{text-decoration:none}
/* Row hover reveals the name's underline instead of lighting the row like a
   button - grafted from the Broadsheet direction. */
.namecell a{text-decoration:underline;text-decoration-color:transparent}
tbody tr:hover .namecell a{text-decoration-color:var(--a9)}

/* 3. The shape rule, applied. Pill shape now MEANS state. */
.card,.stats,.scroller,.progline,.cf,.planview,.newdemo,.gate,details.grp{border-radius:var(--r-panel)}
button,.btn,input,select,textarea,.attn,.search,.findrow input{border-radius:var(--r-ctl)}
.pill,.waitpill,.filters a,ol.stages li{border-radius:var(--r-state)}
table,.prog,.prog i,.thumbs a{border-radius:var(--r-flat)}

/* 4. The signal bus. One class, whole-row signalling. */
.is-ok{--sig:var(--ok9);--sig-bg:var(--ok2);--sig-fg:var(--ok11)}
.is-wait{--sig:var(--wait9);--sig-bg:var(--wait2);--sig-fg:var(--wait11)}
.is-risk{--sig:var(--risk9);--sig-bg:var(--risk2);--sig-fg:var(--risk11)}
.is-stop{--sig:var(--stop9);--sig-bg:var(--stop2);--sig-fg:var(--stop11)}
.is-live{--sig:var(--a9);--sig-bg:var(--a2);--sig-fg:var(--a11)}
table.track tbody tr>td:first-child{box-shadow:inset var(--gutter) 0 0 var(--sig)}
.sig{box-shadow:inset var(--gutter-strong) 0 0 var(--sig)}

/* 5. Type, applied. h2 stops being a heading and becomes panel engraving. */
body{font-family:var(--font);font-size:var(--fs-3);line-height:var(--lh-3);
background:var(--s-page);color:var(--n12)}
h1{font-size:var(--fs-7);line-height:var(--lh-1);letter-spacing:var(--tr-title);
font-weight:var(--w-mid);margin:0 0 2px}
h2{display:flex;align-items:center;gap:8px;margin:30px 0 10px;padding:0 0 6px;
border-bottom:1px solid var(--hair);font:var(--w-bold) var(--fs-1)/1 var(--mono);
letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--n12)}
h2::before{content:"";flex:0 0 auto;width:3px;height:10px;background:var(--a9);border-radius:var(--r-tick)}
h2 .count{margin-left:auto;font-weight:var(--w-data);color:var(--n10);
text-transform:none;letter-spacing:var(--tr-mono);font-size:var(--fs-2)}
code,.meta,.mono,.progn,.evtime,.slug,td.num,.cfage,.namecell .meta,td .meta{
font-family:var(--mono);font-variant-numeric:var(--num);letter-spacing:var(--tr-mono)}
table th{font:var(--w-bold) var(--fs-1)/1 var(--mono);letter-spacing:var(--tr-label);
text-transform:uppercase;color:var(--n11);background:var(--s-well)}
table td{font-size:var(--fs-3)}
.card,.stats,.scroller,table,.progline,details.grp{background:var(--s-card);
box-shadow:inset 0 1px 0 var(--edge-top)}
p.sub{color:var(--n11);font-size:var(--fs-3);line-height:var(--lh-3);max-width:78ch}

/* 6. Progress dashes become ONE gauge with internal divisions - a fuel gauge you
   read peripherally in a 40-row table, not seven pieces of confetti. */
.prog{display:inline-grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:1px;
width:98px;height:7px;background:var(--hair);overflow:hidden;vertical-align:-1px}
.prog i{width:auto;height:auto;background:var(--n9);opacity:.32;border-radius:0}
.prog i.on{background:var(--a9);opacity:1}
.prog i.now,.prog i.wip{background:var(--a9);opacity:1;box-shadow:inset -2px 0 0 var(--a-lead)}
.prog i.blocked{background:var(--wait9);opacity:1;
background-image:repeating-linear-gradient(45deg,rgb(255 255 255/.45) 0 2px,transparent 2px 5px)}
.progn{font:var(--w-data) var(--fs-2)/1 var(--mono);letter-spacing:var(--tr-mono);
font-variant-numeric:var(--num);color:var(--n11)}
.progline .progn{color:var(--n12);font-weight:var(--w-bold)}
/* The video intake carried its own separate dash rail. One gauge language, so a
   four-segment rail and a seven-segment rail read as the same instrument. */
.intakehead .rail{display:inline-grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:1px;
width:72px;height:7px;background:var(--hair);overflow:hidden;vertical-align:-1px}
.intakehead .rail i{width:auto;height:auto;border-radius:0;background:var(--n9);opacity:.32}
.intakehead .rail i.on{background:var(--a9);opacity:1}

/* 7. Five identical chips become a keypad rail with exactly one filled key. */
.links{display:flex;flex-wrap:wrap;align-items:stretch;width:fit-content;max-width:100%;
border:1px solid var(--hair);border-radius:var(--r-ctl);overflow:hidden;
background:var(--s-card);margin:0 0 12px;gap:0}
.lnk{display:inline-flex;align-items:center;gap:6px;min-height:var(--tap-min);
padding:0 11px;border:0;border-radius:0;box-shadow:inset 1px 0 0 var(--hair-quiet);
font:var(--w-bold) var(--fs-0)/1 var(--mono);letter-spacing:var(--tr-label);
text-transform:uppercase;color:var(--n11);background:transparent}
.lnk:first-child{box-shadow:none}
.lnk:hover{background:var(--n3);color:var(--n12);text-decoration:none}
.lnk.primary{background:var(--a-solid);color:var(--on-accent);font-size:var(--fs-1);box-shadow:none}
.lnk.primary:hover{background:var(--a10);color:var(--on-accent)}
/* The per-video catalogue deep links are subordinate: their own quieter rail. */
.links.deep{margin:-4px 0 14px;background:transparent;border-color:var(--hair-quiet)}
.links.deep .lnk{color:var(--n10);font-size:var(--fs-0)}

/* 8. Stat cards become a readout cluster: one strip, no gaps, the numeral is the
   biggest type on the page. */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:0;
border:1px solid var(--hair);border-radius:var(--r-panel);overflow:hidden;
background:var(--s-card);margin:0 0 18px}
.stat{position:relative;padding:11px 14px 12px;border:0;border-radius:0;background:transparent;
box-shadow:inset 1px 0 0 var(--hair-quiet),inset 0 1px 0 var(--hair-quiet)}
.stat:before{content:none}
.stat b{display:block;font:var(--w-bold) var(--fs-8)/var(--lh-0) var(--mono);
letter-spacing:var(--tr-readout);font-variant-numeric:var(--num);color:var(--n12)}
.stat span{display:block;margin-top:5px;font:var(--w-bold) var(--fs-0)/1.2 var(--mono);
letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--n11)}
.stat em{display:block;margin-top:3px;font-size:var(--fs-1);line-height:var(--lh-2);
color:var(--n10);font-style:normal}
.stat.good{--sig:var(--ok9)}
.stat.hot{--sig:var(--risk9)}
.stat.good:after,.stat.hot:after{content:"";position:absolute;inset:0 0 auto;
height:var(--gutter);background:var(--sig)}
.stat.hot b{color:var(--risk11)}

/* 9. Native file inputs, styled with no JS and no markup change. */
input[type=file]{max-width:100%;width:100%;font:var(--w-data) var(--fs-2)/1.2 var(--mono);
letter-spacing:var(--tr-mono);color:var(--n11);padding:7px 8px;border:1px dashed var(--n7);
border-radius:var(--r-ctl);background:var(--s-well);cursor:pointer}
input[type=file]:hover{border-color:var(--a9)}
input[type=file]::file-selector-button{margin:-1px 10px -1px -1px;padding:0 10px;
min-height:var(--tap-min);font:var(--w-bold) var(--fs-0)/1 var(--mono);
letter-spacing:var(--tr-label);text-transform:uppercase;border:1px solid var(--hair-strong);
border-radius:3px;background:var(--s-card);color:var(--n12);cursor:pointer}
input[type=file]::file-selector-button:hover{background:var(--n3);border-color:var(--a9)}

/* 10. Status output is stamped, not lozenged-in-a-random-hex. Every old pill
   variant repoints onto the signal bus so dark mode works everywhere. */
/* Direct colours, NOT the signal bus: --sig-bg is DECLARED as transparent at :root,
   so var(--sig-bg,var(--n3)) never reaches its fallback and every plain pill came out
   invisible - including ADMIN on the dark header. The bus stays for rows and bands,
   where a class sets --sig-bg explicitly. */
.pill,.waitpill{display:inline-flex;align-items:center;gap:5px;
background:var(--n3);color:var(--n11);border:1px solid transparent;
font:var(--w-bold) var(--fs-0)/1 var(--mono);letter-spacing:var(--tr-label);
text-transform:uppercase;padding:4px 8px;white-space:nowrap}
.pill.est,.waitpill{background:var(--wait2);color:var(--wait11)}
.pill.ok,.pill.done{background:var(--ok2);color:var(--ok11)}
.pill.pub{background:var(--a2);color:var(--a11)}
.pill.bad,.pill.hot,.waitpill.risk{background:var(--risk2);color:var(--risk11)}
/* On the bezel, a pill is a stamped outline rather than a light chip. */
header .pill{background:rgb(255 255 255/.10);color:var(--chrome-fg-strong);
box-shadow:inset 0 0 0 1px var(--hair-chrome)}
.waitpill em{font-style:normal;opacity:.75;font-variant-numeric:var(--num)}

/* 11. The identity line becomes a slug of labelled key/value pairs divided by
   hairlines, so at 375px it lays out as tidy stamped rows instead of five lines
   of run-on text. Triage moves out into its own attention band. */
.slug{display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px;margin:4px 0 14px;
font:var(--w-data) var(--fs-2)/1.35 var(--mono);letter-spacing:var(--tr-mono);color:var(--n11)}
.slug>span{display:inline-flex;align-items:baseline;gap:6px}
.slug .k{font-size:var(--fs-0);font-weight:var(--w-bold);letter-spacing:var(--tr-label);
text-transform:uppercase;color:var(--n9)}
.slug .v{color:var(--n12)}
.slug .sep{width:1px;align-self:stretch;background:var(--hair-strong);margin:2px 0}
/* Its own class, NOT .attn: the library's "who owes the next move" cell already uses
   .attn, and banding every "nothing outstanding" cell turned that table into noise. */
.attnband{display:flex;align-items:center;gap:10px;min-height:var(--tap-min);padding:8px 12px;
margin:0 0 12px;border-radius:var(--r-ctl);background:var(--sig-bg);color:var(--sig-fg);
box-shadow:inset var(--gutter-strong) 0 0 var(--sig);font-size:var(--fs-3)}
.attnband .n{font:var(--w-bold) var(--fs-4)/1 var(--mono);font-variant-numeric:var(--num)}
.attnband a{margin-left:auto;color:inherit}
.attnband>span{flex:1;min-width:0}
.attnband button,.attnband .btn{white-space:nowrap;flex:0 0 auto}
.attnband form{flex:0 0 auto;margin-left:auto}
.attnband form+a{margin-left:0}

/* Mass changes as a conversation. Not a chat toy: the transcript is the audit of what an
   operator asked for, sitting next to the changelog of what actually happened. */
.chat{display:flex;flex-direction:column;gap:8px;margin:0 0 14px}
.turn{max-width:min(74ch,100%);padding:9px 12px;border-radius:var(--r-panel);background:var(--s-card);
box-shadow:inset 0 1px 0 var(--edge-top),0 0 0 1px var(--hair)}
.turn.me{align-self:flex-end;background:var(--a2);box-shadow:0 0 0 1px var(--a6)}
.turn .who{display:block;font:var(--w-bold) var(--fs-0)/1 var(--mono);letter-spacing:var(--tr-label);
text-transform:uppercase;color:var(--n10);margin-bottom:4px}
.turn p{margin:0;font-size:var(--fs-3);line-height:var(--lh-3);white-space:pre-wrap}
.turn .ran{display:inline-block;margin-top:6px;font:var(--w-bold) var(--fs-0)/1 var(--mono);
letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--ok11)}
.chatbox textarea{width:100%;min-width:0}
/* Where a change travels. One line per destination, with its own signal gutter, because
   "27 changed in the Hub" and "27 changed on the public site" are very different claims. */
.proplist{list-style:none;margin:6px 0 14px;padding:0;display:flex;flex-direction:column;gap:6px}
.proplist li{padding:8px 12px;background:var(--sig-bg,var(--s-well));border-radius:var(--r-ctl);
box-shadow:inset var(--gutter) 0 0 var(--sig);font-size:var(--fs-3)}
.proplist li b{margin-right:8px}
.proplist .propwhy{display:block;margin-top:3px;font-size:var(--fs-2);line-height:var(--lh-3);color:var(--n11)}
.cfask input{flex:1}

/* The working state for slow submits. An indeterminate bar, because the server has no
   progress to report - the model answers in one pass - plus a live elapsed clock so it
   is obvious the page is alive rather than hung. */
.busy{margin:14px 0 0;padding:12px 14px;background:var(--s-well);border-radius:var(--r-ctl);
box-shadow:inset var(--gutter-strong) 0 0 var(--a9)}
.busybar{height:3px;background:var(--n5);overflow:hidden;border-radius:var(--r-tick)}
.busybar i{display:block;height:100%;width:38%;background:var(--a9);border-radius:var(--r-tick);
animation:busyslide 1.15s var(--ease-panel) infinite}
@keyframes busyslide{0%{transform:translateX(-100%)}100%{transform:translateX(320%)}}
@media (prefers-reduced-motion:reduce){.busybar i{animation:none;width:100%;opacity:.5}}
.busyhead{display:flex;align-items:baseline;gap:10px;margin:9px 0 0;font-size:var(--fs-3)}
.busyhead .busywhat{font-weight:var(--w-mid)}
.busyhead .busysec{font:var(--w-bold) var(--fs-2)/1 var(--mono);font-variant-numeric:var(--num);
letter-spacing:var(--tr-mono);color:var(--n11)}
.busywhy{margin:4px 0 0;font-size:var(--fs-2);line-height:var(--lh-3);color:var(--n11)}

/* 12. Stage chips and the warn band join the bus too (they carried raw hexes). */
ol.stages li{font:var(--w-data) var(--fs-1)/1 var(--mono);letter-spacing:var(--tr-mono);
padding:5px 10px;background:var(--s-card);border:1px solid var(--hair);color:var(--n11)}
ol.stages li b{background:var(--n8)}
ol.stages li.done{color:var(--ok11);background:var(--ok2);border-color:transparent}
ol.stages li.done b{background:var(--ok9)}
ol.stages li.wip{color:var(--wait11);background:var(--wait2);border-color:transparent}
ol.stages li.wip b{background:var(--wait9)}
.warn{background:var(--wait2);border:1px solid transparent;color:var(--wait11);
box-shadow:inset var(--gutter-strong) 0 0 var(--wait9);border-radius:var(--r-ctl)}
.warn strong{color:var(--wait11)}
.err{color:var(--stop11)}
.progline .left.ok{color:var(--ok11)}
.cfside p b{background:var(--wait2);color:var(--wait11)}

/* 13. The header: a two-row bezel with a scrolling tab strip. The old stack was
   nav shrinking with no wrap rule; the "strikethrough" was an absolutely
   positioned rule at bottom:-9px landing in the next line's text once nav went
   vertical. Both are structural now: the active rule is an in-flow border on the
   item itself, so it physically cannot land in another item's text. */
header{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:0 18px;
padding:0 16px;min-height:52px;background:var(--s-chrome);
background-image:var(--chrome-grad);color:var(--chrome-fg-strong);
border-bottom:1px solid var(--hair-chrome)}
header .brand{font:var(--w-bold) var(--fs-1)/1 var(--mono);letter-spacing:var(--tr-label);
text-transform:uppercase;white-space:nowrap}
header nav{display:flex;gap:2px;overflow-x:auto;scrollbar-width:none;min-width:0}
header nav::-webkit-scrollbar{display:none}
/* The nav scrolls sideways when it does not fit, but a hidden scrollbar hides the fact.
   Under the widths where that happens, fade the trailing edge so "there is more" reads
   at a glance. */
@media (max-width:960px){
header nav{-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 26px),transparent);
mask-image:linear-gradient(90deg,#000 calc(100% - 26px),transparent)}
}
header nav a{position:static;flex:0 0 auto;display:inline-flex;align-items:center;
min-height:44px;padding:0 10px;border-bottom:2px solid transparent;color:var(--chrome-fg);
font-size:var(--fs-3);font-weight:var(--w-data);white-space:nowrap;opacity:1}
header nav a:hover{color:#fff;background:rgb(255 255 255/.06)}
header nav a[aria-current="page"]{color:#fff;border-bottom-color:var(--a8)}
header nav a[aria-current="page"]:after{content:none}
header .who{margin-left:0;display:flex;align-items:center;gap:8px;min-width:0;
font:var(--w-data) var(--fs-1)/1 var(--mono);color:var(--chrome-fg)}
header .who .email{max-width:min(38vw,220px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (max-width:720px){
header{grid-template-columns:1fr auto;grid-template-areas:"brand who" "nav nav";padding:0 12px}
header .brand{grid-area:brand;min-height:44px;display:flex;align-items:center}
header .who{grid-area:who}
header nav{grid-area:nav;margin:0 -12px;padding:0 12px;box-shadow:inset 0 1px 0 var(--hair-chrome)}
}

/* 14. The tap floor, as a token re-point plus hit-area growth rather than fat
   rows: min-height on controls only, so desktop density is untouched. */
@media (max-width:768px),(pointer:coarse){
:root{--tap-min:44px;--cell:11px 12px;--cell-data:10px 10px}
button,.btn,.lnk,.filters a,a.pill,label.btn,summary,input,select,textarea{min-height:44px}
button,.btn,.lnk,.filters a,label.btn{display:inline-flex;align-items:center;justify-content:center}
input[type=file]::file-selector-button{min-height:44px}
summary{padding-block:12px}
button.small,.btn.small{min-height:44px;padding-inline:12px;font-size:var(--fs-3)}
.rowacts{gap:10px}
.prog{width:100%;min-width:72px;height:8px}
}
@media (prefers-contrast:more){
:root{--hair:var(--n8);--hair-quiet:var(--n7);--muted:var(--n12);--sig:var(--n8)}
}
