/* Direction B, "the working drawing" (docs/design/spec-r2.md, FROZEN 2026-10-28): the instruments the film shows once
   the call is under way (the call log, the phone and tablet strip, first aid's phone, the square cursor), then the page
   after the film: a big drawing of how the line works and a panel beside it. Linked just before the
   section, so the film paints without waiting for it (§7). The sheet, its rulers and the gauge are on the first screen,
   so their few rules stay in index.html. Built from sketch B (proto/rest-b/) with spec-r2 §10's fixes. */

:root {
  --key-off: #C9CFD3; --sky: #5B9BD9; --shadow-l: rgba(30,35,40,.22); --shadow-xl: rgba(30,35,40,.5);
  --hair-13: rgba(30,35,40,.13); --hair-2: rgba(30,35,40,.2); --hair-22: rgba(30,35,40,.22); --hair-26: rgba(30,35,40,.26);
  --hair-28: rgba(30,35,40,.28); --hair-4: rgba(30,35,40,.4); --hair-42: rgba(30,35,40,.42); --hair-45: rgba(30,35,40,.45);
  --hair-5: rgba(30,35,40,.5); --hair-55: rgba(30,35,40,.55); --red-45: rgba(213,43,30,.45);
  --blue-42: rgba(0,87,168,.42); --blue-10: rgba(0,87,168,.1);
  /* the blueprint grid (spec-r2 §3): at a dot it is #BDD1E4, where grey text falls to 3.73:1, so no text sits on it */
  --grid: rgba(0,87,168,.22);
  /* spec-r11 §5: the ink footer's text colours (each 4.5:1 or more on --ink) and its dots' blue (the logo's own on its dark
     file, 3:1 or more, never text) */
  --on-ink: #F2F4F5; --mute-on-ink: #9AA3AB; --link-on-ink: #8FBCEB; --blue-on-ink: #4F94DE;
}

/* ===== during the film ===== */
/* the sheet (spec-r2 §4): a hairline frame, ruler ticks that run with the call, crosshair corners; and the depth gauge
 under the bar, a tick per step of the call's chain and a playhead, no times (Zero). Unstyled until this file loads,
 the instruments are empty boxes in the stage: nothing shifts, nothing shows. */
.inst { position: absolute; inset: 0; pointer-events: none; }
.frame { position: absolute; inset: 10px; border: 1px solid var(--hair-13); pointer-events: none; }
.ru { position: absolute; overflow: hidden; display: block; }
.ru b { position: absolute; display: block; will-change: transform; }
.ru-t, .ru-b { left: 18px; right: 18px; height: 12px; } .ru-t { top: 0; } .ru-b { bottom: 0; }
.ru-l, .ru-r { top: 18px; bottom: 18px; width: 12px; } .ru-l { left: 0; } .ru-r { right: 0; }
.ru-t b, .ru-b b { top: 0; bottom: 0; left: 0; width: calc(100% + 80px);
  background: linear-gradient(90deg, var(--hair-42) 1px, transparent 1px) 0 0 / 80px 11px repeat-x, linear-gradient(90deg, var(--hair-26) 1px, transparent 1px) 0 0 / 8px 5px repeat-x; }
.ru-b b { background-position: 0 100%, 0 100%; }
.ru-l b, .ru-r b { left: 0; right: 0; top: 0; height: calc(100% + 80px);
  background: linear-gradient(180deg, var(--hair-42) 1px, transparent 1px) 0 0 / 11px 80px repeat-y, linear-gradient(180deg, var(--hair-26) 1px, transparent 1px) 0 0 / 5px 8px repeat-y; }
.ru-r b { background-position: 100% 0, 100% 0; }
.cx { position: absolute; width: 22px; height: 22px; }
.cx::before, .cx::after { content: ""; position: absolute; background: var(--ink); opacity: .55; }
.cx::before { left: 0; right: 0; top: 10.5px; height: 1px; } .cx::after { top: 0; bottom: 0; left: 10.5px; width: 1px; }
.cx i { position: absolute; inset: 6px; border: 1px solid var(--hair-55); border-radius: 50%; }
.cx-tl { left: -11px; top: -11px; } .cx-tr { right: -11px; top: -11px; } .cx-bl { left: -11px; bottom: -11px; } .cx-br { right: -11px; bottom: -11px; }
.pm { position: absolute; width: 0; height: 0; opacity: 0; transition: opacity .2s; }
.pm-x { top: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 7px solid var(--blue); margin-left: -4px; }
.pm-y { left: 0; border-top: 4px solid transparent; border-bottom: 4px solid transparent; border-left: 7px solid var(--blue); margin-top: -4px; }
.frame.on .pm { opacity: 1; }
.gauge { position: absolute; left: var(--pad); right: var(--pad); top: 82px; height: 16px; }
.gauge .gl, .gauge .gp { position: absolute; left: 0; right: 0; top: 7.5px; height: 1px; background: var(--hair-22); }
.gauge .gp { height: 2px; top: 7px; background: var(--blue); transform-origin: left; transform: scaleX(0); }
.gauge .gl::before, .gauge .gl::after { content: ""; position: absolute; top: -5px; width: 1px; height: 11px; background: var(--hair-5); }
.gauge .gl::before { left: 0; } .gauge .gl::after { right: 0; }
.gt { position: absolute; top: 4px; width: 8px; height: 8px; margin-left: -4px; background: var(--paper); border: 1.5px solid var(--hair-45); transition: background .25s, border-color .25s, transform .25s; }
.gt.on { border-color: var(--blue); background: var(--blue); }
.gt.on.k-red, .gt.on.k-caller { border-color: var(--red); background: var(--red); }
.gt.on.k-accepted, .gt.on.k-told { border-color: var(--green); background: var(--green); }
.gt.now { transform: scale(1.35); }
.gh { position: absolute; top: -3px; left: 0; width: 1.5px; height: 22px; background: var(--ink); will-change: transform; }
.gh::before { content: ""; position: absolute; left: -3px; top: -3px; width: 7.5px; height: 4px; background: var(--ink); }
html:not(.js) .gauge { display: none; }
/* the phone: the sheet inset 6 px, its rulers 8 px deep (long ticks 7, short 4), so they end inside the 16 px gutter */
@media (max-width: 760px) {
  .frame { inset: 6px; } .gauge { display: none; }
  .ru-t, .ru-b { height: 8px; } .ru-l, .ru-r { width: 8px; }
  .ru-t b, .ru-b b { background-size: 80px 7px, 8px 4px; } .ru-l b, .ru-r b { background-size: 7px 80px, 4px 8px; }
}
/* the call log (lower left): types in the chain's steps as they happen, titles only */
.log { position: absolute; left: var(--pad); bottom: 6vh; width: 288px; padding: 14px 18px 12px; opacity: 0; will-change: opacity; --rows: 5; }
.log h2 { margin: 0 0 6px; }
.log h2 .tag::before { content: ""; display: inline-block; width: 7px; height: 7px; background: var(--red); margin-right: 6px; vertical-align: 1px; animation: rec 1.2s steps(2) infinite; }
@keyframes rec { 50% { opacity: .15; } }
.log .win { height: calc(min(var(--rows), var(--fit, 99)) * 24px); overflow: hidden; position: relative; }
.log ol { list-style: none; margin: 0; padding: 0; transition: transform .45s cubic-bezier(.2,.7,.2,1); }
.log li, .strip .row { display: flex; align-items: center; gap: 10px; height: 24px; font-size: 14px; font-weight: 600; white-space: nowrap; }
.mk { flex: none; width: 8px; height: 8px; background: var(--blue); }
.mk.k-red, .mk.k-caller { background: var(--red); } .mk.k-accepted, .mk.k-told { background: var(--green); } .mk.k-in { background: var(--ink); }
.log li .tx { color: var(--ink); } .log li.old .tx { color: var(--mute); }
.caret { display: inline-block; width: 7px; height: 14px; background: var(--blue); margin-left: -6px; vertical-align: -2px; animation: rec 1s steps(2) infinite; }
.log li:not(:last-child) .caret { display: none; }
/* the phone and tablet form: one row, the latest step, beside a strip of squares */
.strip { position: absolute; left: var(--pad); right: var(--pad); display: none; align-items: center; gap: 12px; height: 38px; padding: 0 14px;
  background: var(--card); border-radius: 12px; box-shadow: 0 1px 0 var(--line), 0 12px 28px -16px var(--shadow-l); opacity: 0; }
