/* resyn — one stylesheet, token driven. Light and dark share every rule; only tokens change. */
@view-transition{navigation:auto}  /* A visit to another page cross-fades, and transitions.js moves a run's figure; reduced motion turns it off below. */
@font-face{font-family:"Figtree";src:url("fonts/figtree-latin-wght.woff2") format("woff2");font-weight:300 900;font-style:normal;font-display:swap}

:root{
  --bg:#fbf9f7;--surface:#ffffff;--page-canvas:#fff;--surface-2:#f4f1ee;--surface-3:#ece8e4;
  --ink:#16131a;--ink-2:#3b3640;--muted:#6b6570;--faint:#736d78;
  --line:#e7e2dd;--line-strong:#d6cfc8;--control-line:#878089;
  --accent:#cf2c68;--accent-strong:#b31f57;--accent-ink:#ffffff;--accent-soft:#fdeaf1;--accent-line:#f6c3d6;--accent-text:#b82559;
  --warm:#fff6f1;--warm-line:#f7e4d8;
  --good:#1f9a55;--good-soft:#e5f5ec;--good-text:#17773f;
  --warn:#c77712;--warn-soft:#fdf1df;--warn-text:#8f5409;
  --bad:#c8322d;--bad-soft:#fdeceb;--bad-text:#a52c28;--bad-ink:#ffffff;
  --tier-bronze:#b26b3a;--tier-silver:#8e979f;--tier-gold:#c99a1c;--tier-platinum:#5f9db3;--tier-diamond:#4f86d1;
  --radius:14px;--radius-sm:10px;--radius-lg:20px;--radius-control:12px;--radius-pill:999px;
  --space-1:4px;--space-2:8px;--space-3:12px;--space-4:16px;--space-5:20px;--space-6:24px;--space-7:32px;--space-8:40px;--space-9:48px;--space-10:64px;--space-11:96px;
  --fs-xs:13px;--fs-sm:15px;--fs-md:17px;--fs-lg:20px;--fs-xl:24px;--fs-2xl:32px;--fs-display:clamp(28px,3.4vw,40px);
  --sans:"Figtree",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  color-scheme:light;
}
/* Heights, the same in every theme: buttons and fields are --control tall, compact ones --control-sm; the header is --header.
   Motion, the same in every theme: --motion-fast for a control's feedback, --motion for a state change, --motion-slow for
   a celebration, all easing out. */
:root{--control:48px;--control-sm:40px;--control-hero:56px;--header:60px;--motion-fast:150ms;--motion:250ms;--motion-slow:600ms;--motion-turn:45ms;--ease-out:cubic-bezier(.2,.7,.2,1)}
:root[data-theme=dark]{
  --bg:#141217;--surface:#1c1a20;--page-canvas:#fff;--surface-2:#232028;--surface-3:#2c2932;
  --ink:#f4f1f6;--ink-2:#d9d4de;--muted:#a49dab;--faint:#958e9c;
  --line:#2f2b35;--line-strong:#3d3844;--control-line:#7a7381;
  --accent:#ff5c93;--accent-strong:#ff7aa7;--accent-ink:#1a0b11;--accent-soft:#3a1b28;--accent-line:#5c2a3f;--accent-text:#ff8db3;
  --warm:#221b1d;--warm-line:#3a2c2d;
  --good:#3fcf7f;--good-soft:#173123;--good-text:#6fe0a0;
  --warn:#f0a43a;--warn-soft:#3a2a12;--warn-text:#f6c072;
  --bad:#ff6b66;--bad-soft:#3c1c1b;--bad-text:#ff9a96;--bad-ink:#1f0a09;
  --tier-bronze:#d08c5a;--tier-silver:#c3cad2;--tier-gold:#eab83f;--tier-platinum:#8dc3d8;--tier-diamond:#7fb0f0;
  color-scheme:dark;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme=light]){
    --bg:#141217;--surface:#1c1a20;--page-canvas:#fff;--surface-2:#232028;--surface-3:#2c2932;
    --ink:#f4f1f6;--ink-2:#d9d4de;--muted:#a49dab;--faint:#958e9c;
    --line:#2f2b35;--line-strong:#3d3844;--control-line:#7a7381;
    --accent:#ff5c93;--accent-strong:#ff7aa7;--accent-ink:#1a0b11;--accent-soft:#3a1b28;--accent-line:#5c2a3f;--accent-text:#ff8db3;
    --warm:#221b1d;--warm-line:#3a2c2d;
    --good:#3fcf7f;--good-soft:#173123;--good-text:#6fe0a0;
    --warn:#f0a43a;--warn-soft:#3a2a12;--warn-text:#f6c072;
    --bad:#ff6b66;--bad-soft:#3c1c1b;--bad-text:#ff9a96;--bad-ink:#1f0a09;
    --tier-bronze:#d08c5a;--tier-silver:#c3cad2;--tier-gold:#eab83f;--tier-platinum:#8dc3d8;--tier-diamond:#7fb0f0;
    color-scheme:dark;
  }
}

/* Base */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
main{scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--ink);font:var(--fs-md)/1.55 var(--sans);-webkit-font-smoothing:antialiased;overflow-x:hidden}
img,svg{max-width:100%}
a{color:inherit;text-decoration:none}
a:hover{color:var(--accent-text)}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer}
h1,h2,h3{margin:0;line-height:1.15;letter-spacing:-.02em}
p{margin:0}
:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:6px}
main{min-height:70vh;outline:none;padding-bottom:var(--space-8)}
main:focus-visible{outline:none}  /* Focused by script (the skip link, the keys that scroll it): no ring round the window. */
.icon{flex:none;vertical-align:middle}
.visually-hidden{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.skip-link{position:absolute;top:8px;left:8px;z-index:1000;transform:translateY(-200%);padding:var(--space-3) var(--space-4);border-radius:10px;background:var(--surface);color:var(--ink)}
.skip-link:focus{transform:none}
.muted{color:var(--muted)}
.small{font-size:var(--fs-sm)}
.nowrap{white-space:nowrap}
time{white-space:nowrap}  /* A date never breaks across lines: 2026-10 / 21 reads as another date. */
.mono{font-family:var(--mono);font-size:.9em}
.break{overflow-wrap:anywhere;word-break:break-word}
.wrap{width:100%;max-width:1440px;margin:0 auto;padding:0 clamp(var(--space-4),5vw,var(--space-11))}

/* Header and footer */
.site-header{border-bottom:1px solid var(--line);background:var(--bg)}
.header-inner,.footer-inner{max-width:1440px;margin:0 auto;padding:0 clamp(var(--space-4),5vw,var(--space-11));display:flex;align-items:center;justify-content:space-between;gap:var(--space-4)}
.header-inner{min-height:var(--header)}
.brand{display:inline-flex;flex:none;align-items:center;gap:var(--space-3);color:var(--ink)}
.brand:hover{color:var(--ink)}
.brand-mark{width:44px;height:44px;object-fit:contain;transition:transform var(--motion-fast) var(--ease-out)}
.brand-name{font-size:var(--fs-2xl);font-weight:700;letter-spacing:-.04em;line-height:1}
.main-nav{display:flex;align-items:center;gap:clamp(var(--space-4),3vw,var(--space-9));font-size:var(--fs-md);font-weight:500}
.main-nav>a{position:relative;min-width:24px;padding:var(--space-4) 0;color:var(--ink-2);text-align:center;transition:color var(--motion-fast) var(--ease-out)}
.main-nav>a:hover{color:var(--ink)}
.main-nav>a[aria-current=page]{color:var(--ink);font-weight:700}
/* The mark under the current page's link. Named for the page transition: a visit to another page slides it to that page's link. */
.main-nav .nav-mark{position:absolute;left:0;right:0;bottom:-1px;height:3px;border-radius:3px;background:var(--accent);view-transition-name:nav-current}
.label-short{display:none}
/* The name is clipped on its own label, not on the link: a clipping link would also clip the mark under it. */
.main-nav>.nav-account{display:flex;max-width:9em;white-space:nowrap}
.main-nav>.nav-account>.label-long,.main-nav>.nav-account>.label-short{min-width:0;overflow:hidden;text-overflow:ellipsis}
/* From 1000px the links fit at normal size, chat included, so at large text sizes they wrap onto a further line rather than
   running past the window's edge (WCAG 1.4.4). Below 1000px they keep their single row: at normal size they already squeeze
   or overflow a few pixels there, and wrapping would change that. */
@media (min-width:1000px){
  .main-nav{flex-wrap:wrap;justify-content:flex-end;row-gap:var(--space-2)}
  .main-nav>.nav-account{max-width:none}  /* A wrapping nav has room for the whole name. */
}
.nav-account-icon{display:none}
.theme-toggle{display:grid;place-items:center;width:48px;height:48px;padding:0;border:1px solid var(--control-line);border-radius:50%;background:var(--surface);color:var(--ink-2)}
.theme-toggle:hover{color:var(--ink);border-color:var(--line-strong)}
/* The two icons share the button's centre. The one that shows turns to rest and fades in; the other turns away and fades out. */
.theme-toggle>span{grid-area:1/1;display:grid;transition:opacity var(--motion) var(--ease-out),transform var(--motion) var(--ease-out)}
.theme-icon-dark{opacity:0;transform:rotate(-90deg)}
:root[data-theme=dark] .theme-icon-light{opacity:0;transform:rotate(90deg)}
:root[data-theme=dark] .theme-icon-dark{opacity:1;transform:none}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]) .theme-icon-light{opacity:0;transform:rotate(90deg)}:root:not([data-theme=light]) .theme-icon-dark{opacity:1;transform:none}}
.site-footer{border-top:1px solid var(--line);background:var(--bg)}
.footer-inner{min-height:0;flex-wrap:wrap;padding-top:var(--space-2);padding-bottom:var(--space-2)}
.footer-brand .brand-mark{width:30px;height:30px}
.footer-brand .brand-name{font-size:var(--fs-md)}
.footer-brand .brand-mark{width:24px;height:24px}
.footer-links{display:flex;flex-wrap:wrap;gap:var(--space-1) var(--space-4);font-size:var(--fs-xs);color:var(--muted)}
.footer-links a{display:inline-block;min-height:24px;line-height:24px}
.footer-links a{display:inline-flex;align-items:center;min-height:32px}
.footer-links a[aria-current=page]{color:var(--ink);font-weight:600}
.footer-links .footer-account{min-width:24px}  /* A target is 24px wide at least; a short name alone is 21px. */

/* Type */
p,li{text-wrap:pretty}  /* A paragraph or item never ends on a lone word, where the browser can keep two. */
.display{font-size:var(--fs-display);font-weight:800;letter-spacing:-.035em;line-height:1.05;text-wrap:balance}
.lede,.page-subtitle{margin-top:var(--space-2);color:var(--muted);font-size:var(--fs-md);line-height:1.4}
.panel-label{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-3);color:var(--muted);font-size:var(--fs-sm);font-weight:600}

/* Buttons */
.button{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-3);white-space:nowrap;min-height:var(--control);padding:0 var(--space-6);border:1px solid var(--accent);border-radius:var(--radius-control);background:var(--accent);color:var(--accent-ink);font-size:var(--fs-md);font-weight:650;line-height:1.1;text-align:center;transition:background-color var(--motion-fast) var(--ease-out),border-color var(--motion-fast) var(--ease-out),color var(--motion-fast) var(--ease-out),transform var(--motion-fast) var(--ease-out)}
.button[hidden]{display:none}  /* display:inline-flex would otherwise win over the hidden attribute. */
.button:hover{background:var(--accent-strong);border-color:var(--accent-strong);color:var(--accent-ink)}
.button.secondary{border-color:var(--line-strong);background:var(--surface-2);color:var(--ink)}
.button.secondary:hover{border-color:var(--faint);background:var(--surface-3);color:var(--ink)}
.button.ghost{border-color:transparent;background:transparent;color:var(--muted)}
.button.ghost:hover{color:var(--ink);background:var(--surface-2)}
.button.danger{border-color:var(--bad);background:var(--bad);color:var(--bad-ink)}
.button.danger:hover{filter:brightness(.92);color:var(--bad-ink)}
.button.small{min-height:var(--control-sm);gap:var(--space-2);padding:0 var(--space-4);border-radius:10px;font-size:var(--fs-sm)}
.button.hero{min-height:var(--control-hero);padding:0 var(--space-7);font-size:var(--fs-lg);font-weight:700}  /* One per page: the reason the page exists. */
.button.hero>svg{transition:transform var(--motion-fast) var(--ease-out)}  /* Its arrow leans the way it points while the pointer is on it (below, with hover). */
/* A press: the button shrinks a touch while the pointer is down. Only transform changes, so the layout holds. */
.button:active{transform:scale(.97)}
/* After a copy the icon is a check that scales in beside "Copied" (app.js); the copy icon comes back with the label. */
.copy-check{animation:copy-check-in var(--motion-fast) var(--ease-out)}
@keyframes copy-check-in{from{opacity:0;transform:scale(.5)}}
.back-link>.icon{transform:rotate(180deg)}  /* The icon set has no left arrow: the right arrow, turned round. */
button:disabled,input:disabled,select:disabled,textarea:disabled{cursor:not-allowed;opacity:.55}

/* Chips and badges */
.tone-good{color:var(--good-text)}
.tone-bad{color:var(--bad-text)}
.tone-mixed{color:var(--warn-text)}
.tone-neutral{color:var(--muted)}
.accent-link{color:inherit}
/* Links inside sentences carry an underline, not just a colour (WCAG 1.4.1): the text's own colour, pink on hover. */
.accent-link{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;text-decoration-color:currentColor;transition:color var(--motion-fast) var(--ease-out),text-decoration-color var(--motion-fast) var(--ease-out)}

/* Notes */
.note{display:flex;align-items:flex-start;gap:var(--space-3);margin-top:var(--space-5);color:var(--muted);font-size:var(--fs-sm);line-height:1.5}
.note .icon{flex:none;margin-top:2px;color:var(--muted)}