.strip .row { flex: 1; min-width: 0; overflow: hidden; }
.strip .sq { display: flex; gap: 4px; flex: none; }
.strip .sq i { width: 7px; height: 7px; border: 1.2px solid var(--hair-4); }
.strip .sq i.on { background: var(--blue); border-color: var(--blue); }
.strip .sq i.on.k-red, .strip .sq i.on.k-caller { background: var(--red); border-color: var(--red); }
.strip .sq i.on.k-accepted, .strip .sq i.on.k-told { background: var(--green); border-color: var(--green); }
.strip .prog { position: absolute; left: 14px; right: 14px; bottom: 0; height: 2px; background: var(--blue); transform-origin: left; transform: scaleX(0); }

/* first aid's phone, a small live screen (Potadot), rising near the accepter's dot when first aid is rung; every word
   on it at 13 px or more (§2), so the phone is 148 px wide */
.fone { position: absolute; left: 0; top: 0; width: 148px; opacity: 0; display: none; will-change: transform, opacity; }
.fone .body { position: relative; height: 262px; border-radius: 26px; background: var(--ink); padding: 7px; box-shadow: 0 22px 40px -22px var(--shadow-xl); }
.fone .scr { position: relative; height: 100%; border-radius: 20px; background: var(--card); overflow: hidden; text-align: center; }
.fone .scr::before { content: ""; position: absolute; left: 50%; top: 6px; width: 34px; height: 9px; margin-left: -17px; border-radius: 6px; background: var(--ink); }
.fs { position: absolute; inset: 0; padding: 26px 8px 12px; display: flex; flex-direction: column; align-items: center; opacity: 0; transition: opacity .3s; }
.fone[data-s="in"] .fs-in, .fone[data-s="on"] .fs-on, .fone[data-s="key"] .fs-key, .fone[data-s="ok"] .fs-ok { opacity: 1; }
.fs small { font-size: 13px; font-weight: 700; color: var(--mute); text-transform: uppercase; letter-spacing: .06em; }
.fs strong { font-size: 14px; font-weight: 800; margin-top: 4px; line-height: 1.15; }
.fs .code { margin-top: 4px; font-size: 13px; font-weight: 700; color: var(--red-t); }
.fs .ring { margin: 16px auto 0; width: 34px; height: 34px; border-radius: 50%; border: 2px solid var(--red); position: relative; }
.fs .ring::after { content: ""; position: absolute; inset: 9px; border-radius: 50%; background: var(--red); }
.fs-in .ring { animation: fring 1s ease-out infinite; }
@keyframes fring { 0% { box-shadow: 0 0 0 0 var(--red-45); } 100% { box-shadow: 0 0 0 16px var(--red-0); } }
.fs .btns { margin-top: auto; display: flex; gap: 26px; }
.fs .btns i { width: 28px; height: 28px; border-radius: 50%; background: var(--key-off); }
.fs .btns i + i { background: var(--green); }
.fs .vw { margin-top: 22px; display: flex; gap: 3px; align-items: center; height: 40px; }
.fs .vw b { width: 4px; height: 40px; background: var(--blue); border-radius: 2px; transform: scaleY(.15); will-change: transform; }
.fs-key small { color: var(--ink); text-transform: none; letter-spacing: 0; font-size: 13px; }
.pad { margin-top: 10px; display: grid; grid-template-columns: repeat(3, 30px); gap: 5px; }
.pad i { height: 30px; border-radius: 8px; background: var(--paper); font: 700 13px/30px var(--font); font-style: normal; color: var(--mute); padding-top: 1px; }
.pad i.lit { background: var(--blue); color: var(--card); box-shadow: 0 0 0 3px var(--blue-25); animation: lit 1s ease-in-out infinite; }
@keyframes lit { 50% { box-shadow: 0 0 0 6px var(--blue-10); } }
.fs .okr { margin: 16px auto 0; width: 44px; height: 44px; border-radius: 50%; border: 2.5px solid var(--green); display: grid; place-items: center; }
.fs .okr::after { content: ""; width: 16px; height: 8px; border-left: 3px solid var(--green); border-bottom: 3px solid var(--green); transform: translateY(-2px) rotate(-45deg); }
.fs-ok small { color: var(--green-t); }
.fs .after { margin-top: 10px; font-size: 13px; color: var(--mute); line-height: 1.3; }
/* the tag sits clear of the body's shadow, which darkens the paper about 40 px down: at 8 px its grey fell to 3.86:1 */
.fone .tagl { display: block; margin-top: 24px; font-size: 13px; font-weight: 700; color: var(--mute); text-align: center; line-height: 1.3; }