/* Home */
.home-hero{padding-top:var(--space-6)}
.setup-form{margin-top:var(--space-5)}
.kind-picker{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-3);margin:0;padding:0;border:0;min-width:0}
.kind-card{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2);min-height:0;padding:var(--space-4) var(--space-3);text-align:center;border:1.5px solid var(--control-line);border-radius:var(--radius);background:var(--surface);cursor:pointer;transition:border-color var(--motion-fast) var(--ease-out),background-color var(--motion-fast) var(--ease-out)}
.kind-card:hover{border-color:var(--ink-2)}
.kind-card input{position:absolute;opacity:0;pointer-events:none}
.kind-card:has(input:focus-visible){outline:3px solid var(--accent);outline-offset:3px}
.kind-card:has(input:checked){border-color:var(--accent);background:var(--accent-soft)}
.kind-icon{flex:none;color:var(--ink)}
.kind-text{display:grid;gap:var(--space-1)}
.kind-text strong{font-size:var(--fs-lg);font-weight:650}
.kind-text small{color:var(--muted);font-size:var(--fs-sm);line-height:1.35}
.kind-check{position:absolute;top:var(--space-3);right:var(--space-3);display:none;place-items:center;width:24px;height:24px;border-radius:50%;background:var(--accent);color:var(--accent-ink)}
.kind-card:has(input:checked) .kind-check{display:grid}
/* The three cards share rows, so icons, names and descriptions line up across them whatever wraps. */
.kind-picker{grid-template-rows:repeat(3,auto)}
.kind-card{display:grid;grid-row:span 3;grid-template-rows:subgrid;row-gap:var(--space-2);justify-items:center;align-items:start;align-content:start}
.kind-text{display:contents}
.kind-text strong{line-height:1.2}
.setup-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-5) var(--space-6);margin-top:var(--space-7)}
.js .setup-fields:not(:has(.hardware-fields:not([hidden]))){display:none}
.field-wide{grid-column:1/-1}
.field label,.form-field label{display:block;margin:0 0 var(--space-2);color:var(--ink-2);font-size:var(--fs-md);font-weight:500}
.optional{color:var(--faint);font-weight:400;font-size:.9em}
.field input,.field select,.form-field input,.form-field select,.form-field textarea{width:100%;min-height:var(--control);padding:var(--space-3) var(--space-5);border:1px solid var(--control-line);border-radius:var(--radius-control);background:var(--surface);color:var(--ink);font-size:var(--fs-md);appearance:none;-webkit-appearance:none}
.field input,.field select,.form-field input,.form-field select,.search-field input{height:var(--control);padding-top:0;padding-bottom:0}
.form-field textarea{min-height:110px;resize:vertical;line-height:1.5}
.field input::placeholder,.form-field input::placeholder,.form-field textarea::placeholder{color:var(--faint)}
.field input:focus,.field select:focus,.form-field input:focus,.form-field select:focus,.form-field textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.form-field select{background-image:none;padding-right:var(--space-9)}
.select-wrap{position:relative;display:block}
.select-wrap select{padding-right:var(--space-9);cursor:pointer}
.select-wrap>.icon{position:absolute;right:18px;top:50%;transform:translateY(-50%);pointer-events:none;color:var(--muted)}
.hardware-fields[hidden]{display:none}
.setup-actions{display:flex;flex-direction:column;align-items:flex-start;gap:var(--space-4);margin-top:var(--space-5)}
.setup-buttons{display:flex;gap:var(--space-3);flex-wrap:wrap}
.switch{display:inline-flex;align-items:center;gap:var(--space-4);color:var(--ink-2);font-size:var(--fs-md);cursor:pointer}
.switch input{position:absolute;opacity:0;width:1px;height:1px}
.switch-track{position:relative;width:52px;height:30px;border-radius:var(--radius-pill);background:var(--surface-3);border:1px solid var(--control-line);transition:background-color var(--motion-fast) var(--ease-out)}
.switch-track::after{content:"";position:absolute;top:3px;left:3px;width:22px;height:22px;border-radius:50%;background:#fff;border:1px solid var(--control-line);transition:transform var(--motion-fast) var(--ease-out)}
.switch input:checked+.switch-track{background:var(--accent);border-color:var(--accent)}
.switch input:checked+.switch-track::after{transform:translateX(22px)}
.switch input:focus-visible+.switch-track{outline:3px solid var(--accent);outline-offset:3px}
.alert{display:flex;gap:var(--space-3);align-items:flex-start;margin-bottom:var(--space-4);padding:var(--space-4) var(--space-5);border-radius:var(--radius-control);background:var(--bad-soft)}
.results{margin-top:var(--space-6)}
.results::before{content:"";display:block;height:1px;margin-bottom:var(--space-6);background:var(--line)}
.count{color:var(--muted);font-size:var(--fs-md);font-weight:500;letter-spacing:0}
.results-status{margin-top:var(--space-3);font-size:var(--fs-sm);color:var(--ink-2)}
.results-status.muted{color:var(--muted)}
.results-status+.results-status{margin-top:var(--space-1)}
.results-status .accent-link{white-space:nowrap}
.search-field{position:relative;display:block}
.search-field .icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--muted);pointer-events:none}
.search-field input{min-height:var(--control);border:1px solid var(--control-line);border-radius:var(--radius-control);background:var(--surface);font-size:var(--fs-sm);appearance:none;-webkit-appearance:none}
.search-field input{width:280px;max-width:100%;padding:var(--space-2) var(--space-4)}
.clear-link{padding:var(--space-2) var(--space-2);color:var(--muted);font-size:var(--fs-sm);background:none;border:0;text-decoration:underline;text-underline-offset:3px}
.task-category{margin:var(--space-2) 0;color:var(--accent-text);font-size:var(--fs-sm);font-weight:650}

/* Shared page details */
.breadcrumbs{display:flex;flex-wrap:wrap;gap:var(--space-3);margin-bottom:var(--space-3);color:var(--muted);font-size:var(--fs-sm)}
.breadcrumbs a{display:inline-block;min-height:24px;line-height:24px}
.breadcrumbs .crumb-sep{margin-right:var(--space-3)}  /* A separator stays with the crumb after it, so a wrap never strands it at a line's end. */
.breadcrumbs a:hover{color:var(--accent-text)}
.two-col{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
.two-col>div{min-width:0;padding-right:var(--space-7)}
.two-col>div+div{padding-right:0;padding-left:var(--space-7);border-left:1px solid var(--line)}
.kv{margin:0;font-size:var(--fs-md)}
.kv>div{display:grid;grid-template-columns:minmax(120px,12rem) minmax(0,1fr);gap:var(--space-4);padding:var(--space-3) var(--space-2);border-bottom:1px solid var(--line)}
.kv>div:last-child{border-bottom:0}
.kv dt{color:var(--muted)}
.kv dd{margin:0;min-width:0;color:var(--ink)}
.checksum{font-size:var(--fs-sm)}
.stack-list{margin:0;padding:0;list-style:none;border-top:1px solid var(--line)}
.stack-list>li{border-bottom:1px solid var(--line)}
.stack-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--space-4);padding:var(--space-4) var(--space-2)}
/* The dense variant: the run page's task rows, 12px top and bottom against 16px. */
.stack-row.dense{padding-top:var(--space-3);padding-bottom:var(--space-3)}
.stack-row strong{display:block;font-size:var(--fs-md);font-weight:600;overflow-wrap:anywhere}
.stack-row small{display:block;color:var(--muted);font-size:var(--fs-sm);overflow-wrap:anywhere}
.link-row{transition:background-color var(--motion-fast) var(--ease-out),color var(--motion-fast) var(--ease-out)}
.link-row:hover{background:var(--surface);color:var(--ink)}
.stack-list>li.muted{padding:var(--space-4) var(--space-2)}
.code{display:block;max-width:100%;margin:var(--space-4) 0;padding:var(--space-4) var(--space-4);overflow:auto;border:1px solid var(--line);border-radius:var(--radius-control);background:var(--surface-2);font:var(--fs-sm)/1.6 var(--mono);white-space:pre-wrap;overflow-wrap:anywhere}
.disclosure{margin-top:var(--space-4)}
.disclosure summary{cursor:pointer;color:var(--muted);font-weight:600}
.disclosure summary:hover{color:var(--ink)}
/* A disclosure the person opens eases its content into place: a few pixels and a fade, while the layout is already there.
   app.js marks it only while it opens, so one open on load, or opened from a link, is shown as it is, and a part shown
   later inside it does not move. */
details.is-opening[open]>:not(summary){animation:disclosure-in var(--motion) var(--ease-out)}
@keyframes disclosure-in{from{opacity:0;transform:translateY(-4px)}}

/* Generic pages (method, about, forms, receipts) */
.page-head{padding-top:var(--space-6);padding-bottom:var(--space-5)}
.page-head h1{font-size:var(--fs-display);font-weight:800;letter-spacing:-.035em;line-height:1.08;text-wrap:balance}
.page-head .button{margin-top:var(--space-4)}
.page-head .hero-actions .button{margin-top:0}

.form-shell>*{max-width:880px}
.panel,.form-panel,.about-card{padding:0;border:0;background:none}
.panel+.panel{margin-top:var(--space-7);padding-top:var(--space-5);border-top:1px solid var(--line)}
.panel:has(> .stack-list:last-child)+.panel{border-top:0;padding-top:0}
@media (max-width:1099px){.run-tasks+.comments{border-top:0;padding-top:0}}
.panel h2,.form-panel h2{font-size:var(--fs-xl);font-weight:700;margin-bottom:var(--space-3)}
.panel-intro{margin:var(--space-1) 0 var(--space-4);color:var(--muted);font-size:var(--fs-sm)}
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-5)}
.form-field{min-width:0}
.form-field.full{grid-column:1/-1}
.form-help{margin-top:var(--space-2);color:var(--muted);font-size:var(--fs-sm)}
.form-section-title{margin:var(--space-7) 0 var(--space-4)!important;padding-top:var(--space-6);border-top:1px solid var(--line)}
.form-actions{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;margin-top:var(--space-6)}
.form-actions form{margin:0}
.callout,.validation-summary{margin:0 0 var(--space-5);padding:var(--space-4) var(--space-5);border:1px solid var(--warm-line);border-radius:var(--radius);background:var(--warm);color:var(--ink-2);font-size:var(--fs-md);line-height:1.5}
.callout strong{display:block;margin-bottom:var(--space-1);color:var(--ink)}
.validation-summary{border-color:var(--bad);background:var(--bad-soft);color:var(--bad-text)}
.validation-summary h2{font-size:var(--fs-md);margin:0}
.validation-summary .validation-title{margin:0;font-weight:600}
.validation-summary ul{margin:var(--space-2) 0 0;padding-left:var(--space-5)}
.validation-summary a{color:inherit;text-decoration:underline;text-underline-offset:2px;padding-block:2px}  /* 24px tall: WCAG 2.5.8 asks that of a link on a line of its own. */
.field-error{display:block;margin-top:var(--space-2);color:var(--bad-text);font-size:var(--fs-sm)}
.field-error.alert{display:flex}
.form-field [aria-invalid=true]{border-color:var(--bad)}
.pre-wrap{white-space:pre-wrap;overflow-wrap:anywhere;color:var(--ink-2)}
.plain-list{padding-left:var(--space-5);color:var(--ink-2)}
.plain-list li{margin:var(--space-2) 0}
h2+.plain-list{margin-top:0}  /* Under a title the list's first item is spaced by the title's 12px, not the browser's 1em. */
.receipt-token{display:block;margin:var(--space-2) 0 var(--space-4);padding:var(--space-4) var(--space-4);border:1px solid var(--line);border-radius:var(--radius-control);background:var(--surface-2);overflow-wrap:anywhere;font:var(--fs-sm) var(--mono)}
.flag-details{margin-top:var(--space-6);padding-top:var(--space-4);border-top:1px solid var(--line)}
.flag-details summary{cursor:pointer;color:var(--muted);font-weight:600}
.flag-details summary:hover{color:var(--ink)}
.compact-form{margin-top:var(--space-4);padding:var(--space-5)}
.compact-form .form-field+.form-field{margin-top:var(--space-4)}
.start-steps{padding-bottom:var(--space-10)}
.start-steps>.panel,.start-steps>div>.panel{max-width:820px}
.step-number{display:inline-grid;place-items:center;width:32px;height:32px;margin-right:var(--space-3);border-radius:50%;background:var(--surface-3);color:var(--ink);font-size:var(--fs-md);font-weight:800;vertical-align:middle}
.hardware-help{margin-top:var(--space-2);font-size:var(--fs-sm);color:var(--ink-2)}
.hardware-help summary{min-height:44px;padding-block:var(--space-3)}  /* A disclosure: the native marker shows, as on the other disclosures. */
.hardware-help ul{margin-top:var(--space-2);padding-left:var(--space-5)}
.hardware-help li{margin:var(--space-1) 0}
.lede .accent-link{white-space:nowrap}
/* The chat is an app page: the frame fills the window beside the room, who you are, and the settings and rules folded;
   under 1100px they follow the frame in one scrolling pane, and on a phone the frame gives way to a button. */
.chat-shell{min-height:0;display:grid;grid-template-rows:auto minmax(0,1fr);padding-bottom:var(--space-3)}
.chat-head{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"title presence" "sub presence";column-gap:var(--space-7);row-gap:0;align-items:center;padding-top:var(--space-3);padding-bottom:var(--space-2)}
.chat-head h1{grid-area:title;font-size:var(--fs-xl);font-weight:800;letter-spacing:-.02em;line-height:1.2}
.chat-head .page-subtitle{grid-area:sub;margin:0;font-size:var(--fs-sm);line-height:1.4}
.chat-head .chat-presence,.chat-head .chat-down{grid-area:presence;max-width:30rem;margin:0}
.chat-head .chat-down{padding:var(--space-2) var(--space-4);font-size:var(--fs-sm)}
.chat-grid{position:relative;min-height:0;display:grid;align-content:start;gap:var(--space-5);overflow:auto;overscroll-behavior:contain;padding:var(--space-1);margin:0 calc(-1 * var(--space-1))}
.chat-main{position:relative;display:grid;gap:var(--space-3)}
.chat-frame{display:block;width:100%;height:min(72vh,720px);min-height:420px;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface)}
.chat-side{position:relative;min-width:0}
.chat-you{display:grid;gap:var(--space-2)}
.chat-you .chat-who{margin:0}
.chat-grid .accent-link{display:inline-block;min-height:24px;line-height:24px}  /* Links in the chat's own text are 24px tall, as the gallery's are. */
.chat-you+.panel{margin-top:var(--space-5);padding-top:var(--space-4);border-top:1px solid var(--line)}
.chat-side>.panel+.panel{margin-top:var(--space-4);padding-top:var(--space-4)}
.chat-more>.disclosure{margin-top:0}
.chat-more summary h2{display:inline;margin:0;font:inherit}
.chat-more .panel-intro{margin-top:var(--space-3)}
.chat-more .plain-list{margin:var(--space-3) 0 0}
.chat-presence{display:flex;align-items:center;gap:var(--space-2);margin-top:var(--space-3);color:var(--ink-2);font-weight:600}
.chat-open{display:none;margin:0}
.chat-about{margin:0}
@media (min-width:1100px){
  .chat-grid{grid-template-columns:minmax(0,3fr) minmax(0,2fr);grid-template-rows:minmax(0,1fr);column-gap:var(--space-9);align-content:stretch;overflow:visible;padding:0;margin:0}
  .chat-main{min-height:0;grid-template-rows:minmax(0,1fr)}
  .chat-side{min-height:0;overflow:auto;overscroll-behavior:contain;padding:var(--space-1);margin:0 calc(-1 * var(--space-1))}
}
@media (min-width:1100px) and (min-height:600px){.js .chat-frame{height:100%;min-height:0}}  /* The shell: the frame takes the window's height. */
@media (min-width:1400px){.chat-grid{grid-template-columns:minmax(0,2fr) minmax(0,1fr)}}
@media (max-width:700px){
  .chat-head{grid-template-columns:minmax(0,1fr);grid-template-areas:"title" "sub" "presence"}
  .chat-head .chat-presence,.chat-head .chat-down{margin-top:var(--space-2)}
}
.chat-members{margin-top:var(--space-2);overflow-wrap:anywhere}
.chat-log{display:grid;gap:var(--space-1);margin:var(--space-3) 0 0;padding:0;list-style:none;font-size:var(--fs-sm)}
.chat-log time{margin-right:var(--space-1);color:var(--muted);font-variant-numeric:tabular-nums}
.chat-log strong{color:var(--ink)}
.chat-log span{overflow-wrap:anywhere}
@media (max-width:700px){.chat-frame{display:none}.chat-open{display:block}}
.presence-dot{box-sizing:border-box;width:18px;height:18px;margin:-4px;border:4px solid var(--good-soft);border-radius:50%;background:var(--good);background-clip:padding-box}
.presence-dot.quiet{background:var(--faint);border-color:var(--surface-3)}
.about-grid{columns:2;column-gap:var(--space-9)}
.about-card{break-inside:avoid;margin-bottom:var(--space-7)}
.about-card p+p{margin-top:var(--space-3)}
@media (min-width:1400px){.about-grid{columns:3}}
@media (max-width:760px){.about-grid{columns:1}}
.about-card h2{margin-bottom:var(--space-2);font-size:var(--fs-lg);font-weight:700}
.about-card p{color:var(--muted)}
.optional-section{margin-top:var(--space-7);padding:var(--space-5) var(--space-5);border:1px solid var(--line);border-radius:var(--radius);background:var(--surface-2)}
.optional-section>summary{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--space-2) var(--space-4);cursor:pointer;list-style:none}
.optional-section>summary::-webkit-details-marker{display:none}
.optional-section>summary strong{font-size:var(--fs-md)}
.optional-section>summary span{color:var(--muted);font-size:var(--fs-sm)}
.optional-section[open]>summary{padding-bottom:var(--space-4);margin-bottom:var(--space-4);border-bottom:1px solid var(--line)}
.optional-section>p{margin-bottom:var(--space-4);color:var(--muted)}
.tag{display:inline-block;padding:3px var(--space-3);border-radius:var(--radius-pill);background:var(--surface-2);color:var(--muted);font-size:var(--fs-sm);font-weight:550;vertical-align:middle}
.tag-good{background:var(--good-soft);color:var(--good-text)}
.best-fit strong .tag{margin-left:var(--space-1);padding:0 var(--space-2);font-size:var(--fs-xs);font-weight:600;line-height:24px}
.mascot-inline{display:block;width:180px;height:auto;margin:0 0 var(--space-2)}
hr{margin:var(--space-7) 0;border:0;border-top:1px solid var(--line)}

/* Responsive */
.kind-card .kind-icon .icon{width:32px;height:32px}
.kind-text{justify-items:center}
@media (max-width:900px){
  .label-long{display:none}
  .label-short{display:inline}
  .two-col{grid-template-columns:1fr}
  .two-col>div,.two-col>div+div{padding:0;border-left:0}
  .two-col>div+div{margin-top:var(--space-7)}
}
@media (max-width:700px){
  .header-inner{min-height:56px}
  .brand-mark{width:36px;height:36px}
  .brand-name{font-size:var(--fs-xl)}
  .main-nav{gap:var(--space-4);font-size:var(--fs-sm)}
  .main-nav>a{padding:var(--space-4) 0}
  .footer-brand{display:none}
  .footer-inner{justify-content:flex-start}
  .footer-links .footer-account{display:none} /* The account is in the header; its name is in the link's label. */
  .theme-toggle{width:40px;height:40px}
  .setup-fields,.form-grid,.about-grid{grid-template-columns:1fr}
  .form-field.full{grid-column:auto}
  .setup-actions{align-items:stretch}
  .setup-buttons .button{width:100%}
  .hero-actions>.button{flex:1 1 0;min-width:max-content} /* Equal widths when they share a row, full width when they do not. */
  .hero-actions>.button.hero{flex:1 1 100%;min-width:0;padding:0 var(--space-5);white-space:normal} /* Full width is the column's width: the words wrap inside it at larger text rather than overhang a 320px column. */
  .search-field{flex:1 1 0;min-width:0}
  .search-field input{width:100%}
  .catalog-tools{flex-wrap:nowrap}
  .catalog-tools .button{flex:none}
  .kv>div{grid-template-columns:1fr;gap:2px}
}
@media (max-width:600px){
  .main-nav.with-chat .nav-about{display:none} /* Six links do not fit; About is still in the footer. */
}
@media (max-width:580px){
  .brand-name{display:none} /* The mark stays; five links need the room. */
}
@media (max-width:486px){
  .main-nav .nav-about{display:none} /* Six links need 487px to fit; below that About is still in the footer. */
}
@media (max-width:440px){
  .main-nav{gap:var(--space-3)}
}
@media (max-width:420px){
  .main-nav{font-size:var(--fs-xs)}
  /* The account link is its icon alone here; its name stays in the footer and in the link's label. */
  .main-nav>.nav-account .label-short,.main-nav>.nav-account .label-long{display:none}
  .main-nav>.nav-account{display:inline-flex;justify-content:center;min-width:24px}
  .nav-account-icon{display:inline-flex;align-items:center}
}
@media (max-width:380px){
  .header-inner{gap:var(--space-2)}
  .main-nav{gap:var(--space-2)}
}
@media (max-width:340px){
  /* With the chat link there is no room for the account too: its link stays in the footer here. */
  .main-nav.with-chat>.nav-account{display:none}
  .footer-links.with-chat .footer-account{display:inline-flex}
}
@media (prefers-reduced-motion:reduce){
  @view-transition{navigation:none}  /* No page transition: the next page appears at once. */
  html,main{scroll-behavior:auto}
  *,*::before,*::after{transition:none!important;animation-name:none!important}  /* Every animation ends on the element's own style, so none leaves the final state. */
}
/* A page's cross-fade, and a run's figure moving between pages, take --motion and ease out. */
::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation-duration:var(--motion);animation-timing-function:var(--ease-out)}
/* Arrival (motion.js): a block marked data-reveal, or each child of one marked stagger, rises into place once it is on screen,
   those on screen together --motion-turn apart (--turn, 0 to 7). Held back before that only under html.motion, which theme.js sets
   where the script can release it: with no script, or reduced motion, a page shows whole at once. A held block is opacity 0 and
   nothing else: it keeps its layout box and its place, so nothing scrolls, lands or anchors differently, and only the arriving block
   moves, for --motion. The arrival starts when motion.js adds is-in and backwards fill keeps the block unseen through its --turn
   delay; the animation ends on the element's own style, so a hover or a press after it transitions as ever.
   overflow-anchor: the block's rise moves it 10px while the browser restores a Back position, so it is not a scroll anchor. */
@keyframes rise-in{from{opacity:0;transform:translateY(10px)}}
.motion [data-reveal]:not([data-reveal=stagger]),.motion [data-reveal=stagger]>*{--turn:0;overflow-anchor:none}
.motion [data-reveal]:not([data-reveal=stagger]):not(.is-in),.motion [data-reveal=stagger]>:not(.is-in){opacity:0}
.motion [data-reveal].is-in,.motion [data-reveal=stagger]>.is-in{animation:rise-in var(--motion) var(--ease-out) calc(var(--turn) * var(--motion-turn)) backwards}

/* Report page and shared extras */
.report-outcome{display:flex;align-items:center;gap:var(--space-4);margin-bottom:var(--space-7);padding:var(--space-5) var(--space-6);border:1px solid var(--line);border-radius:var(--radius-lg);background:var(--surface-2)}
.report-outcome strong{display:block;font-size:var(--fs-xl);font-weight:750}
.report-outcome small{color:var(--muted);font-size:var(--fs-sm)}
.tone-card-good.report-outcome{background:var(--good-soft);border-color:var(--good-soft)}
.tone-card-bad.report-outcome{background:var(--bad-soft);border-color:var(--bad-soft)}
.tone-card-mixed.report-outcome{background:var(--warn-soft);border-color:var(--warn-soft)}
.report-cols h2{margin-bottom:var(--space-3);font-size:var(--fs-xl);font-weight:700}
.report-cols h2:not(:first-child){margin-top:var(--space-7)}
.error-page{text-align:left}
.page-head>.button{justify-self:start}
.form-field select:not(.select-wrap select){background:var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%238d8792' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 16px center}

/* Admin */
.admin-user{display:inline-flex;align-items:center;gap:var(--space-2);color:var(--ink-2);font-weight:600}
.inline-form{display:inline;margin:0}
.admin-nav{display:flex;gap:var(--space-1) var(--space-2);flex-wrap:wrap;padding-top:var(--space-4);padding-bottom:var(--space-4);border-bottom:1px solid var(--line)}
.admin-nav a{padding:var(--space-2) var(--space-4);border-radius:var(--radius-pill);color:var(--ink-2);font-size:var(--fs-sm);font-weight:550}
.admin-nav a:hover{background:var(--surface-2);color:var(--ink)}
.admin-nav a[aria-current=page]{background:var(--accent-soft);color:var(--accent-text)}
.admin-main{padding-top:var(--space-7)}
.admin-head{margin-bottom:var(--space-6)}
.admin-head h1{font-size:var(--fs-2xl);font-weight:800;letter-spacing:-.03em;overflow-wrap:anywhere}
.admin-head p{margin-top:var(--space-2);display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-2)}
.admin-card{padding:0}
.admin-card+.admin-card,.admin-columns>div>.admin-card+.admin-card{margin-top:var(--space-7)}
form.admin-card,.admin-card.one-time{padding:var(--space-6);border:1px solid var(--line);border-radius:var(--radius-lg);background:var(--surface)}
.admin-columns>div>*+*{margin-top:var(--space-6)}
.admin-card h2{margin-bottom:var(--space-4);font-size:var(--fs-lg);font-weight:700}
.admin-card .form-field+.form-field{margin-top:var(--space-4)}
.section-gap{margin-top:var(--space-7)}
.admin-columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-7) var(--space-9);align-items:start;margin-top:var(--space-7)}
.admin-columns.wide-left{grid-template-columns:minmax(0,1.6fr) minmax(280px,1fr)}
.admin-columns>*{min-width:0}  /* A column takes the window's width even when a command or a table in it is wider: that block scrolls itself. */
.stat-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border-top:1px solid var(--line);border-bottom:1px solid var(--line)}  /* Nine cards: three rows of three, so no corner is left empty. */
.stat-card{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-5) var(--space-5);color:var(--ink)}
.stat-card{border-left:1px solid var(--line)}
.stat-card:nth-child(3n+1){padding-left:0;border-left:0}
.stat-card:nth-child(n+4){border-top:1px solid var(--line)}
.stat-card:hover{color:var(--accent-text)}
.stat-card span{color:var(--muted);font-size:var(--fs-sm)}
.stat-card strong{font-size:var(--fs-2xl);font-weight:800;line-height:1}
.stat-card.attention strong{color:var(--warn-text)}
.stat-card.flagged strong{color:var(--bad-text)}
.admin-list{margin:0;padding:0;list-style:none}
.admin-list li{display:grid;gap:2px;padding:var(--space-3) 0;border-bottom:1px solid var(--line)}
.admin-list li:last-child{border-bottom:0}
.admin-list span{color:var(--ink-2);font-size:var(--fs-sm);overflow-wrap:anywhere}
.admin-list small{color:var(--muted);font-size:var(--fs-xs)}
.state{display:inline-block;padding:var(--space-1) var(--space-3);border-radius:var(--radius-pill);background:var(--surface-2);color:var(--muted);font-size:var(--fs-xs);font-weight:600;text-transform:capitalize;white-space:nowrap}
.state-visible{background:var(--good-soft);color:var(--good-text)}
.state-pending{background:var(--warn-soft);color:var(--warn-text)}
.state-flagged,.state-rejected,.state-withdrawn{background:var(--bad-soft);color:var(--bad-text)}
.state-tabs{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-bottom:var(--space-4)}
.state-tabs a{display:inline-flex;align-items:center;gap:var(--space-2);min-height:var(--control-sm);padding:0 var(--space-4);border:1px solid var(--line);border-radius:var(--radius-pill);background:var(--surface);color:var(--ink-2);font-size:var(--fs-sm)}
.state-tabs a[aria-current=page]{border-color:var(--accent);color:var(--accent-text);font-weight:650}
.count-pill{min-width:22px;padding:0 var(--space-2);border-radius:var(--radius-pill);background:var(--surface-2);color:var(--muted);font-size:var(--fs-xs);text-align:center}
.table-wrap{position:relative;overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius-lg);background:var(--surface)}
.admin-table{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
.admin-table th{padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--line);color:var(--muted);font-size:var(--fs-xs);font-weight:600;text-align:left;text-transform:uppercase;letter-spacing:.03em}
.admin-table td{padding:var(--space-4) var(--space-4);border-bottom:1px solid var(--line);vertical-align:top}
.admin-table tr:last-child td{border-bottom:0}
.admin-table td small{display:block;margin-top:2px;color:var(--muted);font-size:var(--fs-xs)}
.admin-table tbody tr{position:relative}
.admin-table tbody tr:hover{background:var(--surface-2)}
.admin-table td.open-cell{width:1%;white-space:nowrap}
.table-link{display:inline-flex;align-items:center;min-width:24px;min-height:24px;font-weight:650}  /* A link in a table is a 24 x 24 px target (docs Components). */
.table-link::after{content:"";position:absolute;inset:0}
/* The row's own controls sit above its stretched link, or the link takes their clicks. */
.admin-table .disclosure>summary{min-height:24px;line-height:24px}
.admin-table td form,.admin-table td button,.admin-table td details,.admin-table td summary,.admin-table td a:not(.table-link),.admin-table td input,.admin-table td select{position:relative;z-index:1}
.empty-cell{padding:var(--space-7) var(--space-4)!important;color:var(--muted);text-align:center}
.row-actions{display:flex;gap:var(--space-2);justify-content:flex-end;flex-wrap:wrap}
.admin-flash{display:flex;align-items:flex-start;gap:var(--space-3);margin:0 0 var(--space-4);padding:var(--space-4) var(--space-5);border-radius:var(--radius-control);font-size:var(--fs-sm)}
.admin-flash.bad{background:var(--bad-soft);color:var(--bad-text)}
.admin-flash.good{background:var(--good-soft);color:var(--good-text)}
.admin-flash .icon{margin-top:1px}
.timeline{margin:0;padding:0;list-style:none}
.timeline li{padding:var(--space-3) 0 var(--space-3) var(--space-4);border-left:2px solid var(--line)}
.timeline strong{display:block;font-size:var(--fs-sm)}
.timeline small{color:var(--muted);font-size:var(--fs-xs)}
.timeline p{margin-top:var(--space-1);color:var(--ink-2);font-size:var(--fs-sm)}
.one-time{margin-bottom:var(--space-4);border-color:var(--warn);background:var(--warn-soft)}
.action-form textarea{min-height:90px}
.auth-shell{display:flex;flex-direction:column;align-items:center;padding:clamp(var(--space-4),5vw,var(--space-9)) 0}
.auth-card{width:100%;max-width:460px;padding:var(--space-7);border:1px solid var(--line);border-radius:var(--radius-lg);background:var(--surface)}
.auth-card h1{margin-top:0;font-size:var(--fs-2xl);font-weight:800;letter-spacing:-.03em}
.auth-card>p{margin-top:var(--space-2)}
.auth-form{margin-top:var(--space-6)}
.auth-form .form-field+.form-field{margin-top:var(--space-4)}
.auth-form .admin-flash{margin-top:var(--space-3)}
.auth-submit{width:100%;margin-top:var(--space-6)}
.auth-step{display:flex;align-items:center;gap:var(--space-3);margin:var(--space-6) 0 var(--space-2);font-size:var(--fs-lg);font-weight:700}
.auth-step span{display:grid;place-items:center;width:26px;height:26px;border-radius:50%;background:var(--surface-2);color:var(--ink-2);font-size:var(--fs-sm)}
.auth-foot{display:flex;align-items:flex-start;gap:var(--space-2);margin-top:var(--space-5)}
.auth-foot>.icon{margin-top:var(--space-1)}  /* The 16px shield centres on the first line of a note that wraps (15px text, 1.55 line height). */
.qr-box{display:flex;justify-content:center;margin:var(--space-4) 0;padding:var(--space-3);border-radius:var(--radius-control);background:var(--page-canvas)}
.qr-box svg{width:185px;height:185px}
.secret-key{margin:var(--space-3) 0;padding:var(--space-3);border-radius:10px;background:var(--surface-2);font-size:var(--fs-md);letter-spacing:.06em}
.code-input{font:600 var(--fs-xl) var(--mono)!important;letter-spacing:.3em;text-align:center}
@media (max-width:900px){
  .admin-columns,.admin-columns.wide-left{grid-template-columns:1fr}
}
@media (max-width:700px){
  .admin-table td{overflow-wrap:anywhere} /* Every cell wraps: a long unbroken model name would otherwise widen its card past the window. */
  .admin-table td:last-child{white-space:normal}
  .admin-table td:last-child .inline-form{display:block}
  .admin-table td:last-child>.inline-form+.inline-form{margin-top:var(--space-2)}  /* Stacked forms only: beside each other in a row-actions flex, they stay level. */
  .admin-user{display:none}
  .auth-card{padding:var(--space-6) var(--space-5)}
  /* Phones: each row is a card and each cell names its column (data-label), so no column is hidden or squeezed. */
  .table-wrap:has(>.admin-table){overflow:visible;border:0;background:none}
  .admin-table,.admin-table tbody{display:grid;gap:var(--space-3)}
  .admin-table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .admin-table tbody tr{display:grid;gap:var(--space-3);padding:var(--space-4);border:1px solid var(--line);border-radius:var(--radius-lg);background:var(--surface)}
  .admin-table td{display:block;padding:0;border:0}
  .admin-table td:empty{display:none}  /* A cell with nothing in it (a login's detail) is left out of its card. */
  .admin-table td[data-label]::before{display:block;margin-bottom:2px;color:var(--muted);font-size:var(--fs-xs);font-weight:600;text-transform:uppercase;letter-spacing:.03em;content:attr(data-label)}
  .admin-table td.open-cell{position:absolute;top:var(--space-4);right:var(--space-4);width:auto;padding:0;pointer-events:none}
  .admin-table tr:has(>.open-cell)>td:first-child{padding-right:var(--space-7)}
  /* The section nav wraps on a phone, inside the page grid: every section is on screen and the current one is marked. */
  nav.admin-nav>a{flex:none;display:inline-flex;align-items:center;min-height:var(--control-sm);padding:var(--space-2) var(--space-3)}  /* Narrower pills: the sections take three or four rows, not five. */
}
.admin-columns>.admin-card+.admin-card{margin-top:0}
.auth-form .disclosure{margin:var(--space-1) 0 var(--space-5)}
.admin-list a{color:var(--ink);display:inline-flex;align-items:center;min-height:24px}
.admin-list a:hover{color:var(--accent-text)}
.page-subtitle,.lede,.results-status,.panel-intro,.note>span,.setup-intro,.board-note,.form-help,p.muted.small{max-width:60ch}
.kind-legend{margin-bottom:var(--space-3);padding:0;color:var(--ink-2);font-size:var(--fs-md);font-weight:500}
.kind-picker+.field-error{margin-top:var(--space-2)}
.button.is-busy,button.is-busy{cursor:progress;opacity:.7}