/* a small square cursor (fine pointers, over the drawing surfaces only; the native cursor stays on every control) */
.sqc { position: fixed; left: 0; top: 0; width: 0; height: 0; pointer-events: none; z-index: 20; opacity: 0; transition: opacity .15s; will-change: transform;
  --h: 6.25px; --k: .35; }
/* its four edges, each a 40 px line scaled to the square's size and moved out to its side: the square grows round a
   hotspot by transforms alone (Hallmark 10a), its edges staying 1.5 px; at rest 14 px (--k .35), round a hotspot its size
   plus 10 (rest.js sets --h and --k) */
.sqc i { position: absolute; left: 0; top: 0; background: var(--ink); transition: transform .18s, background-color .18s; }
.sqc i:nth-child(-n+2) { width: 40px; height: 1.5px; margin: -.75px 0 0 -20px; }
.sqc i:nth-child(n+3) { width: 1.5px; height: 40px; margin: -20px 0 0 -.75px; }
.sqc i:nth-child(1) { transform: translateY(calc(-1 * var(--h))) scaleX(var(--k)); } .sqc i:nth-child(2) { transform: translateY(var(--h)) scaleX(var(--k)); }
.sqc i:nth-child(3) { transform: translateX(calc(-1 * var(--h))) scaleY(var(--k)); } .sqc i:nth-child(4) { transform: translateX(var(--h)) scaleY(var(--k)); }
.sqc::after { content: ""; position: absolute; left: -1px; top: -1px; width: 2px; height: 2px; background: var(--ink); }
.sqc.on { opacity: 1; }
.sqc.hot i { background: var(--blue); }
.fine #field, .fine .art { cursor: none; }

@media (min-width: 1024px) { .js .fone { display: block; } }
@media (max-width: 1023px) {
  html:not(.still) .log { display: none; }
  .js:not(.still) .strip { display: flex; }
}
/* the tablet's still page shows the call log complete after the copy (spec-r2 §6; his yes 2026-11-01), the phone none */
@media (max-width: 760px) { .log { display: none; } }
@media (min-width: 761px) and (max-width: 1023px) {
  .strip { top: calc(56vh - 50px); top: calc(56svh - 50px); max-width: 400px; }
}
@media (max-width: 760px) {
  .strip { left: 16px; right: 16px; top: calc(47vh - 46px); top: calc(47svh - 46px); }
}
@media (max-height: 880px) { .log { --rows: 4; } }
/* in the film the call log closes the copy column (rest.js puts it there), which runs to 6vh from the bottom: the log
   sits at its foot where there is room and follows the caption 6 px under it where there is not, its window giving up
   whole rows (--fit, rest.js; a short desktop screen: at a fixed 6vh it covered the caption at 1100x700, site-r5-run6),
   hidden where not one fits (.cramped). On a screen 800 px tall or less its card is 13 px slimmer, so a 1366x768
   laptop keeps two rows in every call.
   The 9 key's label narrows to clear first aid's phone while the call is under way where the phone has no room above
   it (--gl, rest.js), its lines balanced so "made-up" keeps its hyphen */
@media (min-width: 1024px) {
  /* the column's empty foot and the log stay the field's, for the square cursor, as the log was in .inst */
  .js:not(.still) .copy { bottom: 6vh; display: flex; flex-direction: column; pointer-events: none; }
  .js:not(.still) .copy > :not(.log) { pointer-events: auto; }
  .js:not(.still) .copy .caption { margin-bottom: 6px; }
  .js:not(.still) .copy .log { position: relative; left: auto; bottom: auto; margin-top: auto; flex: none; }
  .js:not(.still) .copy .log.cramped { visibility: hidden; }
  .folded #gate-label { max-width: var(--gl, 270px); }
  .folded #gate-label, .folded #gate-label small { text-wrap: balance; }
}
@media (min-width: 1024px) and (max-height: 800px) {
  .js:not(.still) .copy .log { padding: 9px 18px 8px; }
  .js:not(.still) .copy .log h2 { margin-bottom: 2px; }
}
/* the still page clips nothing: its copy column holds the headline, the selector that never folds (spec-r3 §7), the
   caption and the call log complete (spec-r2 §6), more than a short screen holds, so the stage grows to it. The field
   stays one screen tall at the stage's top with the subtitle on it; the call log follows the caption (rest.js) */
@media (min-width: 761px) {
  .still .stage { height: auto; min-height: 100vh; min-height: 100svh; }
  .still .hud { position: relative; min-height: 100vh; min-height: 100svh; display: flow-root; }
  .still .copy { position: relative; inset: auto; margin: 19vh 0 0 var(--pad); padding-bottom: 6vh; }
  .still canvas#field { height: 100vh; height: 100svh; }
  .still .hud > .subs { bottom: calc(100% - 94vh); bottom: calc(100% - 94svh); }
  .still .copy .log { position: static; margin-top: 24px; }
}
@media (min-width: 761px) and (max-width: 1023px) { .still .copy { margin: 56vh var(--pad) 0; margin-top: 56svh; } }
/* the phone's still page: the subtitle follows the selector in the copy column (film.js), where it sat on the picks
   (site-r5-run6), so the stage grows to hold it; the headline keeps its 44vh, the field one screen at the top */