/* Speed reports */
.speed-section{margin-bottom:var(--space-7);padding-bottom:var(--space-6);border-bottom:1px solid var(--line)}
.wrap>.speed-section:last-child,.suite-grid>.speed-section:last-child{margin-bottom:0;padding-bottom:0;border-bottom:0}
.speed-section h3{margin-top:var(--space-6);font-size:var(--fs-lg);font-weight:650}
.table-scroll{position:relative;max-width:calc(100% + 2 * var(--space-1));margin:var(--space-4) calc(-1 * var(--space-1)) 0;padding:0 var(--space-1);overflow-x:auto}  /* Positioned: the screen-reader-only text in its cells stays inside it, not main. It reaches 4px past the column so a focus ring at the edge is not cut off. */
.speed-table{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
.speed-table th,.speed-table td{padding:var(--space-3) var(--space-3);border-bottom:1px solid var(--line);text-align:left;vertical-align:baseline;white-space:nowrap}
.speed-table thead th{color:var(--muted);font-weight:600}
.speed-table tbody th{font-weight:600;color:var(--ink)}
.speed-table .num{text-align:right;font-variant-numeric:tabular-nums}
.speed-table a{display:inline-flex;align-items:center;justify-content:center;min-width:24px;min-height:24px}
.tag-measured{display:inline-block;margin-left:var(--space-1);padding:0 var(--space-2);border-radius:var(--radius-pill);background:var(--good-soft);color:var(--good-text);font-size:var(--fs-xs);font-weight:600}
.speed-figure{display:flex;align-items:baseline;gap:var(--space-1);min-width:96px;font-size:var(--fs-lg);font-weight:750;font-variant-numeric:tabular-nums;line-height:1.2;white-space:nowrap}
.speed-figure small{color:var(--muted);font-size:var(--fs-xs);font-weight:500}
.speed-file{display:grid;gap:var(--space-1)}
.speed-file .mono{color:var(--muted);font-size:var(--fs-sm)}
.signed-as{margin-top:var(--space-6)}

/* Accounts */
.account-shell{padding-bottom:var(--space-10)}
.account-shell>*{max-width:480px}  /* A narrow form, on the same left edge as the page heading. */
.account-form .form-field+.form-field{margin-top:var(--space-5)}
.account-form .callout{margin:var(--space-6) 0 0}
/* A form with a note beside it rather than under it, where there is room */
@media (min-width:900px){
  .account-shell>.account-form:has(>.callout){max-width:none;display:grid;grid-template-columns:480px minmax(240px,420px);column-gap:var(--space-9);align-items:start}
  .account-form:has(>.callout)>*{grid-column:1}
  .account-form:has(>.callout)>.callout{grid-column:2;grid-row:1/span 4;margin:0}
}
.account-switch{margin-top:var(--space-5);color:var(--ink-2)}
.profile-grid{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(260px,.9fr);gap:var(--space-9);align-items:start;padding-bottom:var(--space-10)}
.profile-grid h2+.stack-list,.profile-grid h2+p{margin-top:var(--space-3)}
.setup-row{grid-template-columns:minmax(0,1fr) auto auto;gap:var(--space-2)}
#api-token .callout code{display:block;margin-top:var(--space-2)}
/* A profile without its owner's aside: the run reports on the left, the short panels stacked on the right */
.profile-grid.no-aside{grid-template-columns:minmax(0,1.2fr) minmax(0,1fr);row-gap:0}  /* The panels are grid items here: their own 32px margin is the gap. */
.profile-grid.no-aside>div{display:contents}
.profile-grid.no-aside>div>.panel{min-width:0;grid-column:2}
.profile-grid.no-aside>div>.panel[aria-labelledby=speed-title]{grid-column:1;grid-row:1/span 4;margin-top:0;padding-top:0;border-top:0}
@media (max-width:760px){.profile-grid,.profile-grid.no-aside{grid-template-columns:1fr;gap:var(--space-7)}.profile-grid.no-aside>div{display:block}}

/* Hardware cards on phones: three compact choices in one row, the long description kept for screen readers. */
@media (max-width:700px){
  .kind-picker,.form-shell .kind-picker{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-2)}
  .kind-card,.form-shell .kind-card{flex-direction:column;justify-content:center;gap:var(--space-2);min-height:88px;padding:var(--space-3) var(--space-2);text-align:center}
  .kind-card .kind-icon .icon,.form-shell .kind-card .kind-icon .icon{width:28px;height:28px}
  .kind-text strong{font-size:var(--fs-sm);line-height:1.25}
  .kind-text small{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .kind-check{top:var(--space-2);right:var(--space-2)}
  .kind-picker,.form-shell .kind-picker{grid-template-rows:repeat(2,auto)}
  .kind-card,.form-shell .kind-card{grid-row:span 2}
}


.section-title{margin-bottom:var(--space-3);font-size:var(--fs-xl);font-weight:700}

.speed-failed{color:var(--bad-text);font-size:var(--fs-sm);font-weight:650;white-space:nowrap}
.result-picker{border:0;margin:0;padding:0;min-width:0}
.result-picker legend{margin-bottom:var(--space-2);font-weight:600}
.choice-row{display:flex;flex-wrap:wrap;gap:var(--space-2)}
.choice-row>.choice{white-space:nowrap}
/* On a phone a row of choices is two columns; a row in the navigation (the gallery's tasks, the leagues) wraps onto more lines. */
@media (max-width:700px){
  .choice-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-2)}
  .choice-row>.choice{white-space:normal;min-width:0;min-height:var(--control);padding:0 var(--space-2);font-size:var(--fs-sm);line-height:1.1;border-radius:var(--radius-pill)}  /* Two lines fit the 48px control; the chips share one pill radius. */
  nav.choice-row{display:flex;flex-wrap:wrap}
  nav.choice-row>.choice{flex:none;white-space:nowrap;padding:0 var(--space-4)}
}
.choice{display:inline-flex;align-items:center;gap:var(--space-2);min-height:var(--control-sm);padding:0 var(--space-4);border:1.5px solid var(--control-line);border-radius:var(--radius-pill);background:var(--surface);color:var(--ink);font-weight:550;cursor:pointer;transition:border-color var(--motion-fast) var(--ease-out),background-color var(--motion-fast) var(--ease-out),color var(--motion-fast) var(--ease-out)}
.choice:has(input:checked){border-color:var(--accent);background:var(--accent-soft)}
.choice:has(input:focus-visible){outline:3px solid var(--accent);outline-offset:2px}
.choice input{width:18px;height:18px;margin:0;accent-color:var(--accent)}
.result-picker .choice input[type=radio]{flex:none;width:18px;height:18px;min-height:0;margin:0;padding:0;border:0;border-radius:50%;background:none;box-shadow:none;appearance:auto;-webkit-appearance:auto}
.result-picker .choice{display:inline-flex;align-items:center;gap:var(--space-2);margin:0;line-height:1.2}
.result-picker legend{padding:0}
/* Rows with a title and a detail line: the icons line up with the title, not the middle of both lines. */
.stack-row{align-items:start}
/* A link that is a row's title (the model links on /models) is a tap target on its own: at least 24px tall. */
.stack-row strong>a,.stack-row small>a{display:inline-block;min-height:24px;line-height:24px}
/* "optional" on the warm panel background needs the darker muted colour to reach 4.5:1 in the light theme. */
.optional-section .optional{color:var(--muted)}
.stack-row>span[class^="tone-"],.stack-row>.icon{display:flex;align-items:center;align-self:start;height:calc(var(--fs-md) * 1.55)}
.stack-row>.icon{display:block}  /* The 18px drawing sits centred in a box one title line tall. */
.stack-row>.speed-figure.speed-failed{align-self:start;line-height:calc(var(--fs-md) * 1.55)}

/* For agents: the helper and the message to paste. */
.agent-panel h2{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3)}
.agent-panel .form-help{margin-top:var(--space-3)}
.agent-panel .code{margin-top:var(--space-2);white-space:pre-wrap;overflow-wrap:anywhere}
.agent-chooser{display:grid;gap:var(--space-3);margin-top:var(--space-3)}
.agent-chooser .form-field:not(fieldset){max-width:420px}

/* Task suite */
.suite-table th[scope=row]{white-space:normal;width:34%;min-width:12rem}
.suite-where,.board-where{display:block;color:var(--muted);font-size:var(--fs-xs);font-weight:400}
.suite-meta{margin-bottom:var(--space-6)}
.suite-task{--task-indent:calc(20px + var(--space-4))}  /* The title column, past the 20px outcome icon; the rows pull out by their padding. */
.task-row{grid-template-columns:auto minmax(0,1fr) auto auto;cursor:pointer;list-style:none}
.task-row::-webkit-details-marker,.run-category>summary::-webkit-details-marker{display:none}
.task-row strong{font-size:var(--fs-md)}
.task-row small{text-align:right;max-width:24rem;line-height:calc(var(--fs-md) * 1.55)}
.task-name{min-width:0}  /* The title, and the cut-off line and a failed task's reason under it, share the title's column: no side note narrows the title. */
.task-row .task-name>small{max-width:none;text-align:left}
.task-row>.row-chevron{align-self:center;grid-column:4}  /* The outcome icon keeps to the title's line; the chevron centres on the row, in its own column when a row has no reason. */
.task-row>.row-chevron,.run-category>summary>.icon{display:flex;color:var(--muted);transition:transform var(--motion-fast) var(--ease-out)}
.suite-task[open]>.task-row>.row-chevron,.run-category[open]>summary>.icon{transform:rotate(180deg)}
.task-row:hover strong,.run-category>summary:hover .run-category-name{color:var(--accent-text)}
.suite-detail{margin:0 var(--space-2) var(--space-4)}
.run-tasks{margin-bottom:var(--space-8)}
.run-category{border-top:1px solid var(--line)}
p+.run-category{margin-top:var(--space-4)}  /* A note above the list keeps its distance from the first rule. */
.run-category:last-of-type{border-bottom:1px solid var(--line)}
.run-category>summary{display:flex;align-items:center;gap:var(--space-3);min-height:48px;margin:0 calc(-1 * var(--space-2));padding:var(--space-2);cursor:pointer;list-style:none;font-size:var(--fs-lg);font-weight:650}
.run-category>summary .count{color:var(--muted);font-size:var(--fs-sm);font-weight:500}
.run-category>summary>.icon{margin-left:auto}
.run-category>.stack-list,.run-category>.plain-list{margin-bottom:var(--space-4)}
.run-failed .task-row,.run-tasks .task-row{margin:0 calc(-1 * var(--space-2))}
@media (max-width:640px){.task-row{grid-template-columns:auto minmax(0,1fr) auto}.task-row small{grid-column:2;text-align:left}.task-row>.row-chevron{grid-row:1;grid-column:3}}
.suite-rubric{margin:0 var(--space-2) var(--space-3) var(--task-indent);max-width:60ch;color:var(--muted);font-size:var(--fs-sm)}
.suite-rubric strong{margin-right:.35em;color:var(--ink);font-weight:600}
.suite-detail .suite-rubric{margin:var(--space-3) 0}
.suite-detail .code{white-space:pre-wrap;overflow-wrap:anywhere;max-height:420px;overflow:auto}
.page-frame{display:block;width:100%;height:420px;margin-top:var(--space-3);border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--page-canvas)}
.conversation{display:grid;gap:var(--space-3);margin:var(--space-3) 0 0;padding:0;list-style:none}
.conversation-role{display:block;color:var(--muted);font-size:var(--fs-xs);font-weight:650;text-transform:uppercase;letter-spacing:.04em}
.suite-results{margin-top:var(--space-6);container:suite-results/inline-size}
.suite-table abbr{text-decoration:none}
/* The category columns are short: the header names each by its abbreviation (the full name is its title), smaller and tighter. */
.suite-table .suite-cat{padding-inline:var(--space-1);font-size:var(--fs-xs)}
/* The twelve category columns need a pane of 1220px (measured: the table fits a 1220px pane with them, each category cell
   padded 4px a side), so a narrower pane leaves them out rather than scroll sideways; each run's page has its categories. */
@container suite-results (max-width:1219px){
  .suite-table .suite-cat{display:none}
}
/* A table wider than its pane: a rule marks the edge while more lies beyond it, and the hint under it says so (app.js). */
.table-scroll.is-clipped{border-right:1px solid var(--control-line)}
.table-hint{margin-top:var(--space-2)}
/* The pass rates (/suite/tasks): a label or a category may wrap onto a second line. The desktop cells are nowrap, and a
   nowrap cell cannot shrink, so a label wider than its column pushed the table past its pane from 701 to 720px. A share stays
   on one line. */
.task-table td,.task-table th{white-space:normal}
.task-table .share{white-space:nowrap}
/* The table stops at its content (docs/ui-copy-and-style.md): a full-width table at 1280px put the points and the share a
   long way from the titles. Its pane still holds it, and scrolls it if it ever runs wider. The title takes its own width:
   the suite tables' 34% would make the table wider than its content, and a minimum width would hold a short table (a site
   with few runs has no labels) at 720px. */
.task-table{width:auto}
.task-table th[scope=row]{width:auto}
/* Phones: each run (and each leaderboard entry) is a card, its facts labelled and running on, its categories one compact
   line at the foot. The desktop columns are hidden; the table's header is still there for screen readers, as a visually hidden row. */