@media (max-width: 760px) {
  .still .stage { height: auto; min-height: 100vh; min-height: 100svh; }
  .still .hud { position: relative; min-height: 100vh; min-height: 100svh; display: flow-root; }
  .still .copy { position: relative; inset: auto; margin: 44vh 16px 0; margin-top: 44svh; padding-bottom: 6vh; }
  .still canvas#field { height: 100vh; height: 100svh; }
  .still .copy .subs { position: static; margin-top: 22px; }
}

/* past the film the bar takes an opaque ground, so nothing ghosts through it (§10.7), and Skip has nothing to skip; its
   hairline is its own last row (inset), never a row below its box: a line sliding under the bar met that row first, and
   the judge measured it as the line's ground (04's fine line 4.44 at 1440, 2026-11-05; tests/still-bar.test.mjs) */
.past .bar { background: var(--paper); box-shadow: inset 0 -1px 0 var(--line); }
.past #skipfilm { visibility: hidden; }

/* ===== after the film: the drawing ===== */
.explain { position: relative; background: var(--paper); }
/* the sideways move (spec-r3 §5, FROZEN 2026-10-29): this section sits in the film's track (index.html) and starts a lead
   (--lead) before the film ends. Its track opens with the room for the lead and the stretch (.ex-run); ex-pin0 stands
   where the stage rests, the stretch's end; the stage is held at the top through the room by its sticky bottom, then by
   its sticky top as before. On the phone the stage is taller than a screen, so its bottom is held that much lower
   (--ex-hold, glide.js). The browser holds both stages; script only slides them sideways (tasks/lessons.md 30). The
   section lets the film's stage show through as it slides out; the explainer's stage is opaque. */
.ex-run { display: none; }
.js:not(.still) .ex-run { display: block; height: calc(var(--lead) + var(--stretch)); }
.js:not(.still) .explain { background: none; }
.js:not(.still) .ex-track { height: calc(400vh + var(--lead) + var(--stretch)); }
.ex-stage { position: relative; min-height: 100vh; min-height: 100svh; padding: 96px var(--pad) 44px; display: flex; flex-direction: column; }
.js:not(.still) .ex-stage { position: sticky; top: 0; bottom: 0; height: 100vh; height: 100svh; z-index: 3; background: var(--paper); }
/* glide.js: the explainer waits off the right until the move brings it in; the film, once out, is hidden */
.glide .stage, .glide .ex-stage { will-change: transform; }
.glide .ex-stage { transform: translate3d(100vw, 0, 0); }
.film-out .stage { visibility: hidden; }
/* Lenis 1.3.26's own rules (glide.js) */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: clip; }
/* the blueprint dot grid, faint, on paper; no text ever sits on it (§3): HTML text has an opaque paper ground, SVG
   labels a paper ground and halo */
.ex-stage::before { content: ""; position: absolute; inset: 10px; pointer-events: none;
  background: radial-gradient(circle, var(--grid) 1px, transparent 1.4px) 0 0 / 24px 24px; }