@media (max-width:700px){
  .suite-table,.board-table,.suite-table tbody,.board-table tbody{display:block}
  .suite-table thead,.board-table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .suite-table tbody tr,.board-table tbody tr{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--space-4);padding:var(--space-2) 0;border-bottom:1px solid var(--line)}
  .suite-table .suite-where,.board-table .board-where{line-height:1.4}
  .suite-table th,.suite-table td,.board-table th,.board-table td{display:block;width:auto;min-width:0;padding:0;border:0;text-align:left;white-space:normal}
  .suite-table tbody th[scope=row],.board-table tbody th[scope=row]{flex:0 0 100%}
  .suite-table tbody th[scope=row]{min-width:0}  /* The desktop row header's 12rem minimum grows with the text size: at 200% it would run past a phone's card. */
  .board-table .board-model{flex:0 0 100%}
  .suite-table td[data-label]::before,.board-table td[data-label]::before{margin-right:var(--space-1);color:var(--muted);font-size:var(--fs-xs);content:attr(data-label)}
  .board-table td[data-label="#"]::before{margin-right:0}  /* The rank reads #1, not # 1. */
  .suite-table .num,.board-table .num{text-align:left}
  .suite-table .nowrap{white-space:nowrap}
  .suite-table .suite-cat{display:none}
}
/* The hardware leaderboard as a table: its figures keep their columns and stay on one line; only the names wrap. */
.board-table tbody td,.board-table tbody th[scope=row]{white-space:normal;overflow-wrap:anywhere}
.board-table td[data-label="By"]{overflow-wrap:normal}  /* A username is one word: it wraps whole, never inside its letters, so the column keeps its width. */
.board-table .num{white-space:nowrap}
.board-table tr.is-mine>*{background:var(--accent-soft)}  /* Your own row: where you are, in the accent's tint. */
/* Arrival: a visitor who came to their own row (#mine) sees it slide up into place and its tint fade in, once. */
@keyframes board-arrive{from{transform:translateY(var(--space-3))}}
@keyframes board-tint{from{background-color:transparent}}
.board-table tr.is-mine:target{animation:board-arrive var(--motion) var(--ease-out),board-tint var(--motion) var(--ease-out)}
.board-table tr.is-mine:target>*{animation:board-tint var(--motion) var(--ease-out)}
@media (max-width:700px){
  /* The band reaches the pane's own padding and no further: a band wider than its pane is sideways overflow, which marks the pane as scrollable. */
  .board-table tbody tr.is-mine{margin-inline:calc(-1 * var(--space-1));padding-inline:var(--space-1);background:var(--accent-soft)}
  .board-table tbody tr.is-mine>*{background:none}  /* A card fills as one, not cell by cell. */
}
.runner-setup ul,.runner-setup ol{margin:var(--space-2) 0 0;padding-left:var(--space-5)}
.runner-setup li{margin-top:var(--space-1)}
.setup-os{margin-top:var(--space-3)}
.setup-os summary{color:var(--ink)}
.setup-os[open]>summary{margin-bottom:var(--space-1)}
.code-lines{white-space:pre-wrap}
.runner-setup .copy-row{margin:var(--space-1) 0}
.form-help.tone-good{color:var(--good-text)}
.form-help.tone-bad{color:var(--bad-text)}
.runner-model-row{display:flex;gap:var(--space-3);align-items:center}
.runner-model-row input{flex:1;min-width:0}
.runner-model-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(16rem,100%),1fr));gap:var(--space-2);max-height:15rem;overflow:auto;margin:var(--space-3) 0 0;padding:2px;border:0;min-width:0}
.runner-model-list .choice{display:flex;min-height:40px;padding:var(--space-1) var(--space-3);border-radius:var(--radius-pill);font-size:var(--fs-sm);font-weight:500;overflow-wrap:anywhere}
.runner-model-list .choice input[type=radio]{flex:none;width:18px;height:18px;min-height:0;margin:0;padding:0;border:0;border-radius:50%;background:none;box-shadow:none;appearance:auto;-webkit-appearance:auto}
#runner-done .hero-actions .button{display:inline-flex;align-items:center;white-space:normal;min-width:0}  /* A long label (Beat ...) wraps inside a 320px dialog rather than run past it. */
.runner-setup code{overflow-wrap:break-word}  /* A break only where the text allows one (a space, or a wbr in the template): a flag or a setting name stays whole. */
.copy-row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3);margin-top:var(--space-2);font-size:var(--fs-sm)}
#runner [hidden]{display:none!important}
.hero-actions{display:flex;flex-wrap:wrap;gap:var(--space-3);margin-top:var(--space-6)}
.hero-actions+p{margin-top:var(--space-3)}
.agents-main .muted.small+.muted.small{margin-top:var(--space-3)}
.hero-actions .accent-link{display:inline-flex;align-items:center;min-height:24px;align-self:center}  /* A link beside the hero: 24px, centred on it. */
.top-runs-title{margin-top:var(--space-6)}
.top-runs{margin-top:var(--space-3)}
.top-score{min-width:3.6em;font-variant-numeric:tabular-nums;line-height:calc(var(--fs-md) * 1.55);white-space:nowrap}
.top-score strong,.top-score small{display:inline;line-height:inherit}
.top-score.is-empty{min-width:0}  /* A row with no score yet: the dash takes no more room than itself. */
.top-score strong{font-size:var(--fs-lg)}
.top-score small{color:var(--muted)}
.bench-leagues{display:flex;flex-wrap:wrap;gap:var(--space-2);margin:var(--space-3) 0 var(--space-4)}
.bench-leagues .choice{text-decoration:none}
.bench-leagues .is-current,.choice.is-current{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-text);font-weight:650}
.top-runs .stack-row{grid-template-columns:4.75rem minmax(0,1fr) auto}
.board-meta{overflow-wrap:anywhere}
.board-meta .num{white-space:nowrap}
.top-runs-more{margin-top:var(--space-4)}
.model-link-form{margin:var(--space-6) 0}
.model-link-form textarea{width:100%}
.model-link-row{display:flex;gap:var(--space-3);align-items:center;margin-top:var(--space-2)}
.model-link-row input{flex:1;min-width:0;height:var(--control);padding:0 var(--space-4);border:1px solid var(--control-line);border-radius:var(--radius-control);background:var(--surface);color:var(--ink);font-size:var(--fs-md)}
.model-link-row input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.form-shell>.run-choices{max-width:none;display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);gap:var(--space-6);align-items:start}
.run-choices>.run-choice{margin:0}
.run-agent .code{margin-top:var(--space-3)}
#runner-manual{margin:var(--space-4) 0 0}
#runner-manual .result-picker{margin:var(--space-3) 0}
@media (max-width:900px){.form-shell>.run-choices{grid-template-columns:1fr}}
.home-setup{margin-top:var(--space-7)}
.home-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:0}
.home-grid>*+*,.page-grid>*+*{margin-top:var(--space-7)}
.home-top .top-runs-title:first-child,.home-latest .top-runs-title:first-child{margin-top:0}
/* From 1400px the home page is a dashboard: the top machines beside the hero, the latest runs beside the picker,
   and both lists in two columns, so no column runs on alone. */
@media (min-width:1100px){
  .home-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-areas:"hero top" "built built" "main latest";column-gap:var(--space-9);row-gap:var(--space-7);align-items:start}
  .home-grid>*+*{margin-top:0}
  /* From 1400px the hero fills its row, so no corner is left blank beside the top machines: its "New here?" note sits on the foot of the row. */
  .home-grid>.home-hero{grid-area:hero;padding-top:var(--space-6);display:flex;flex-direction:column;align-self:stretch}
  .home-grid>.home-hero>.hero-actions{margin-bottom:var(--space-3)}
  .home-grid>.home-hero>.muted.small{margin-top:auto}
  .home-grid>.home-built{grid-area:built;margin-top:0} /* The row gap spaces it; not the section-after-section margin too. */
  .home-main{grid-area:main;min-width:0}
  .home-top{grid-area:top;min-width:0}
  .home-latest{grid-area:latest;min-width:0}
  .home-grid>.home-top{padding-top:var(--space-6);align-self:stretch} /* The list's box runs to the row's foot like the hero's, so the two columns end together. */
}
/* From 1100px to 1399px the sections run down one column in reading order (order sets it), and the two lists run in two
   columns. Beside the hero, the top machines ran on far below it, and the picker's height swings with its fields, so no
   pairing of two sections kept both columns full in every state; the blank was the space under the shorter one. The
   column is a flex stack with a gap, not named grid rows, so an absent section leaves no gap; an empty top-machines
   section is hidden for the same reason. An odd last item spans both columns, so no empty cell is left beside it. */
@media (min-width:1100px) and (max-width:1399px){
  .home-grid{display:flex;flex-direction:column;gap:var(--space-7);align-items:stretch}
  .home-grid>.home-built{order:1} /* The pages the runs built stay on the first screen, as on a phone. */
  .home-grid>.home-top{order:2;padding-top:0} /* Nothing beside it for the title to line up with. */
  .home-grid>.home-top:not(:has(> *)){display:none}
  .home-grid>.home-main{order:3}
  .home-grid>.home-latest{order:4}
  .home-top .stack-list.cols,.home-latest .stack-list.cols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:var(--space-7)}
  .home-top .stack-list.cols:not(:has(> li:nth-child(4))),.home-latest .stack-list.cols:not(:has(> li:nth-child(4))){display:block}
  .home-top .stack-list.cols>li:last-child:nth-child(odd),.home-latest .stack-list.cols>li:last-child:nth-child(odd){grid-column:1/-1}
}
.home-main>section:first-child{margin-top:0}
@media (min-width:1400px){
  .home-grid{grid-template-columns:minmax(0,1.1fr) minmax(0,1fr) minmax(0,1fr);grid-template-areas:"hero top top" "built built built" "main latest latest"}
}
/* What models built, on the home page: a few passing pages a day, one per page task, in turn (play.showcase). The frame is the
   picture: no box around a card. Four in a row from 1100px, two to a row from 700px, and on a phone one row that
   scrolls sideways and snaps, bleeding to the window's edges like a row of chips, so the page stays short. */
.home-built{min-width:0}
.built-head{display:grid;grid-template-columns:minmax(0,1fr);grid-template-areas:"title" "lede" "more"}
.built-head>.section-title{grid-area:title;margin-bottom:0}
.built-head>.lede{grid-area:lede;margin-top:var(--space-3)}
.built-more{grid-area:more;margin:var(--space-2) 0 0;font-size:var(--fs-sm)}
.built-more a{display:inline-block;min-height:24px;line-height:24px}
@media (min-width:700px){
  .built-head{grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"title more" "lede lede";column-gap:var(--space-4);align-items:baseline}
  .built-more{margin:0;justify-self:end}
}
.showcase{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-4);margin:var(--space-4) 0 0;padding:0;list-style:none}
.showcase-card{min-width:0}
/* A built page as a thumbnail: the whole page, laid out 480px wide and scaled to the card, so a game board or a
   menu shows entire rather than its top-left corner. The scale is the card's width over 480px, from container
   units; a browser without them shows the page at full size, cropped. The page stays live: a game plays scaled. */
.page-thumb{position:relative;overflow:hidden;aspect-ratio:4/3;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--page-canvas);container-type:inline-size}
.page-thumb iframe{display:block;width:480px;height:360px;border:0;transform-origin:0 0;transform:scale(tan(atan2(100cqw,480px)))}
.page-thumb:has(iframe.is-focused){outline:3px solid var(--accent);outline-offset:3px}
/* A built page that stopped responding (app.js): its frame becomes this notice, in the same box, thumbnail or full size. */
.page-stopped{display:grid;align-content:center;justify-items:center;gap:var(--space-3);box-sizing:border-box;padding:var(--space-4);text-align:center;color:var(--ink-2);font-size:var(--fs-sm);background:var(--page-canvas)}
.page-stopped p{margin:0;max-width:30ch}
.page-stopped .stopped-actions{display:flex;flex-wrap:wrap;gap:var(--space-2);justify-content:center}
.page-thumb>.page-stopped{position:absolute;inset:0;padding:var(--space-3)}
/* A built page whose frame is being made again (app.js restart): an empty place of the frame's own size, until the page is back. */
.page-restarting{display:block;box-sizing:border-box;background:var(--page-canvas)}
.page-thumb>.page-restarting{position:absolute;inset:0}
iframe.is-focused:not(.page-thumb iframe){outline:3px solid var(--accent);outline-offset:3px} /* The focus is inside the frame: app.js marks it, as no :focus selector matches. */
/* A thumbnail's frame lets the pointer through to its card, so the card answers a hover (a sandboxed frame would hide the
   pointer from the page). A click gives the page the focus (app.js), and then the page's own controls take the pointer. */
.showcase-card .page-thumb iframe,.gallery-card .page-thumb iframe{pointer-events:none}
.showcase-card .page-thumb iframe.is-focused,.gallery-card .page-thumb iframe.is-focused{pointer-events:auto}
/* A built page's card answers the pointer and the focus: it lifts a little, and its frame takes the stronger line. Hover
   counts only where there is a pointer, so a tap on a phone leaves nothing lifted. A focus on the page's vote does not
   lift it: a press changes the count and nothing else (votes.py). */
.showcase-card,.gallery-card,.page-thumb{transition:transform var(--motion-fast) var(--ease-out),border-color var(--motion-fast) var(--ease-out)}
.showcase-card:is(:focus-within,:has(iframe.is-focused)):not(:has(.page-vote-slot:focus-within)),.gallery-card:is(:focus-within,:has(iframe.is-focused)):not(:has(.page-vote-slot:focus-within)){transform:translateY(-2px)}
.showcase-card:is(:focus-within,:has(iframe.is-focused)) .page-thumb,.gallery-card:is(:focus-within,:has(iframe.is-focused)) .page-thumb{border-color:var(--line-strong)}
@media (hover:hover){
  .showcase-card:hover,.gallery-card:hover{transform:translateY(-2px)}
  .showcase-card:hover .page-thumb,.gallery-card:hover .page-thumb{border-color:var(--line-strong)}
  .brand:hover .brand-mark{transform:rotate(-8deg)}  /* The mascot turns its head to the pointer. */
  .button.hero:hover>svg{transform:translateX(3px)}
  .choice:not(.is-current):not(:has(input:checked)):hover{border-color:var(--line-strong)}
}
@media (min-width:1100px){.showcase{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media (max-width:699px){
  .showcase{display:flex;position:relative;gap:var(--space-3);overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;margin-inline:calc(-1 * clamp(var(--space-4),5vw,var(--space-11)));padding:var(--space-1) clamp(var(--space-4),5vw,var(--space-11));scroll-padding-inline:clamp(var(--space-4),5vw,var(--space-11))}
  .showcase::-webkit-scrollbar{display:none}
  .showcase-card{flex:none;width:max(260px,78vw);scroll-snap-align:start}
}
/* The titles of both galleries (the home page's and the run page's): a title may wrap to a second line, and never to a
   third (the clamp). A one-line title takes one line, so nothing is reserved under it: a wrapped title pushes its own
   second line down, and the frames and the first lines of the titles stay level. */
.showcase .gallery-caption>span:last-child{min-width:0}
.showcase .gallery-caption strong{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.showcase .gallery-caption strong a{display:inline;line-height:inherit}
.setup-intro{margin:var(--space-2) 0 var(--space-5);color:var(--muted)}
.run-summary{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-4) var(--space-8);margin:0 0 var(--space-4)}
/* A fact is its label at the left and its figure at the right, so a row's text runs across the row. Two facts share a row;
   an odd fact out takes the whole row, so no row stands with an empty column beside its text (the writing speed came
   fifth, alone, with three columns empty beside it at 1280). */
.run-summary>div{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-3)}
.run-summary>div:last-child:nth-child(odd){grid-column:1/-1}
.run-summary dd{text-align:right;min-width:0}
@media (max-width:559px){.run-summary{grid-template-columns:minmax(0,1fr)}}
.run-summary dt{color:var(--muted);font-size:var(--fs-sm)}
.run-summary dd{margin:0;color:var(--muted);font-variant-numeric:tabular-nums}
.run-summary dd strong{color:var(--ink);font-size:var(--fs-2xl);font-weight:650}
.run-summary dd small{display:block;font-size:var(--fs-sm)}
/* The caveat under a fact stops at 18ch, so the facts share rows at 1280 (a placement note keeps its width), and its
   lines are balanced so the last one is never a lone word. */
.run-summary .run-caveat{max-width:18ch;text-wrap:balance}
/* The notes under the facts (tok/s, then the context) are separate lines, not one paragraph. */
.run-summary+p.muted.small+p.muted.small{margin-top:var(--space-3)}
/* A column is never wider than the list (12rem at 200% text is wider than a phone), and a long label wraps so its count stays on screen. */
.run-categories{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(12rem,100%),1fr));column-gap:var(--space-6);margin:var(--space-5) 0 var(--space-8);padding:0;list-style:none;font-size:var(--fs-sm)}
.run-categories a{display:flex;justify-content:space-between;gap:var(--space-3);padding:var(--space-1) 0}
.run-categories .run-category-name{text-decoration:underline}
.run-categories .num{color:var(--muted);font-variant-numeric:tabular-nums}
.run-details{margin:var(--space-6) 0 var(--space-4)}
.suite-task .suite-detail{margin-left:var(--task-indent)}
/* Your setup, checked: the verdict, then what differs from the fastest run, one line each behind its status icon */
.run-check{margin:var(--space-5) 0 var(--space-6);overflow-wrap:anywhere}
.run-check h2{margin:0 0 var(--space-2);font-size:var(--fs-lg);font-weight:650}
.run-check-verdict{margin:0 0 var(--space-3);font-weight:600;line-height:1.5}
.run-check .check-row{grid-template-columns:auto minmax(0,1fr)}
.run-check>p.muted{margin:var(--space-3) 0 0}
.run-note{margin:0 0 var(--space-5);padding:var(--space-4) var(--space-5);border-left:3px solid var(--line-strong);color:var(--ink-2);line-height:1.5;overflow-wrap:anywhere}
.run-note strong{display:block;margin-bottom:var(--space-1);color:var(--ink);font-size:var(--fs-sm)}
.compare-form{display:grid;grid-template-columns:1fr 1fr auto;gap:var(--space-4);align-items:end;margin-bottom:var(--space-7)}
.compare-form .form-actions{margin-top:0}
.compare-form.pick-run{grid-template-columns:minmax(0,1fr) auto} /* One run to add beside its button; the note under both. */
.compare-form.pick-run>.form-help{grid-column:1/-1;margin-top:0}
@media (max-width:700px){.compare-form,.compare-form.pick-run{grid-template-columns:1fr}}
.compare-table{width:100%;border-collapse:collapse;font-size:var(--fs-md)}
.compare-table th,.compare-table td{padding:var(--space-3) var(--space-3);border-bottom:1px solid var(--line);text-align:left;vertical-align:top}
.compare-table th:first-child,.compare-table td:first-child{padding-left:0}
.compare-table .num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.compare-table td small{display:block;color:var(--muted);font-size:var(--fs-xs)}
.compare-table td.is-best .icon{margin-right:var(--space-1)} /* The check leads the best figure, in the cell's own ink, so the figures keep one right edge. */
.compare-table a{display:inline-block;min-height:24px;line-height:24px}
.compare-table tr.compare-task>th[scope=row]{padding-left:var(--space-5);color:var(--ink-2);font-weight:400}  /* A task sits under its category's row. */
.challenge-decision{display:inline-flex;gap:var(--space-2);align-items:center;margin:0 var(--space-2) var(--space-2) 0;vertical-align:middle}
.challenge-decision input{min-width:14rem}
.challenge-decision input,.challenge-decision select{min-height:var(--control-sm);padding:0 var(--space-3);border:1px solid var(--control-line);border-radius:10px;background:var(--surface);color:var(--ink);font-size:var(--fs-sm);appearance:none;-webkit-appearance:none}
.challenge-decision .select-wrap>.icon{right:10px}
.challenge-decision .select-wrap select{padding-right:var(--space-8)}
@media (max-width:900px){
  .admin-table td:has(.challenge-decision){white-space:normal}
  .challenge-decision{display:flex;flex-wrap:wrap;width:100%;margin-right:0}
  .challenge-decision input{min-width:0;flex:1 1 0;width:100%}
}
.milestones{margin:var(--space-3) 0 0;padding:0;list-style:none;display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:0 var(--space-4)}
.milestones li{padding:var(--space-3) 0;border-top:1px solid var(--line)}  /* Facts ruled apart, not boxed: containers earn their borders. */
.milestones strong{display:block;font-weight:650}
.milestones small{display:block;margin-top:2px;color:var(--muted);font-size:var(--fs-sm)}
.badge-preview{display:block;max-width:100%;height:auto;margin:var(--space-3) 0}
.home-news{margin-top:var(--space-7)}
.model-aside{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--space-7) var(--space-9);margin-top:var(--space-7)}
.model-aside .plain-list{padding-left:0;list-style:none}
.model-aside .plain-list li{margin:var(--space-2) 0}
.model-aside .plain-list a,.panel .plain-list a{display:inline-block;min-height:24px;line-height:24px}
.machine-main .plain-list{padding-left:0;list-style:none}
.machine-main .plain-list li{margin:var(--space-2) 0}
.machine-main .plain-list a{display:inline-block;min-height:24px;line-height:24px}
/* The machine page's two columns, each one flow: its models, latest runs and owners on the left, the leaderboard and the links on the right. */
.machine-main,.machine-side{display:flex;flex-direction:column;gap:var(--space-7)}
.machine-side>.model-aside{margin-top:0}
.wrap:not(.home-grid)>section+section,main>section+section,.home-main>section+section,.home-side>section+section{margin-top:var(--space-7)}
.bench-mine{margin:var(--space-2) 0 var(--space-3);color:var(--muted)}
.bench-mine strong{color:var(--ink);font-size:var(--fs-xl);font-variant-numeric:tabular-nums}
.machine-change{padding-left:0}
.page-head + .home-setup{margin-top:0}  /* On /models the picker follows the title directly. */
.run-share{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);margin:var(--space-4) 0}
.run-share .button[hidden]{display:none}
.run-failed{border-bottom:0;padding-bottom:0}
.board-note{margin-top:var(--space-3)}
.board-pages{display:flex;flex-wrap:wrap;gap:var(--space-4);align-items:center;margin:var(--space-4) 0}
.is-mine>.link-row{background:var(--surface)}
.runner-ranking{margin:var(--space-3) 0;color:var(--ink);font-weight:600}
.runner-place{font-variant-numeric:tabular-nums}
.score-strip{margin:var(--space-3) 0 var(--space-4)}
.score-strip svg{display:block;max-width:640px;overflow:visible}
.strip-axis{stroke:var(--line);stroke-width:1}
.strip-dot{fill:var(--muted);stroke:var(--bg);stroke-width:2}
.strip-you{fill:var(--accent);stroke:var(--bg);stroke-width:2}
.strip-label{fill:var(--ink);font-size:var(--fs-xs);font-weight:600}
.strip-tick{fill:var(--muted);font-size:var(--fs-xs);font-variant-numeric:tabular-nums}
/* Comments under model, machine, run and challenge pages */
.comments{margin-top:var(--space-7);padding-top:var(--space-5);border-top:1px solid var(--line)}
.challenge-grid>.standings{margin-top:var(--space-7);padding-top:var(--space-5);border-top:1px solid var(--line)}  /* Under 1100px the standings and the comments share one divider. */
.comment-list{margin:0 0 var(--space-6);padding:0;list-style:none}
.comment{padding:var(--space-4) 0;border-bottom:1px solid var(--line)}
.comment-head{margin:0 0 var(--space-2);font-size:var(--fs-sm)}
.comment-body{margin:0;white-space:pre-line;overflow-wrap:anywhere;line-height:1.55}
.comment-actions{display:flex;flex-wrap:wrap;gap:var(--space-3);align-items:center;margin:var(--space-3) 0 0;font-size:var(--fs-sm)}
.comment-flag summary{cursor:pointer;color:var(--muted);font-weight:600;min-height:24px;line-height:24px}
.comment-flag .compact-form{max-width:420px}
.comment-actions>.comment-flag[open]{flex-basis:100%}
.comment-form{margin-top:var(--space-4)}
.comment-form textarea{width:100%}
.admin-table .comment-cell{max-width:28rem;white-space:pre-line;overflow-wrap:anywhere}
.more-link{margin:var(--space-3) 0 var(--space-5)}
.more-link a,.board-pages a{display:inline-block;min-height:24px;line-height:24px}
.model-row .model-links{margin-top:var(--space-1)}
.model-row .model-links a{display:inline-block;min-height:24px;line-height:24px}
/* On a phone the comparison reads as cards: the model across the top, the two machines side by side under it. */
@media (max-width:640px){
  .compare-table thead tr,.compare-table tbody tr{display:grid;grid-template-columns:1fr 1fr;column-gap:var(--space-4)}
  .compare-table thead th:first-child{display:none}
  .compare-table tbody th[scope=row]{grid-column:1/-1;padding-bottom:0;border-bottom:0}
  .compare-table th,.compare-table td{padding-left:0}
  .compare-table .num{text-align:left;white-space:normal}
  /* Runs compared side by side keep their columns (two to six) and scroll inside .table-scroll instead. */
  .compare-table.compare-runs thead tr,.compare-table.compare-runs tbody tr{display:table-row}
  .compare-table.compare-runs thead th:first-child{display:table-cell}
  .compare-table.compare-runs thead a{white-space:nowrap}  /* A run's name is one line; the table scrolls to fit it. */
  .compare-table.compare-runs tbody th[scope=row]{padding-bottom:var(--space-3);border-bottom:1px solid var(--line)}
  .compare-table.compare-runs tbody tr.compare-category>*{padding-bottom:var(--space-2)}  /* A category's row sits closer to its tasks on a phone: the page keeps its six-screen budget with twelve categories. */
  .compare-table.compare-runs .num{text-align:right;white-space:normal}
  .compare-table.compare-runs tbody:first-of-type td.num{white-space:nowrap} /* "38 of 44" and "120 tok/s" stay one phrase; the pane scrolls sideways anyway. */
  .compare-table.compare-runs{font-size:var(--fs-sm)}
  .compare-table.compare-runs tr.compare-task>th[scope=row]{padding-left:0}  /* The narrow column keeps its width for the title; the category above is bold. */
  .compare-table.compare-runs th[scope=row],.compare-table.compare-runs thead th:first-child{position:sticky;left:0;background:var(--bg);padding-right:var(--space-3)}
  /* Forty-four task rows, under their categories: closer together than the summary rows above them. */
  .compare-table.compare-runs tbody tr.compare-task>*{padding-top:var(--space-2);padding-bottom:var(--space-2)}
  .compare-runs tbody+tbody tr.compare-category>*{padding-top:var(--space-3)}  /* The bold category heads its tasks; no extra gap. */
}
/* Runs compared: the model heads its column with the computer and runtime under it; each task's cell is its grade
   over its speed; a run's lost categories are said under the table. */
.compare-runs th small{display:block;color:var(--muted);font-size:var(--fs-xs);font-weight:400}
.compare-runs .take-out{font-size:var(--fs-sm);font-weight:400}  /* A column's action under its name: regular, not the bold head. */
.compare-runs tbody+tbody tr:first-child th,.compare-runs tbody+tbody tr:first-child td{padding-top:var(--space-5)}
.compare-runs .outcome{display:inline-flex;align-items:center;min-height:24px}
.compare-loss{margin:var(--space-4) 0 0;color:var(--ink-2)}
.hero-actions>.small{align-self:center}
/* The reveal */
.reveal-tier{font-size:var(--fs-lg);font-weight:650;color:var(--accent-text)}
.reveal-tier:empty::before{content:'\00a0'}
.reveal-sub{display:block;margin-top:var(--space-1);color:var(--muted);font-size:var(--fs-sm);font-weight:400}
.reveal-line{margin:var(--space-2) 0;color:var(--ink-2)}
#runner-done .hero-actions{margin-top:var(--space-4);margin-bottom:var(--space-4)}
#runner-done .hero-actions a{margin-top:0}
.race-table{width:100%;margin:var(--space-3) 0 var(--space-4);border-collapse:collapse;font-size:var(--fs-sm)}
.race-table th,.race-table td{padding:var(--space-2) var(--space-3);border-bottom:1px solid var(--line);text-align:left;vertical-align:top}
.race-table th:first-child,.race-table td:first-child{padding-left:0}
.race-table .num{text-align:right;font-variant-numeric:tabular-nums}
.race-table td.is-best{font-weight:650}
.race-table td.is-best .icon{margin-right:var(--space-1)}
.runner-guess{margin-bottom:var(--space-2)}
.runner-guess input{max-width:12rem}
/* The size picker is a fieldset of radio cards, not form fields: the field rules (48px inputs, a block label) would break the card. */
.size-picker{min-width:0;margin:0;padding:0;border:0}
.size-picker legend{margin-bottom:var(--space-2);padding:0;color:var(--ink-2);font-size:var(--fs-md);font-weight:500}
.size-options{display:grid;gap:var(--space-2)}
.size-option{display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:var(--space-3);row-gap:var(--space-1);align-items:start;padding:var(--space-3) var(--space-4);border:1.5px solid var(--control-line);border-radius:var(--radius-control);background:var(--surface);color:var(--ink);cursor:pointer;transition:border-color var(--motion-fast) var(--ease-out),background-color var(--motion-fast) var(--ease-out)}
.size-option:hover{border-color:var(--ink-2)}
.size-option:has(input:checked){border-color:var(--accent);background:var(--accent-soft)}
.size-option:has(input:focus-visible){outline:3px solid var(--accent);outline-offset:2px}
.size-option input{width:18px;height:18px;margin:0;accent-color:var(--accent)}
.size-head{grid-column:2;display:flex;flex-wrap:wrap;align-items:baseline;gap:0 var(--space-3)}
.size-name{font-weight:600}
.size-count{color:var(--ink-2);font-size:var(--fs-sm)}
.size-line{grid-column:2;color:var(--ink-2);font-size:var(--fs-sm)}
/* The gallery of built pages */
.gallery-tasks{margin-bottom:var(--space-6)}
.gallery-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(300px,100%),1fr));gap:var(--space-6);margin:var(--space-5) 0 0;padding:0;list-style:none}
.gallery-caption{display:flex;align-items:start;gap:var(--space-2);margin:var(--space-3) 0 0}
.gallery-caption>span[class^="tone-"]{display:flex;align-items:center;height:calc(var(--fs-md) * 1.55)}
.gallery-caption strong{display:block;font-size:var(--fs-md)}
.gallery-caption strong a{display:inline-block;min-height:24px;line-height:24px}
.gallery-caption small{display:block;color:var(--muted);font-size:var(--fs-sm)}
.gallery-card{display:flex;flex-direction:column}
.gallery-links{margin:auto 0 0;padding-top:var(--space-1);font-size:var(--fs-sm)}
.gallery-links a{display:inline-block;min-height:24px;line-height:24px}
/* The order of the gallery's pages: two plain links, the current one in the accent colour. */
.gallery-order{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-5);margin-top:var(--space-5);font-size:var(--fs-sm)}
.gallery-order a{display:inline-block;min-height:24px;line-height:24px}
.gallery-order a[aria-current=page]{color:var(--accent-text);font-weight:650}
.gallery-order+.gallery-grid{margin-top:var(--space-4)}
/* A built page's votes and comments (votes.py) sit over the bottom-right corner of its preview, inside the frame, so no card
   changes size and no caption changes: a press changes the count and the pressed state, and nothing else moves. One bar, an
   icon and a count for each, as a gallery marks a thumbnail. Its colours do not follow the theme: a dark fill with a light
   outline keeps 3:1 against a light preview (by the fill) and a dark one (by the outline), whatever the page built. It is
   40px tall, as a bordered control is (the control audit and the 36px touch check), and it sits above the frame, which
   takes the pointer only while its page has the focus. A pressed vote fills with the accent. */
:root{--vote-fill:#1c1920;--vote-line:#9a95a0;--vote-ink:#fff;--vote-hover:#36323b;--vote-accent:#b82559}
.page-vote-slot{position:absolute;right:var(--space-2);bottom:var(--space-2);z-index:1;display:flex;align-items:stretch;box-sizing:border-box;min-height:var(--control-sm);max-width:calc(100% - 2 * var(--space-2));border:1px solid var(--vote-line);border-radius:var(--radius-pill);background:var(--vote-fill);color:var(--vote-ink)}
.page-vote-form{display:flex;margin:0}
.page-vote,.page-vote-own,.page-comments{display:inline-flex;align-items:center;gap:var(--space-1);box-sizing:border-box;margin:0;padding:0 var(--space-3);border:0;border-radius:var(--radius-pill);background:transparent;color:inherit;font-family:inherit;font-size:var(--fs-sm);font-weight:650;line-height:1;white-space:nowrap;text-decoration:none;font-variant-numeric:tabular-nums;transition:background-color var(--motion-fast) var(--ease-out),color var(--motion-fast) var(--ease-out)}
.page-vote>span,.page-vote-own>span,.page-comments>span{display:inline-block;min-width:2ch;text-align:center}  /* Two figures wide: the busy mark takes the count's place, and nothing moves. */
.page-vote{cursor:pointer}
@media (hover:hover){.page-vote:hover,.page-comments:hover{background:var(--vote-hover)}}
.page-vote[aria-pressed=true]{background:var(--vote-accent);color:#fff}
.runner-quick a.accent-link{display:inline-block;min-height:24px;line-height:24px}
.top-score .top-tier{display:block;font-size:var(--fs-xs);color:var(--muted);line-height:1.3}

/* The runner, compact: sections closer together, the hardware cards one row high, long excerpts clamped */
.run-choice .form-section-title{margin:var(--space-5) 0 var(--space-3)!important;padding-top:var(--space-4)}
.run-choice .kind-card{min-height:72px;padding:var(--space-3) var(--space-4);gap:var(--space-4)}
.run-choice .kind-card .kind-icon svg{width:32px;height:32px}
.run-choice .kind-text small{display:none}
.run-choice .kind-picker{grid-template-rows:repeat(2,auto)}
.run-choice .kind-card{grid-row:span 2}
.run-choice .form-help{margin-top:var(--space-1)}
.runner-model-row .visually-hidden+input{margin-top:0}

.step{padding:var(--space-4) 0;border-top:1px solid var(--line)}
.step-head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);min-height:32px}
.step-head h2{margin:0;font-size:var(--fs-lg);font-weight:650}
.step-no{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;background:var(--surface-3);color:var(--ink);font-size:var(--fs-sm);font-weight:700}
.step.is-done .step-no{background:var(--surface);border:1.5px solid var(--good);color:var(--good-text)}
.step-summary{flex:1 1 12rem;min-width:0;color:var(--muted);overflow-wrap:anywhere}
.step-summary:empty{display:none}
.step-change{min-height:var(--control-sm);padding:0 var(--space-4);border:1px solid var(--control-line);border-radius:10px;background:var(--surface);color:var(--ink-2);font:inherit;font-size:var(--fs-sm);font-weight:600;cursor:pointer}
.step-body{margin-top:var(--space-3)}
.step-body>.form-help:first-child{margin-top:0}
.runner-model-list{margin-top:var(--space-3)}
/* The runner's hardware cards: three across at every width, as on phones, so step 3 stays short */
.runner .kind-picker{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-2)}
.runner .kind-card{flex-direction:column;justify-content:center;gap:var(--space-2);min-height:88px;padding:var(--space-3) var(--space-2);text-align:center}
.runner .kind-card .kind-icon .icon{width:28px;height:28px}