.ex-head { position: relative; display: flex; align-items: flex-end; justify-content: space-between; gap: 32px; margin-bottom: 2.5vh; }
.ex-head > div { background: var(--paper); padding: 4px 8px 6px; margin: -4px -8px -6px; }
.ex-kick { margin: 0 0 12px; font-size: 13px; font-weight: 700; color: var(--blue); display: flex; align-items: center; }
.ex-kick::before { content: ""; width: 32px; height: 2px; background: currentColor; margin-right: 10px; }
.explain h2 { margin: 0; font-weight: 900; font-size: clamp(32px, 3.3vw, 54px); line-height: .98; letter-spacing: -0.035em; max-width: 25ch; text-wrap: balance; }
.ln { display: block; overflow: hidden; padding-bottom: .06em; margin-bottom: -.06em; }
.ln > span { display: block; transition: transform .9s cubic-bezier(.2,.75,.15,1); }
.js:not(.still) .explain h2.split:not(.in) .ln > span { transform: translateY(105%); }
.ex-body { position: relative; flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 44px; align-items: center; }
.dwg { position: relative; min-height: 0; }
.js:not(.still) .dwg { height: 100%; display: grid; place-items: center; }
.js:not(.still) .ex-body { grid-template-rows: minmax(0, 1fr); }
.ex-room { display: none; }
.art { position: relative; aspect-ratio: 1000 / 656; width: 100%; }
.js:not(.still) .art { aspect-ratio: auto; }
.art svg, .art picture img { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.art picture img { object-fit: contain; }
.svg-p { display: none; }
.sph { position: absolute; left: 24.4%; top: 37.2%; width: 11.2%; height: 17.07%; pointer-events: none; }

/* drawing marks; a label is 13 px rendered at any scale (§2: rest.js sets --lab, --halo and --k for the drawing's scale) */
.art text { font-family: var(--font); font-size: var(--lab, 13px); font-weight: 700; fill: var(--mute); letter-spacing: .07em; text-transform: uppercase; }
.art .lab { paint-order: stroke fill; stroke: var(--paper); stroke-width: var(--halo, 5px); stroke-linejoin: round; }
.art .lg { fill: var(--paper); }
.art .dense .sub { display: none; }
.art .b { fill: var(--ink); }
.art .r { fill: var(--red-t); } .art .g { fill: var(--green-t); } .art .bl { fill: var(--blue); }
.art .mid { text-anchor: middle; } .art .end { text-anchor: end; }
.w { fill: none; stroke: var(--ink); stroke-width: 1.4; stroke-linecap: round; }
.w.red { stroke: var(--red); stroke-width: 1.8; } .w.blue { stroke: var(--blue); stroke-width: 1.8; } .w.green { stroke: var(--green); stroke-width: 2.6; }
.w.thin { stroke-width: 1; stroke: var(--hair-55); } .w.ghost { stroke-width: 1; stroke: var(--hair-28); stroke-dasharray: 3 5; }
.w.wire { stroke: var(--blue-42); stroke-width: 1; }
.w.ret { stroke: var(--green); stroke-width: 1.4; stroke-dasharray: 6 6; }
.w.dash { stroke-dasharray: 3 4; stroke: var(--hair-5); stroke-width: 1; }
.dot.red { fill: var(--red); } .dot.green { fill: var(--green); } .ring.green { fill: var(--card); stroke: var(--green); stroke-width: 2.4; }
.flow { fill: none; stroke-width: 4; stroke-linecap: round; stroke-dasharray: .001 .035; }
.flow.red { stroke: var(--red); } .flow.blue { stroke: var(--blue); } .flow.green { stroke: var(--green); }
.js:not(.still) .flow { animation: flow 1.4s linear infinite; }
@keyframes flow { to { stroke-dashoffset: -.072; } }
.phg rect { fill: var(--card); stroke-width: 1.6; } .phg line { stroke-width: 1.6; stroke-linecap: round; }
.phg.red rect, .phg.red line { stroke: var(--red); } .phg.blue rect, .phg.blue line { stroke: var(--blue); }
.art .acc .phg.red:not(.on) { opacity: .35; }
.pz { fill: none; stroke-width: 1.2; transform-box: fill-box; transform-origin: center; opacity: 0; }
.pz.red { stroke: var(--red); } .pz.blue { stroke: var(--blue); } .pz.green { stroke: var(--green); }
.js:not(.still) .pz { animation: pz 1.8s ease-out infinite; }
.js:not(.still) .pz.d { animation-delay: .9s; }
@keyframes pz { 0% { transform: scale(.5); opacity: .8; } 100% { transform: scale(1.6); opacity: 0; } }
.art .acc .pz.red { animation: none; }
.still .pz { opacity: .5; }
.key9 rect { fill: var(--card); stroke: var(--ink); stroke-width: 1.4; } .art .key9 text { fill: var(--red-t); font-size: 14px; letter-spacing: 0; }
.doc path { fill: var(--card); stroke: var(--ink); stroke-width: 1.3; } .doc line { stroke: var(--hair-5); stroke-width: 1.3; }
.js:not(.still) .art [data-s] { opacity: 0; }
.js:not(.still) .art [data-s][pathLength] { opacity: 1; stroke-dasharray: 1 2; stroke-dashoffset: 1; }
/* a picked step stands out: the other steps' strokes and marks step back, their labels keep their colours (§10.5). A
   mark that draws in by opacity carries it on a <g data-s> round it (assets/drawing/), so the step-back on the mark
   itself multiplies with it instead of being overridden; the other steps' pulses stop, and the line's sphere is step 1's */
.art :is(path, circle, ellipse, line, rect:not(.lg)) { transition: opacity .3s; }
/* (.js:not(.still) so these outrank the draw-in rule above, which holds a drawing stroke at opacity 1) */
.js:not(.still) .art[data-sel] .st :is(path, circle, ellipse, line, rect:not(.lg)) { opacity: .3; }
.js:not(.still) .art[data-sel="0"] .st0 :is(path, circle, ellipse, line, rect:not(.lg)), .js:not(.still) .art[data-sel="1"] .st1 :is(path, circle, ellipse, line, rect:not(.lg)),
.js:not(.still) .art[data-sel="2"] .st2 :is(path, circle, ellipse, line, rect:not(.lg)), .js:not(.still) .art[data-sel="3"] .st3 :is(path, circle, ellipse, line, rect:not(.lg)) { opacity: 1; }
.js:not(.still) .art[data-sel]:not([data-sel="0"]) .st0 .pz, .js:not(.still) .art[data-sel]:not([data-sel="1"]) .st1 .pz,
.js:not(.still) .art[data-sel]:not([data-sel="2"]) .st2 .pz, .js:not(.still) .art[data-sel]:not([data-sel="3"]) .st3 .pz { animation: none; opacity: 0; }
.sph { transition: filter .3s; }
.js:not(.still) .art[data-sel]:not([data-sel="0"]) .sph { filter: opacity(.3); }

/* numbered square hotspots (Heron) */
.hss { position: absolute; inset: 0; pointer-events: none; }
.hs { position: absolute; left: var(--x); color: inherit; text-decoration: none; top: var(--y); transform: translate(-50%, -50%); pointer-events: auto; display: flex; align-items: center; gap: 10px;
  padding: 0; border: 0; background: none; cursor: pointer; text-align: left; font: inherit; }
.hs b { flex: none; width: 30px; height: 30px; display: grid; place-items: center; padding-top: 2px; background: var(--card); border: 1.5px solid var(--blue); color: var(--blue);
  font-size: 13px; font-weight: 800; transition: background .2s, color .2s, box-shadow .2s; box-shadow: 0 0 0 4px var(--paper); }
.hs span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.hs[aria-current] b, .hs:hover b { background: var(--blue); color: var(--card); }
.js:not(.still) .hs.next b { animation: hsping 1.6s ease-out infinite; }
@keyframes hsping { 0% { box-shadow: 0 0 0 4px var(--paper), 0 0 0 4px var(--blue-50); } 100% { box-shadow: 0 0 0 4px var(--paper), 0 0 0 14px var(--blue-0); } }
.js:not(.still) .hs { opacity: 0; transition: opacity .3s; } .js:not(.still) .hs.shown { opacity: 1; }

/* the panel beside the drawing (Heron's live product panel): one step's words, a small live screen */
.side { display: flex; flex-direction: column; gap: 16px; align-self: center; }
.panel { position: relative; background: var(--card); border-radius: 18px; padding: 22px 22px 18px; box-shadow: 0 1px 0 var(--line), 0 24px 50px -24px var(--shadow-l); }
.js:not(.still) .panel { min-height: 300px; }
.step { scroll-margin-top: 96px; }
.step + .step { margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--line); }
.js:not(.still) .step + .step { margin: 0; padding: 0; border: 0; }
.js:not(.still) .step.off { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.step h3 { margin: 0 0 10px; display: flex; align-items: center; gap: 12px; font-size: 24px; font-weight: 800; letter-spacing: -0.015em; }
.step h3 b { flex: none; width: 30px; height: 30px; display: grid; place-items: center; padding-top: 2px; background: var(--blue); color: var(--card); font-size: 13px; }
.step p { margin: 0; font-size: 16px; line-height: 1.5; color: var(--mute); }
.mini { margin-top: 16px; border: 1px solid var(--line); border-radius: 10px; padding: 8px 12px 6px; }
.mini:empty { display: none; }
.mini .mh { display: flex; justify-content: space-between; font-size: 13px; font-weight: 700; color: var(--mute); padding-bottom: 4px; }
.mini .mh span:last-child { color: var(--blue); }
.mini ul { list-style: none; margin: 0; padding: 0; }
.mini .mr { display: grid; grid-template-columns: 8px 1fr auto; gap: 2px 10px; align-items: center; padding: 6px 0 5px; border-top: 1px solid var(--line); font-size: 13.5px; font-weight: 600; }
.mini .mr small { grid-column: 2 / 4; font-size: 13px; color: var(--mute); font-weight: 400; }
.mini .mr em { font-style: normal; font-size: 13px; font-weight: 700; }
.mini em.k-red { color: var(--red-t); } .mini em.k-ring { color: var(--blue); } .mini em.k-accepted { color: var(--green-t); }
.js:not(.still) .step:not(.off) .mr { animation: mr .5s cubic-bezier(.2,.7,.2,1) both; }
.js:not(.still) .step:not(.off) .mr:nth-child(2) { animation-delay: .12s; } .js:not(.still) .step:not(.off) .mr:nth-child(3) { animation-delay: .24s; }
@keyframes mr { from { opacity: 0; transform: translateY(6px); } }
.dis { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 18px; pointer-events: none; }
/* for the 0.56 s the blocks cover the words, the canvas is the topmost thing there (a hit test finds it, not the words) */
.dis.on { pointer-events: auto; }
/* the title block, bottom right of the sheet */
.tb { display: grid; grid-template-columns: auto 1fr; border: 1px solid var(--hair-45); font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; background: var(--paper); }
.tb span { padding: 6px 9px 4px; border-bottom: 1px solid var(--hair-2); color: var(--mute); }
.tb span:nth-child(odd) { border-right: 1px solid var(--hair-2); color: var(--ink); }
.tb span:nth-last-child(-n+2) { border-bottom: 0; }
.legend { list-style: none; margin: 0 0 4px; padding: 12px 14px; display: grid; gap: 7px; font-size: 13px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--mute); border: 1px solid var(--hair-28); background: var(--paper); flex: none; }
.legend li { display: flex; align-items: center; gap: 10px; }
.legend i { flex: none; width: 26px; height: 2px; background: var(--red); }
.legend .lg-b { background: var(--blue); } .legend .lg-g { background: var(--green); height: 3px; }
.legend .lg-s { width: 18px; height: 18px; margin: 0 4px; background: var(--card); border: 1.5px solid var(--blue); color: var(--blue); font-style: normal;
  font-size: 13px; display: grid; place-items: center; padding-top: 1px; }