.runner-model-row .runner-model-list{flex:1;min-width:0}
/* Under 360px the field takes the row's width and the button sits full width under it, so the placeholder reads whole. */
@media (max-width:359px){.runner-model-row{flex-direction:column;align-items:stretch;gap:var(--space-2)}.runner-model-row input,.runner-model-row .runner-model-list{flex:none}}

/* The runner as an application: the page is one screen tall and the document never scrolls. The setup steps scroll
   inside their pane; the board, the open tile's sheet and the reveal are sized to the window. */
/* A page is a document: the window scrolls it, so the browser's own keys, find, and Back to the same place all work.
   In a window 600px tall or more the header stays at the top and a short page keeps the footer at the bottom. An app
   page (the runner, the chat) is the window instead: one window tall, its panes scroll. A shorter window (a phone on
   its side, 200% zoom) and paper get the ordinary page. */
@media (min-height:600px){
  .js body{min-height:100vh;min-height:100dvh;display:grid;grid-template-rows:auto 1fr auto;grid-template-columns:minmax(0,1fr)}
  .js main{min-height:0;position:relative}
  .site-header{position:sticky;top:0;z-index:5}
  html{scroll-padding-top:calc(var(--header) + var(--space-4))}
  .js body.app-page{height:100vh;height:100dvh;overflow:hidden;grid-template-rows:auto minmax(0,1fr) auto}
  .js .app-page main{overflow:hidden;display:grid;grid-template-rows:minmax(0,1fr);padding-bottom:0}
}
/* The runner is an application from 480px tall, so a phone on its side keeps Run, Stop and the result in the window:
   the steps and the board scroll inside their panes, and the bar stays put. */
@media (min-height:480px){
  .js body.runner-page{height:100vh;height:100dvh;overflow:hidden;display:grid;grid-template-rows:auto minmax(0,1fr) auto}
  .js body.runner-page main{min-height:0;overflow:hidden;position:relative;display:grid;grid-template-rows:minmax(0,1fr);padding-bottom:0}
  .runner-shell{min-height:0;display:grid;grid-template-rows:auto minmax(0,1fr)}
  .runner-shell>.runner-app{min-height:0;grid-template-rows:auto minmax(0,1fr) auto}
  .runner-stage{min-height:0;display:grid;grid-template-rows:minmax(0,1fr)}
  .runner-pane{min-height:0;overflow:auto;overscroll-behavior:contain}
  .runner-run{min-height:0;overflow:auto;overscroll-behavior:contain}
}
/* Under 1200px the board takes what the head, the Resume strip and the bar leave: its squares scroll inside it, and the
   head and the last grade stay where they are. */
@media (min-height:480px) and (max-width:1199px){
  .runner-run{overflow:hidden;grid-template-rows:auto minmax(0,1fr) auto}
  .runner-tasks{min-height:0;overflow:auto;overscroll-behavior:contain;padding:var(--space-2);margin:0 calc(-1 * var(--space-2))}
}
@media (max-height:479px){.runner-top{position:sticky;top:0;z-index:2;background:var(--bg)}}
@media print{body{height:auto;overflow:visible;display:block}main{overflow:visible}.suite-detail .code,.table-scroll{max-height:none;overflow:visible}[data-reveal],[data-reveal=stagger]>*{animation:none!important;opacity:1!important}}
.runner-shell{padding-bottom:var(--space-3)}
.runner-head{display:grid;grid-template-columns:minmax(0,1fr);grid-template-areas:"crumb" "title" "sub";gap:0 var(--space-4);align-items:baseline;padding-top:var(--space-3);padding-bottom:var(--space-2)}
.runner-head h1{grid-area:title;font-size:var(--fs-xl);font-weight:800;letter-spacing:-.02em;line-height:1.2}
.runner-head .breadcrumbs{grid-area:crumb;margin:0 0 var(--space-1);font-size:var(--fs-sm)}
.runner-head .page-subtitle{grid-area:sub;margin:0;font-size:var(--fs-sm);line-height:1.4}
.runner-shell[data-view=board] .page-subtitle{display:none}
.form-shell>.runner-app,.runner-shell>.runner-app{max-width:none}
.runner-app{display:grid;grid-template-rows:auto auto auto;gap:var(--space-2) 0;align-content:start}
.runner-top{display:grid;gap:var(--space-2)}
.runner-top>.callout,.runner-top>.validation-summary{margin:0;padding:var(--space-2) var(--space-4);font-size:var(--fs-sm)}
.runner-top>.callout .form-actions{margin-top:var(--space-2)}
.runner-race strong{display:inline;margin:0 var(--space-1) 0 0}
.runner-app[data-view=board] .runner-race-how{display:none}
.runner-stage{position:relative}
/* The panes are containing blocks: screen-reader-only text is positioned, and would otherwise reach past the window.
   They carry a little padding, pulled back with a margin, so focus rings at their edges are not clipped. */
.runner-pane{position:relative;padding:var(--space-2);margin:0 calc(-1 * var(--space-2))}
.runner-pane>*{max-width:880px}
.runner-pane .step:first-child{border-top:0;padding-top:var(--space-2)}
/* The bar: the note, the progress line, Run or Stop with Show the result, the status line and the figures; their places are the grid areas */
/* The bar is anchored at its foot: the controls sit at the bottom of it, so whatever is above them (the note, and on a phone
   the status and the figures) can come and go without moving Run, Stop or Show the result. */
.runner-actions{display:grid;grid-template-columns:minmax(0,1fr);grid-template-areas:"note" "live" "status" "bar" "button";gap:var(--space-2) var(--space-3);align-items:center;padding-top:var(--space-2);border-top:1px solid var(--line)}
.runner-progress{grid-area:bar;margin:0}
.runner-progress progress{display:block;width:100%;height:6px;accent-color:var(--accent)}
/* The race in the bar: yours and theirs on one speed scale, each bar a scaled fill, and the line that says who is ahead */
.race-bars{display:grid;gap:var(--space-1);margin-top:var(--space-2)}
.race-lane{display:grid;grid-template-columns:minmax(0,112px) minmax(0,1fr) minmax(0,104px);align-items:center;gap:var(--space-2);color:var(--ink-2);font-size:var(--fs-xs);font-variant-numeric:tabular-nums}
.race-name{min-width:0;overflow-wrap:anywhere}
.race-track{position:relative;display:block;height:8px;overflow:hidden;border-radius:var(--radius-pill);background:var(--surface-3)}
.race-fill{position:absolute;inset:0;background:var(--muted);transform:scaleX(0);transform-origin:0 50%;transition:transform var(--motion) var(--ease-out)}
.race-lane.is-you .race-fill{background:var(--accent)}
.race-value{min-width:0;text-align:right;white-space:nowrap}
.race-line{margin:var(--space-1) 0 0;color:var(--ink);font-size:var(--fs-sm);font-weight:600}
/* The bar keeps its shape from setup to the close of the reveal. A control that is not showing keeps its place (hidden from
   sight, not taken out of its row), so nothing moves when Run turns to Stop or when Show the result comes back. */