.again { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 15vh var(--pad) 6vh; }
.again .key { width: 84px; height: 84px; font-size: 40px; border-radius: 20px; }
.again p { margin: 22px 0 0; font-size: 19px; font-weight: 700; }
.again p small { display: block; margin-top: 4px; font-size: 13.5px; font-weight: 400; color: var(--mute); }
/* the sample call in words, speaker by speaker (from calls.json), for anyone who reads rather than listens */
.tscript { margin: 0 auto 6vh; padding: 0 var(--pad); max-width: calc(62ch + 2 * var(--pad)); }
.tscript summary { cursor: pointer; font-weight: 700; font-size: 16px; color: var(--blue); width: fit-content; margin: 0 auto; padding: 8px 4px; }
.tscript summary:hover { text-decoration: underline; }
.tscript ol { list-style: none; margin: 18px 0 0; padding: 0; display: grid; gap: 12px; font-size: 15px; line-height: 1.45; }
.tscript li b { display: block; font-size: 13px; color: var(--blue); }
.tscript li.caller b { color: var(--red-t); } .tscript li.accepter b { color: var(--green-t); } .tscript li.narrator b { color: var(--mute); }
.tscript li.ev { color: var(--mute); font-style: italic; }
.tscript li small { display: block; color: var(--mute); font-size: 13px; margin-top: 2px; }
/* scripting off: no sample to play, no call to gauge or read */
html:not(.js) .again, html:not(.js) .tscript { display: none; }
.explain .note { margin: 0 auto; text-wrap: pretty; padding: 0 var(--pad) 5vh; max-width: 62ch; font-size: 14px; line-height: 1.5; color: var(--mute); text-align: center; }

@media (prefers-reduced-motion: reduce) { .flow, .pz, .hs b, .caret, .log h2 .tag::before, .fs-in .ring, .pad i.lit { animation: none !important; } .ln > span { transition: none; } }

@media (min-width: 761px) and (max-width: 1023px) {
  .ex-body { grid-template-columns: minmax(0, 1fr); gap: 20px; align-content: start; }
  .js:not(.still) .ex-body { grid-template-rows: minmax(0, 1fr) auto; }
  .js:not(.still) .dwg { height: 100%; }
  .side { flex-direction: row; align-items: stretch; }
  .panel { flex: 1; } .js:not(.still) .panel { min-height: 250px; }
  .tb { align-self: end; }
}
/* the phone: the drawing turns upright, the hotspots become the step list beside it, the panel goes under */
@media (max-width: 760px) {
  .js:not(.still) .ex-track { height: auto; }
  .ex-stage { padding: 88px 16px 0; display: block; min-height: 0; }
  .js:not(.still) .ex-stage { top: auto; bottom: var(--ex-hold, 0px); height: auto; }
  .js:not(.still) .ex-room { display: block; height: 300vh; }
  .ex-stage::before { inset: 6px; background-size: 20px 20px; }
  .ex-head { display: block; margin-bottom: 26px; }
  .explain h2 { font-size: clamp(30px, 8.6vw, 38px); }
  .ex-body { display: flex; flex-direction: column; gap: 14px; align-items: stretch; }
  .js:not(.still) .ex-body { position: sticky; top: calc(64px + env(safe-area-inset-top, 0px)); }
  .dwg, .js:not(.still) .dwg { display: block; height: auto; place-items: normal; container-type: inline-size; }
  .art { aspect-ratio: auto; width: 206px; height: 480px; }
  .svg-l { display: none; } .svg-p { display: block; }
  .sph { left: 35.83%; top: 17.14%; width: 28.33%; height: 12.14%; }
  .hss { left: calc(100% + 14px); right: auto; width: calc(100cqw - 220px); }
  .hs { left: 0; top: var(--py); transform: translateY(-50%); width: 100%; }
  .hs span { position: static; width: auto; height: auto; overflow: visible; clip-path: none; white-space: normal; font-size: 15px; font-weight: 800; line-height: 1.15;
    color: var(--mute); background: var(--paper); padding: 5px 6px 3px; margin: -2px -2px; }
  .hs[aria-current] span { color: var(--ink); }
  .hs b { width: 26px; height: 26px; font-size: 12px; }
  .side { gap: 0; }
  .tb, .legend { display: none; }
  .panel { padding: 16px 16px 14px; }
  .js:not(.still) .panel { min-height: 214px; }
  .step h3 { font-size: 19px; margin-bottom: 6px; } .step h3 b { display: none; }
  .step p { font-size: 14.5px; line-height: 1.45; }
  .mini { margin-top: 10px; padding: 4px 10px 2px; }
  .mini .mh { display: none; }
  .mini .mr:first-child { border-top: 0; }
  .again { padding-top: 10vh; }
}

/* ---------- spec-r4 (FROZEN 2026-10-29): what the line does, after the injury call's section (what.js) ----------
   Still (reduced motion, or the canvas's module failing): each section's text beside its figure, drawn. With motion,
   B "The line, close up" (.dots): the sections at the left, one canvas pinned by the browser in the right column (behind
   them, the figure in the top third, under 1024), never held by a transform from script (spec-r4 §7). */
.wsecs { position: relative; background: var(--paper); }
.wstage { display: none; }
.wsec { position: relative; display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: clamp(32px, 5vw, 88px); align-items: center;
  padding: 96px var(--pad); border-top: 1px solid var(--line); }
.wtxt { max-width: 520px; }
.wkick { display: flex; align-items: center; gap: 10px; margin: 0 0 18px; font-size: 13px; font-weight: 700; color: var(--blue); }
.wkick b { display: grid; place-items: center; min-width: 30px; height: 26px; padding: 2px 6px 0; border: 1.5px solid var(--blue); font-size: 13px; font-weight: 800; }
/* spec-r10 §2: the headline heavier and larger */
.wsec h2 { margin: 0 0 20px; text-wrap: balance; font-size: clamp(34px, 4.3vw, 62px); line-height: 1.0; letter-spacing: -0.03em; font-weight: 900; }
.wbody { margin: 0 0 14px; text-wrap: pretty; font-size: 17px; line-height: 1.5; color: var(--mute); }
.wfine { margin: 0; text-wrap: pretty; font-size: 14px; line-height: 1.45; color: var(--mute); }
.wart { max-width: 560px; justify-self: end; width: 100%; }
/* the figures: ink lines, a sign colour per meaning; the labels' size is what.js's (13 px rendered or more) */
.wfig { display: block; width: 100%; height: auto; overflow: visible; }
.wfig path, .wfig circle { fill: none; stroke: var(--ink); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.wfig .lt { stroke: var(--grey); stroke-width: 1.4; }
.wfig .bl { stroke: var(--blue); } .wfig .gr { stroke: var(--green); } .wfig .rd { stroke: var(--red); }
.wfig .thick { stroke-width: 6; }
.wfig .fl { fill: var(--blue); stroke: var(--blue); } .wfig .fc { fill: var(--card); }
.wfig .pd { stroke: var(--grey); stroke-dasharray: 7 6; stroke-width: 1.6; }
.wfig text { font: 700 15px/1 var(--font); letter-spacing: .06em; text-transform: uppercase; fill: var(--ink); stroke: none; }
.wfig text.m { fill: var(--mute); } .wfig text.b { fill: var(--blue); } .wfig text.g { fill: var(--green-t); }
@media (max-width: 1023px) {
  .wsec { grid-template-columns: minmax(0, 1fr); padding-block: 72px; }
  .wart { justify-self: center; max-width: 520px; }
}

/* B: one stage beside the sections (under 1024, behind them), each section in its own row */
.wsecs.dots { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
.dots .wstage { display: block; grid-column: 2; grid-row: 1 / span 5; align-self: start; position: sticky; top: 0; height: 100vh; height: 100svh; }
/* spec-r10 D: a section holds its word, then its figure (1.5 screens from 1024, 1.4 under) */
.dots .wsec { display: flex; align-items: center; grid-column: 1; min-height: 150vh; padding: 120px 0 80px var(--pad); border: 0; }
.dots .wsec:nth-child(2) { grid-row: 1; } .dots .wsec:nth-child(3) { grid-row: 2; } .dots .wsec:nth-child(4) { grid-row: 3; }
.dots .wsec:nth-child(5) { grid-row: 4; } .dots .wsec:nth-child(6) { grid-row: 5; }
/* the figure is the canvas's; its SVG stays for a screen reader (role img, its label) */
.dots .wart { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.wstage canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.wcount { position: absolute; left: 0; top: 112px; display: flex; align-items: baseline; gap: 8px; font-weight: 800; color: var(--blue); }
.wcount .roll { display: inline-block; height: 1em; overflow: hidden; font-size: 64px; line-height: 1; letter-spacing: -0.03em; }
.wcount .roll span { display: block; transition: transform .5s cubic-bezier(.2, .7, .2, 1); }
.wcount small { font-size: 15px; color: var(--mute); }
.dots .wsec h2 .w { color: var(--grey); transition: color .25s; }
.dots .wsec h2 .w.on { color: var(--ink); }
@media (max-width: 1023px) {
  .wsecs.dots { grid-template-columns: minmax(0, 1fr); }
  .dots .wstage { grid-column: 1; }
  .dots .wsec { z-index: 1; align-items: flex-end; min-height: 140vh; min-height: 140svh; padding: 0 var(--pad) 7svh; }
  /* spec-r10 §3: the text's ground lets the dots show through, paper at 0.85, faded in over 64 px above the text and out
     over 64 px below it (the bottom fade hangs below by a negative margin, so the text stays where it was), full bleed;
     its grey text in ink there, so every line keeps 4.5:1 even over a full ink dot */
  .dots .wtxt { --mute: var(--ink); padding: 64px var(--pad); margin: 0 calc(-1 * var(--pad)) -64px; max-width: none; flex: 1;
    background: linear-gradient(to bottom, rgb(242 244 245 / 0), rgb(242 244 245 / .85) 64px, rgb(242 244 245 / .85) calc(100% - 64px), rgb(242 244 245 / 0)); }
  .dots .wtxt > * { max-width: 520px; }
  .dots .wsec h2 { font-size: 32px; margin-bottom: 14px; }
  .dots .wbody { font-size: 16px; margin-bottom: 10px; }
  .wcount { left: var(--pad); top: 84px; } .wcount .roll { font-size: 40px; }
}
@media (max-width: 760px) { .wbody { font-size: 16px; } }
/* spec-r5 (FROZEN 2026-10-31): the lockout drawing's marks (assets/drawing/lockout-*.svg), its legend, and its caller in
   the line's blue in the call log, the gauge, the strip, the small screens and the transcript (html.call-s03) */
.art .dot.blue { fill: var(--blue); }
.art .doc.on path { stroke: var(--blue); stroke-width: 1.8; } .art .doc.on line { stroke: var(--blue); }
.w.retb { stroke: var(--blue); stroke-width: 1.4; stroke-dasharray: 6 6; }
.art .rd { fill: var(--blue); }
.legend .lg-h { background: none; border-top: 2px dashed var(--grey); height: 0; }
.legend .lg-x { width: 14px; height: 14px; margin: 0 6px; background: none; border: 1.5px dashed var(--grey); border-radius: 50%; }
.call-s03 .gt.on.k-caller, .call-s01 .gt.on.k-caller { border-color: var(--blue); background: var(--blue); }
.call-s03 .mk.k-caller, .call-s01 .mk.k-caller { background: var(--blue); }
.call-s03 .strip .sq i.on.k-caller, .call-s01 .strip .sq i.on.k-caller { background: var(--blue); border-color: var(--blue); }
.call-s03 .tscript li.caller b, .call-s01 .tscript li.caller b { color: var(--blue); }
/* the breakdown drawing's marks (assets/drawing/breakdown-*.svg, spec-r5 §14): the AI's questions, the rest of the
   department's list; its caller in the line's blue as lockout's (html.call-s01) */
.art .qm rect { fill: var(--card); stroke: var(--blue); stroke-width: 1.4; } .art .qm text { fill: var(--blue); font: 800 11px var(--font); }
.art .phg.nx { opacity: .4; }

/* ===== the footer: spec-r11 B "The last stop" (FROZEN 2026-11-05) ===== */
/* On ink, full width, the words in the draft's order (docs/drafts/footer-pages.md's footer block): the name, the contact,
   the four links, the copyright; laid out links first. With scripting on, the footer's ::after is the room of the name in
   dots (foot-dots.js draws it there, with the line, the sphere and its rings, on a canvas behind the words, cleared
   behind every line of them); scripting off, the field is absent and the words stand alone (§7). The links keep one
   place at every width, the footer's top padding, even where the sphere comes under them (his ask, 2026-11-05: "they
   should always keep their position, even if it goes over the sphere"; the sketch dropped them under the sphere below
   1024). */
#foot { position: relative; overflow: hidden; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-areas: "links ." "contact ." "name copy"; row-gap: 36px; align-items: end;
  padding: clamp(120px, 16vh, 200px) var(--pad) calc(56px + env(safe-area-inset-bottom, 0px));
  background: var(--ink); color: var(--mute-on-ink); font-size: 14px; line-height: 1.5; }
#foot p { margin: 0; }
#foot > p:nth-of-type(1) { grid-area: name; }
#foot > p:nth-of-type(2) { grid-area: contact; font-size: 17px; }
#foot > p:nth-of-type(3) { grid-area: copy; justify-self: end; text-align: right; }
#foot strong { color: var(--on-ink); }
#foot a { color: var(--on-ink); }
#foot > p a { font-weight: 700; text-underline-offset: 3px; text-decoration-thickness: 1.5px; }
#foot nav { grid-area: links; }
#foot ul { margin: 0; padding: 0; list-style: none; }
#foot li { width: max-content; max-width: 100%; }
#foot nav a { display: flex; align-items: center; gap: 18px; font-size: clamp(30px, 3.8vw, 56px); font-weight: 800; letter-spacing: -0.03em;
  line-height: 1.18; text-decoration: none; }
/* the dotted lead that draws out on hover and focus, the line's dot */
#foot nav a::after { content: ""; flex: none; width: 0; height: 2.3px;
  background: linear-gradient(90deg, var(--blue-on-ink) 2.3px, transparent 2.3px) 0 50% / 7px 2.3px repeat-x; transition: width .4s cubic-bezier(.2, .8, .2, 1); }
#foot nav a:hover::after, #foot nav a:focus-visible::after { width: clamp(40px, 6vw, 96px); }
#foot :focus-visible { outline: 2px solid var(--link-on-ink); outline-offset: 3px; }
#foot > :not(canvas) { position: relative; z-index: 1; }
#foot > canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.js #foot { padding-bottom: calc(clamp(20px, 3vh, 40px) + env(safe-area-inset-bottom, 0px)); }
.js #foot::after { content: ""; grid-column: 1 / -1; height: clamp(96px, 17vw, 300px); margin-top: clamp(12px, calc(7vh - 36px), 60px); }
@media (max-width: 1023px) {
  #foot { grid-template-columns: minmax(0, 1fr); grid-template-areas: "links" "contact" "name" "copy"; row-gap: 24px; }
  #foot > p:nth-of-type(3) { justify-self: start; text-align: left; }
}
@media (max-width: 760px) {
  .js #foot::after { height: 44vw; margin-top: 16px; }
}
@media (prefers-reduced-motion: reduce) { #foot nav a::after { transition: none; } }