.runner-actions .form-actions{grid-area:button;display:flex;flex-wrap:nowrap;align-items:center;gap:var(--space-3);min-height:var(--control-hero);margin:0}
.runner-status{grid-area:status;margin:0;color:var(--muted);font-size:var(--fs-sm);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.runner-figures{grid-area:live;display:flex;flex-wrap:wrap;gap:var(--space-1) var(--space-4)}
.runner-live,.runner-streak{display:flex;flex-wrap:wrap;gap:var(--space-1) var(--space-4);margin:0;color:var(--ink);font-size:var(--fs-sm);font-weight:600;font-variant-numeric:tabular-nums}
/* Each figure keeps the room of its widest reading, so the numbers can change (and the speed roll) without moving the line:
   "Passed 44 of 44 so far" and "888.8 tok/s" at 15px. */
#runner-live-passed{min-width:10.2em}
#runner-live-speed{min-width:5.4em}
/* The speed's sparkline: a line in the figures' ink with no fill, a point for each task as the tasks finish. Under 375px
   the passed count, the speed and the line do not fit in a row, so the line takes a row of its own, up to 12rem across. */
.runner-spark{flex:none;align-self:center;overflow:visible}
@media (max-width:374px){.runner-spark{flex:0 0 100%;max-width:12rem;align-self:auto}}
.runner-spark polyline{fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.runner-posts{grid-area:note;margin:0}
.runner-app[data-view=board] .runner-posts{display:none}
/* A phone in a short window (480 to 599px tall): the note on posting is 163px at 320px wide and would leave the steps a
   sliver of pane, so the bar keeps its button alone; a run that ranks needs a sign-in, which the result says. */
@media (min-height:480px) and (max-height:599px) and (max-width:699px){.runner-posts{display:none}}
/* The same window, on the board: the page head (its breadcrumb, and its title, which the board's own name stands for) is left
   out, so a kept run's box and a refusal's message above Run have the room the board gives up. The title stays for screen
   readers. The head alone is 77px at 320px. */
@media (min-height:480px) and (max-height:599px) and (max-width:699px){
  .runner-shell[data-view=board] .runner-head{padding:0}
  .runner-shell[data-view=board] .runner-head .breadcrumbs{display:none}
  .runner-shell[data-view=board] .runner-head h1{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
}
/* From a tablet: Run (or Stop) and Show the result are cells of the bar, the status between them. Stop takes Run's cell and
   width, so it sits where Run was; Show the result has its own cell at the row's end, so the status does not move when it
   comes back after the reveal closes. The figures take a row under them, from the left. */
@media (min-width:700px){
  .runner-actions{grid-template-columns:auto minmax(0,1fr) auto;grid-template-areas:"note note note" "bar bar bar" "button status show" "live live live"}
  .runner-actions .form-actions{display:contents}
  #runner-start,#runner-stop{grid-area:button;justify-self:stretch;align-self:center}
  #runner-reveal-open{grid-area:show;align-self:center}
  #runner-start[hidden],#runner-stop[hidden],#runner-reveal-open[hidden]{display:inline-flex!important;visibility:hidden}
  .runner-status{grid-area:status;align-self:center}
  .runner-figures{min-height:calc(var(--fs-sm) * 1.55)}  /* One line from the first step, so the bar does not grow when a figure comes. */
}
/* A phone: Run (or Stop) and Show the result share the row as halves, or one takes the whole row. A label wraps rather than
   widen its button, so the row stays one hero tall. */
@media (max-width:699px){
  .runner-actions .form-actions .button{flex:1 1 0;min-width:0;white-space:normal;padding-left:var(--space-4);padding-right:var(--space-4)}
}
.runner-actions .form-actions .button.hero{min-height:var(--control-hero)}
/* The board: one row per category, a square per task that colours as its grade lands; titles show when there is room */
.runner-run{position:relative;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto auto;align-content:start;gap:var(--space-3);padding:var(--space-2);margin:0 calc(-1 * var(--space-2))}
/* The head is as tall as its Change button from the start: the button appears when the run ends, and it must not move the board. */
.runner-run-head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3);min-height:var(--control-sm)}
.runner-run-head h2{flex:1 1 12rem;min-width:0;font-size:var(--fs-md);font-weight:650;overflow-wrap:anywhere}
.runner-run-where{display:none;color:var(--muted);font-size:var(--fs-sm);overflow-wrap:anywhere}
.runner-run-head .step-change{flex:none;margin-left:auto}
/* While the run is on the script hides Change, but the button keeps its place (hidden only in sight): the title wraps round
   it from the start, so it does not reflow when Change appears at the end. */
#runner-setup-change[hidden]{display:inline-block!important;visibility:hidden}
.runner-tasks{display:grid;align-content:start;gap:var(--space-2);margin:0}
.runner-tasks section{display:grid;grid-template-columns:minmax(0,5.5rem) minmax(0,1fr);gap:var(--space-2);align-items:center}
.runner-tile-label{min-width:0;line-height:1.2}
.runner-tile-group{margin:0;font-size:var(--fs-xs);font-weight:600;color:var(--muted);line-height:1.2}
.runner-tally{display:block;font-size:var(--fs-xs);font-weight:500;line-height:1.2;font-variant-numeric:tabular-nums}
/* Five squares to a category at every width: the squares shrink with their row rather than wrap a fifth onto a second line. */
.tile-grid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:var(--space-2);margin:0;padding:0;list-style:none}
.runner-tile{position:relative;display:grid;place-items:center;width:40px;height:40px;padding:0;border:1px solid var(--control-line);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font:inherit;cursor:pointer;transition:border-color var(--motion) var(--ease-out),color var(--motion) var(--ease-out)}
.runner-tile>span[class^="tone-"]{display:flex;align-items:center;transition:color var(--motion) var(--ease-out)}
.runner-tile-title{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.runner-task.is-wait .runner-tile{color:var(--muted)}
.runner-task.is-asking .runner-tile,.runner-task.is-grading .runner-tile{border-color:var(--warn)}
.runner-task.is-asking .runner-tile .tone-neutral,.runner-task.is-grading .runner-tile .tone-neutral{color:var(--warn-text)}
.runner-task.is-bad .runner-tile{border-color:var(--bad)}
.runner-tile .icon-check-circle path{stroke-dasharray:13}  /* Longer than the check: script draws it in by its dash offset (land() in suite-runner.js). */
.runner-task.is-open .runner-tile{box-shadow:inset 0 0 0 2px var(--accent)}
/* A phone: twelve rows of smaller squares beside labels wide enough for one line, so the board stays in the window */
@media (max-width:699px){
  .runner-run{gap:var(--space-1)}
  .runner-tasks{gap:var(--space-1)}
  .runner-tasks section{grid-template-columns:minmax(0,8em) minmax(0,1fr)}  /* em of the body's 17px: the label keeps its width when the root text size grows */
  .runner-tile{width:32px;height:32px;max-width:100%}
  .tile-grid{gap:var(--space-1)}
}
@media (max-width:360px){.runner-tasks section{grid-template-columns:minmax(0,5.6em) minmax(0,1fr)}}
/* What the model said last, under the board, so every grade brings a sentence to read */
.runner-latest{display:flex;flex-wrap:wrap;gap:0 var(--space-2);align-items:flex-start;margin:0;padding:var(--space-2) var(--space-3);border:1px solid var(--line);border-radius:var(--radius-sm);color:var(--ink-2);font-size:var(--fs-sm);line-height:1.4}
.runner-latest-label{color:var(--muted);font-size:var(--fs-xs);font-weight:600;line-height:calc(var(--fs-sm) * 1.4)}
.runner-latest>span[class^="tone-"]{display:flex;align-items:center;height:calc(var(--fs-sm) * 1.4)}
.runner-latest-body{flex:1 1 12rem;min-width:0;display:flex;flex-wrap:wrap;gap:0 var(--space-2)}
.runner-latest strong{color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.runner-latest-said{flex:1 1 10rem;min-width:0;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
.runner-aside:has(dialog[open]) .runner-latest{display:none}
/* The open tile: a sheet over the bottom of the window, a panel beside the board where the window is wide */
.runner-task-detail{position:fixed;inset:auto 0 0 0;z-index:3;width:auto;height:auto;max-width:none;max-height:45dvh;margin:0;padding:var(--space-3) var(--space-4) var(--space-4);overflow:auto;border:1px solid var(--line-strong);border-bottom:0;border-radius:var(--radius) var(--radius) 0 0;background:var(--surface);color:var(--ink)}
.runner-detail-head{display:flex;align-items:flex-start;gap:var(--space-2);margin-bottom:var(--space-2)}
.runner-detail-head>span[class^="tone-"]{display:flex;align-items:center;height:calc(var(--fs-md) * 1.2)}
.runner-detail-head h3{flex:1;min-width:0;font-size:var(--fs-md);font-weight:650;line-height:1.2;overflow-wrap:anywhere}
.runner-detail-head .button{flex:none;margin-left:auto}
.runner-detail-said{margin:0;color:var(--ink-2);font-size:var(--fs-sm);overflow-wrap:anywhere}
.runner-task-rubric{margin:var(--space-2) 0 0;color:var(--muted);font-size:var(--fs-sm)}
.runner-task-rubric strong{margin-right:.35em;color:var(--ink)}
.runner-task-detail .page-frame{height:min(300px,calc(45dvh - 7.5rem));min-height:120px;margin-top:var(--space-3)}
@media (min-width:700px){.runner-task-detail{max-height:50dvh}}
/* From a tablet's width the twelve categories run in two columns of squares, so the board stays six rows tall; on a
   tablet each label sits over its squares. From 1200px the open tile has a column of its own beside the board, and
   where the window is also 840px tall or more, one column of twelve titled rows takes the board's place. */
@media (min-width:700px){
  .runner-tasks{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:var(--space-5)}
  .runner-task{container:tile/inline-size}
}
/* A square too narrow for its title shows its mark alone, centred, as on a phone; the title is still read out. */
@container tile (max-width:112px){
  .runner-tasks .runner-tile{grid-template-columns:auto;grid-template-rows:auto;justify-content:center;justify-items:center;align-content:center;padding:0}
  .runner-tasks .runner-tile-title{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;display:block}
}
@media (min-width:700px) and (max-width:1199px){
  .runner-tasks section{grid-template-columns:minmax(0,1fr);gap:var(--space-1)}
  .runner-tile-label{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 var(--space-2)}
}
@media (min-width:1200px){
  .runner-run{overflow:visible;grid-template-columns:minmax(0,1fr) 320px;grid-template-rows:auto minmax(0,1fr);column-gap:var(--space-6);padding:0;margin:0}
  .runner-run-head{grid-column:1/-1}
  .runner-run-where{display:inline}
  .runner-run-head h2{flex:0 1 auto;white-space:normal;overflow-wrap:anywhere}
  .runner-tasks{min-height:0;overflow:auto;padding:var(--space-2);margin:0 calc(-1 * var(--space-2))}
  .runner-tasks section{grid-template-columns:minmax(0,6.1em) minmax(0,1fr)}
  .tile-grid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr))}
  .runner-task{display:grid;min-width:0}
  .runner-tile{display:grid;grid-template-columns:auto minmax(0,1fr);justify-items:start;align-items:start;align-content:center;gap:var(--space-1);width:100%;height:100%;min-height:44px;padding:var(--space-1) var(--space-2);text-align:left;font-size:var(--fs-xs);font-weight:500}
  .runner-tile>span[class^="tone-"]{height:calc(var(--fs-xs) * 1.2)}
  .runner-tile-title{position:static;width:auto;height:auto;overflow:hidden;clip:auto;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:1.2}
  .runner-aside{min-height:0;display:grid;grid-template-rows:auto minmax(0,1fr);align-content:start;gap:var(--space-3)}
  .runner-latest{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start}
  .runner-latest-label{grid-column:1/-1}
  .runner-latest-body{display:block}
  .runner-latest strong{display:block}
  .runner-latest-said{-webkit-line-clamp:3}
  .runner-task-detail{position:static;width:auto;height:auto;min-height:0;max-height:100%;border-bottom:1px solid var(--line-strong);border-radius:var(--radius-sm)}
}
@media (min-width:700px) and (max-width:1199px){
  .runner-tasks{gap:var(--space-1)}
  /* A tablet: the squares stretch to fill the row, five to a category, instead of leaving half of it empty. */
  .tile-grid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr))}
  .runner-task{display:grid;min-width:0}
  .runner-tile{width:100%}
}
/* A tall tablet has the room to name each task under its mark. */
@media (min-width:700px) and (max-width:1199px) and (min-height:900px){
  .runner-tile{height:auto;min-height:64px;padding:var(--space-2);gap:var(--space-1);align-content:start;grid-template-rows:auto auto}
  .runner-tile-title{position:static;width:auto;height:auto;overflow:hidden;clip:auto;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:var(--fs-xs);font-weight:500;line-height:1.2;text-align:center}
}
@media (max-height:720px) and (max-width:1199px){.runner-latest{display:none}}
/* A short, wide window (a laptop): lower tiles, still two lines of title, so the six rows fit above the bar */
@media (min-width:1200px) and (max-height:760px){.runner-tile{min-height:40px;padding-top:2px;padding-bottom:2px}.runner-tasks{gap:var(--space-1)}}
/* A wide, tall window has room for one column of twelve titled rows, as the seven-row board had; two columns of squares only where the height is short. */
@media (min-width:1200px) and (min-height:840px){.runner-tasks{grid-template-columns:minmax(0,1fr);row-gap:var(--space-1)}}
@media (max-height:660px){.runner-head .page-subtitle{display:none}}
@media (max-height:660px) and (min-width:700px) and (max-width:1199px){.runner-tile{width:36px;height:36px}.tile-grid{gap:var(--space-1)}}
@media (min-width:1200px) and (max-height:660px){.runner-tile{min-height:36px}}
/* A very short window (a phone on its side): the race line waits for the reveal, the squares shrink, the bar is one row */
@media (max-height:560px){
  .runner-head{padding-top:var(--space-2);padding-bottom:var(--space-1)}
  .runner-shell[data-view=board] .runner-race{display:none}
}
@media (max-height:560px) and (max-width:1199px){.runner-tile{width:32px;height:32px}.tile-grid{gap:var(--space-1)}}
/* The reveal: a dialog over the board when the run posts; the score counts up to its tier on the ladder */
.callout.reveal-dialog{width:min(100% - 2 * var(--space-4),640px);max-width:none;max-height:calc(100dvh - 2 * var(--space-5));margin:auto;padding:0;overflow:auto;border-radius:var(--radius-lg)}
.reveal-dialog::backdrop{background:rgb(22 19 26 / 55%)}
.reveal-inner{padding:var(--space-4) var(--space-6) var(--space-5);font-size:var(--fs-sm)}
/* text-wrap: pretty keeps a single word from standing alone on the last line (the rank: "Apple silicon #2 of 2."). */
.reveal-inner .reveal-line,.reveal-inner .runner-ranking{margin:var(--space-1) 0;line-height:1.45;text-wrap:pretty}
/* A line said once the count lands keeps its place from the start, so the dialog is its final height when it opens. */
.reveal-line.is-waiting{visibility:hidden}
.reveal-inner .race-table{margin:var(--space-2) 0 var(--space-3);font-size:var(--fs-xs)}
.reveal-inner .race-table th,.reveal-inner .race-table td{padding:var(--space-1) var(--space-2)}
.reveal-head{display:flex;align-items:flex-start;gap:var(--space-3);margin-bottom:var(--space-2)}
.reveal-head h2{flex:1;min-width:0;margin:0;color:var(--muted);font-size:var(--fs-md);font-weight:600;line-height:1.3;overflow-wrap:anywhere}
.reveal-head .button{flex:none}
.reveal{position:relative;margin:0 0 var(--space-3);line-height:1.1}
.reveal-score{font-size:var(--fs-display);font-weight:800;color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.tier-ladder{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:var(--space-1);margin:0 0 var(--space-3);padding:0;list-style:none;color:var(--muted);font-size:var(--fs-xs);line-height:1.3}
.tier-ladder li{min-width:0;padding:var(--space-2) var(--space-1) 0 0;border-top:3px solid var(--line-strong)}
@media (max-width:699px){.tier-ladder strong{font-size:var(--fs-xs)}}
@media (max-width:379px){.tier-ladder li:not([aria-current]):not(.is-next) strong,.tier-ladder li:not([aria-current]):not(.is-next) small{display:none}}
.tier-ladder li.is-reached{border-top-color:var(--accent)}
.tier-ladder li{transition:border-top-color var(--motion-fast) var(--ease-out)}
.tier-track{position:relative}
.tier-marker{position:absolute;top:-4px;left:0;width:10px;height:10px;border-radius:50%;background:var(--accent);pointer-events:none;transition:transform var(--motion) var(--ease-out)}
.reveal-burst{position:absolute;inset:0;overflow:hidden;pointer-events:none}
.reveal-burst span{position:absolute;left:0;top:0;width:7px;height:11px;margin:-6px 0 0 -4px;border-radius:2px}
.tier-ladder li[aria-current]{color:var(--accent-text);font-weight:700}
.tier-ladder strong{display:block;font-weight:inherit;font-size:var(--fs-sm)}
.tier-ladder small{display:block;font-size:var(--fs-xs);font-variant-numeric:tabular-nums}
.reveal-best{display:flex;align-items:flex-start;gap:var(--space-2);color:var(--ink);font-weight:600}
.reveal-best>span[class^="tone-"]{display:flex;align-items:center;height:calc(var(--fs-md) * 1.55)}
.reveal-verdict{font-weight:600;overflow-wrap:anywhere}
.reveal-finding{display:flex;align-items:flex-start;gap:var(--space-2);overflow-wrap:anywhere}
.reveal-finding>span[class^="tone-"]{display:flex;flex:none;align-items:center;height:calc(var(--fs-sm) * 1.45)}
.reveal-dialog .hero-actions{margin-top:var(--space-3);margin-bottom:var(--space-3)}
.reveal-dialog .hero-actions .button{flex:1 1 auto}
@media (min-width:700px){.reveal-dialog .hero-actions .button{flex:0 1 auto}}
.reveal-dialog .run-share{margin-bottom:var(--space-2)}
.reveal-dialog .run-share .button{flex:1 1 0;min-width:max-content} /* Equal widths, like the buttons above them. */
.reveal-dialog .form-help{margin-top:var(--space-2)}

/* Balance: on a wide window a page head puts its actions beside the title, and a page's body is two columns,
   heavier on the left, so neither side is empty while the other runs on. From 1400px long lists run in two columns. */
.board-grid{margin-top:var(--space-6)}
.catalog-tools{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);margin:0 0 var(--space-5)}
.compare-form{max-width:880px}
.compare-table{width:auto;min-width:min(100%,720px)}
.compare-table .num{padding-right:var(--space-8)}
@media (min-width:901px){.report-cols{grid-template-columns:minmax(0,3fr) minmax(0,2fr)}}
.comments.is-empty .comment-thread{display:none}
@media (min-width:700px) and (max-width:1099px){
  .gallery-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-4)}
  .model-aside{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--space-7) var(--space-6)}
}
@media (min-width:1100px){
  .page-head:not(.runner-head,.chat-head){display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);column-gap:var(--space-9);align-items:center}
  .page-head:not(.runner-head,.chat-head)>*{grid-column:1}
  .page-head:not(.runner-head,.chat-head)>.hero-actions{grid-column:2;grid-row:1/span 4;margin:0;justify-self:end;justify-content:flex-end;flex-wrap:wrap;align-self:center}
  .page-head:not(.runner-head,.chat-head)>.hero-actions .button{margin-top:0}
  .page-grid{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);column-gap:var(--space-9);row-gap:var(--space-7);align-items:start}
  .page-grid>*{min-width:0;margin-top:0}
  .page-grid>.comments,.page-grid>.model-aside,.page-grid>.span{grid-column:1/-1}
  .page-grid>.comments{padding-top:var(--space-5)}
  /* The aside's last section lines up with the page's right column; the others share the left. */
  .page-grid>.model-aside{grid-template-columns:minmax(0,1fr) minmax(0,1fr) calc((100% - var(--space-9)) * 2 / 5);column-gap:var(--space-9);margin-top:0}
  .page-grid>.model-aside>:last-child:not(:first-child){grid-column:3}
  .machine-side>.model-aside{grid-template-columns:minmax(0,1fr)}
  .wrap.page-grid>section+section,.wrap.suite-grid>section+section,.wrap.challenges-grid>section+section,.wrap.page-grid>*+*{margin-top:0}
  .run-grid{grid-template-columns:minmax(0,3fr) minmax(0,2fr)}  /* The facts and their actions, then the failures: the page's 3:2. */
  .run-grid>.run-facts{grid-column:1}
  .run-grid>.run-failed{grid-column:2;margin-bottom:0;padding-bottom:0;border-bottom:0}
  .run-grid>.run-tasks{grid-column:1/-1}
  .run-grid.no-failed>.run-tasks:not(.run-unscored){grid-column:2;grid-row:1;margin-bottom:0}  /* Unscored tasks come after, under both columns. */
  .board-grid{margin-top:var(--space-6);display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr);grid-template-areas:"all mine" "all note";grid-template-rows:auto 1fr;column-gap:var(--space-9);align-items:start}
  .board-grid>.board-all{grid-area:all;min-width:0}
  .board-grid>.board-mine{grid-area:mine;min-width:0;margin:0;padding:0;border-bottom:0}
  .board-grid>.board-note{grid-area:note;min-width:0}  /* The tiers sit under your computer, beside the leaderboard. */
  .suite-grid{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,3fr);grid-template-areas:"take tasks" "results results";column-gap:var(--space-9);row-gap:var(--space-7);align-items:start}
  .suite-grid>*{min-width:0;margin-top:0}
  .suite-grid>.agent-panel{grid-area:take}
  .suite-grid>.suite-tasks{grid-area:tasks;margin-bottom:0;padding-bottom:0;border-bottom:0}
  .suite-tasks{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:var(--space-7);align-items:start}  /* The twelve categories in two columns: an opened one grows its own row. */
  .suite-tasks>h2,.suite-tasks>p{grid-column:1/-1}
  .suite-tasks>p{margin-bottom:var(--space-4)}
  .suite-tasks>p+.run-category{margin-top:0}
  .suite-tasks>.run-category:nth-last-child(2){border-bottom:1px solid var(--line)}  /* Each column ends on a rule. */
  .suite-grid>.suite-results{grid-area:results;margin-bottom:0;padding-bottom:0;border-bottom:0}
  .challenges-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-areas:"active propose" "proposed propose" "ended propose";column-gap:var(--space-9);row-gap:var(--space-7);align-items:start}
  .challenges-grid>*{min-width:0;margin-top:0}
  .challenges-grid>.ch-active{grid-area:active}
  .challenges-grid>.ch-propose{grid-area:propose}
  .challenges-grid>.ch-proposed{grid-area:proposed}
  .challenges-grid>.ch-ended{grid-area:ended}
  .challenge-grid>.comments{grid-column:2;grid-row:1;margin-top:0;padding-top:0;border-top:0}
  .challenge-grid>.standings{grid-column:1;margin-top:0;padding-top:0;border-top:0}
  .comments:not(.challenge-grid>.comments){display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);column-gap:var(--space-9);align-items:start}
  .comments>h2{grid-column:1/-1}
  .comments>.comment-thread{grid-column:1;min-width:0}
  .comments>.comment-form,.comments>.muted{grid-column:2;grid-row:2;margin-top:0;align-self:start}
  .comments.is-empty>.comment-form,.comments.is-empty>.muted{grid-column:1}
}
@media (min-width:1400px){
  .stack-list.cols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:var(--space-7)}
  .stack-list.cols:not(:has(> li:nth-child(4))){display:block}
}
/* The agents guide: the path on the left, the other routes beside it */
@media (min-width:1100px){
  .agents-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:var(--space-9);align-items:start}
  .agents-grid>div{min-width:0}
  .agents-grid>div>.panel{max-width:none}
  .agents-grid>.agents-side>.panel:first-child{margin-top:0;padding-top:0;border-top:0}
}
/* The runner's first step on a wide window: Connect and what it says on the left, the other ways on the right */
@media (min-width:1200px){
  .runner-pane>#step-app:not(.is-done){max-width:none}
  #step-app-body{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:var(--space-9);align-items:start}
  #step-app-body>.step-main,#step-app-body>.step-side{min-width:0}
  .step-side>.disclosure:first-child{margin-top:0}
}
