/* ═══ v2.19.0 · the phone pass (Arrick, 2026-08-12) — appended so every rule wins source order ═══ */
@media(max-width:760px){
  /* The weather, at half height: icon+temp lead, condition+place stack beside them, then one
     facts line — High · Low · Odds of Rain. Sunrise/sunset are desktop-only (cells 3+4).
     Same DOM, so ≥761px renders the v2.18 card untouched. */
}
@media(max-width:720px){
  /* No footer on phones — its doors live on the More page now. The page keeps enough
     bottom padding that the last card scrolls fully clear of the floating dock. */
  .ft{display:none}
  #appRoot>.page{padding-bottom:calc(94px + env(safe-area-inset-bottom,0px))}
  /* Your Stats header on phones (v2.19.1): the "Metrics that matter" tail is gone —
     the title and the pill share the row alone, the desktop way. */
}
/* installed PWA: same treatment at any width — the tail belongs to desktop-browser view only */
@media(display-mode:standalone){.wh-hd .ct-sub{display:none}}

/* ═══ v2.21.0 · the home stack (Arrick, 2026-08-14 — 4-screen PDF comp) ═══
   Phones only: Home becomes four full-screen slides — Overview · Train · Fuel ·
   Monitor — snapped vertically, one swipe per screen (the Nike grammar, taken to
   its conclusion). The app bar leaves the Home view entirely: each slide carries
   its own chrome — the compact weather block top-left, the avatar chip top-right
   (the avatar replaces the dock's More tab; Crew takes that slot, disabled for
   now). Desktop renders renderTodayDesktop untouched. Every measurement below is
   traced from the comp at 390×848 (vectors extracted from the PDF, not eyeballed). */
@media(max-width:720px){
  /* the header returns the avatar on phones (v2.21 supersedes v2.18's wordmark-only
     header): on every NON-home view the chip is the door to the More page. */
  .ab-right{display:flex}
  .ab-right .menu{display:none!important}   /* the phone chip navigates — never the desktop dropdown */
  body.home-stack .app-bar,body.home-stack .demobar{display:none}
  body.home-stack #appRoot>.page{padding:0;max-width:none}
  /* v2.21.1 (Arrick's phone pass, 2026-08-14) — --hs-top clears the status bar:
     black-translucent lets the slides paint the whole screen, so every top offset
     rides the safe-area inset instead of assuming iOS reserved the bar. */
  body.home-stack{overflow:hidden;--hs-top:max(61px,calc(24px + env(safe-area-inset-top,0px)))}   /* the stack owns the scroll */
  /* v2.21.4 — the stack views enter with a transform-FREE fade: the shared .view.on
     entrance tweens translateY(4px)→none, and a transformed ancestor becomes the
     containing block for position:fixed — the pinned stack would size against the
     view (height 0) for the animation's 300ms instead of the viewport. */
  /* v2.21.10 — NO entrance animation on phones, at all: the ViewTransition owns the
     navigation fade here. v2.21.9 suppressed the entrance only WHILE the VT ran
     (html.vt) and released it after — but releasing animation:none RESTARTS a CSS
     animation from zero, so the arriving view replayed opacity 0→1 AFTER the
     cross-fade settled: the same flash, now with a visible refade (Arrick's second
     recording). The only restart-proof suppression is unconditional. This also
     retires v2.21.4's fadeflat — with no entrance animation there is no transform
     to hijack the fixed stack. Desktop (>720px) keeps its subtle entrance fade;
     phone no-VT paths (reduced-motion, older browsers) show views instantly, which
     beats any flash. */
  .view.on,body.home-stack #view-today.on,body.home-stack #view-crew.on{animation:none}
  /* v2.21.8 — v2.21.7's screen.height compensator is REVERTED: Arrick's video proved
     the webview CLIPS all content (fixed elements included) at the stale viewport's
     bottom edge — oversized slides were cut to the same strip, and the dropped dock
     was cut in half. Nothing can paint there; the only real fix is ending the stale
     window. vp-kick below is that fix's CSS half: for one painted frame the document
     becomes scrollable again (a real view navigation — Arrick's manual fix — does the
     same), which is what makes WebKit re-measure. Everything on screen is covered by
     the fixed stack during that frame, so the kick is invisible. */
  body.home-stack.vp-kick{overflow:visible}

  /* v2.21.4 — the stack pins to the REAL viewport (position:fixed + inset:0), not to
     100dvh: in an installed PWA iOS under-reports dvh by the bottom safe-area inset,
     which left a white letterbox over the home-indicator strip (Arrick's phone pass,
     08-15). Fixed-position geometry sizes to the initial containing block — the same
     box env() measures — so the slides paint edge to edge whatever dvh thinks. */
  .hs{position:fixed;inset:0;overflow-y:auto;scroll-snap-type:y mandatory;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
  /* v2.21.1 — slides are NOT scrollers: one scroll surface (the stack) means a swipe
     always reaches the snap. Content fits by construction — the comp's vertical gaps
     live in .hs-sp spacers that give their height back first when the safe areas eat
     into 100dvh; open-ended lists scroll inside themselves instead of growing the slide. */
  .hs-slide{position:relative;height:100dvh;scroll-snap-align:start;scroll-snap-stop:always;display:flex;flex-direction:column;padding:calc(var(--hs-top) + 54px) 32px 0;overflow:hidden;color:var(--hs-ink)}
  .hs .hs-slide{height:100%}   /* v2.21.4 — slides size to the real scrollport, not dvh; 100dvh above stays as the out-of-stack fallback */
  body.home-stack #view-crew>.hs-slide{position:fixed;inset:0;height:auto}   /* v2.21.4 — Crew's bare slide gets the same edge-to-edge treatment */
  .hs-slide>*{flex:0 0 auto}                /* content never crushes — only spacers + lists yield */
  .hs-sp{flex:0 30 var(--sp);min-height:8px}
  @media(max-height:659px){.hs-slide{overflow-y:auto;overscroll-behavior:auto}}   /* tiny screens: reachability beats the snap — chain at the edges */
  /* slide themes — inks, hairlines and the avatar flip per background, per the comp */
  .hs-overview{--hs-ink:var(--ink);--hs-mut:#5E5950;--hs-rule:#5E5950;--hs-hair:var(--line);--hs-ava-bg:#0A0A0A;--hs-ava-ink:#fff;background:var(--paper)}
  .hs-train{--hs-ink:#fff;--hs-mut:rgba(255,255,255,.85);--hs-rule:rgba(255,255,255,.6);--hs-hair:rgba(255,255,255,.55);--hs-ava-bg:#fff;--hs-ava-ink:var(--ink);background:linear-gradient(180deg,#F31833 0%,#5400DB 100%)}
  .hs-fuel{--hs-ink:var(--ink);--hs-mut:#5E5950;--hs-rule:#5400DB;--hs-hair:#5400DB;--hs-ava-bg:#0A0A0A;--hs-ava-ink:#fff;background:#fff;
    background-image:repeating-linear-gradient(180deg,transparent 0 18.8px,#E8EFF4 18.8px 19.4px),repeating-linear-gradient(90deg,transparent 0 18.8px,#E8EFF4 18.8px 19.4px)}
  .hs-monitor{--hs-ink:#fff;--hs-mut:#D9D6D0;--hs-rule:#E3DED6;--hs-hair:rgba(255,255,255,.9);--hs-ava-bg:#fff;--hs-ava-ink:var(--ink);background:#0A0A0A}   /* v2.21.3 — Recover goes black (was the comp's taupe #5E5950) */

  /* ── the chrome — v2.21.1: ONE weather block + avatar, fixed over the stack.
     It holds still while the slides pass beneath, flipping ink via .dark (Train,
     Monitor); Fuel keeps its purple hairline via .on-fuel. hsChromeSync drives it. ── */
  .hs-chrome{position:fixed;top:0;left:0;right:0;z-index:60;display:flex;justify-content:space-between;align-items:flex-start;padding:var(--hs-top) 32px 0;pointer-events:none;--hs-ink:var(--ink);--hs-rule:#5E5950;--hs-ava-bg:#0A0A0A;--hs-ava-ink:#fff}
  .hs-chrome.on-fuel{--hs-rule:#5400DB}
  .hs-chrome.dark{--hs-ink:#fff;--hs-rule:rgba(255,255,255,.6);--hs-ava-bg:#fff;--hs-ava-ink:var(--ink)}
  .hs-chrome .hs-wx,.hs-chrome .pg-ava{pointer-events:auto}
  .hs-wx{font-family:var(--courier);text-transform:uppercase;color:var(--hs-ink);text-align:left;transition:color .3s var(--ease)}
  .hs-wx-1{display:flex;align-items:center;gap:7px;font-size:10.5px;font-weight:700;letter-spacing:.04em}
  .hs-wx .wx-ico{width:14px;height:14px}
  .hs-chrome.dark .hs-wx svg *{stroke:#fff}
  .hs-wx-rule{width:145px;height:1px;background:var(--hs-rule);margin:6px 0 6px;transition:background-color .3s var(--ease)}
  .hs-wx-2{font-size:9px;font-weight:500;letter-spacing:.04em;color:var(--hs-ink);transition:color .3s var(--ease)}
  /* the avatar chip lives in THE PHONE PAGE layer below (.pg-ava) — one circle
     in the app, whatever chrome it is standing in. The slide themes above and
     .hs-chrome below only set the two colour vars it reads. */

  /* ── slide title row (Train / Fuel / Monitor) ── */
  .hs-head{display:flex;align-items:flex-end;justify-content:space-between;flex:0 0 auto}
  .hs-h1{font-weight:900;font-size:41px;letter-spacing:-.02em;line-height:.9;color:var(--hs-ink)}
  .hs-today{font-family:var(--courier);font-size:15px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--hs-ink);line-height:1;padding-bottom:2px}
  .hs-head-rule{height:1.5px;background:var(--hs-hair);margin-top:14px;flex:0 0 auto}

  /* ── Overview ── */
  .hs-hi{font-weight:900;font-size:21px;letter-spacing:-.02em;line-height:1.1}
  .hs-cd-grad{display:block;font-weight:900;font-size:min(116px,29.5vw,13.7dvh);line-height:.78;letter-spacing:-.02em;-webkit-background-clip:text;background-clip:text;color:transparent;width:fit-content;padding-bottom:.04em}
  .hs-cd-113{background-image:linear-gradient(180deg,#F31833,#B30E76)}
  .hs-cd-days{background-image:linear-gradient(180deg,#930A98,#5400DB)}
  .hs-cd-mid{font-family:var(--courier);font-size:15.5px;font-weight:700;text-transform:uppercase;letter-spacing:.01em;line-height:1;display:flex;gap:26px;margin:7px 0 9px}
  .hs-cd-mid b{color:var(--accent);font-weight:700}
  .hs-cd-until{font-family:var(--courier);font-size:15.5px;font-weight:700;text-transform:uppercase;line-height:1;margin-top:14px;padding-left:3px}
  .hs-race{border-top:1.3px solid var(--line);border-bottom:1.3px solid var(--line);padding:17px 0 16px}
  .hs-race-h{display:flex;align-items:baseline;justify-content:space-between}
  .hs-race-name{font-weight:900;font-size:14px;letter-spacing:-.01em;line-height:1.2;color:var(--accent)}
  .hs-race-up{font-family:var(--courier);font-size:9px;font-weight:500;line-height:1.2;color:#5E5950;letter-spacing:.02em;padding:0}
  .hs-race-meta{display:flex;justify-content:space-between;font-family:var(--courier);font-size:8.5px;font-weight:700;line-height:1;text-transform:uppercase;letter-spacing:.03em;margin-top:13px}
  .hs-track{display:flex;gap:2.5px;margin-top:9px;position:relative}
  .hs-track i{display:block;height:3.2px;background:var(--line)}
  .hs-track .fill{position:absolute;left:0;top:0;height:3.2px;background:var(--ink)}
  .hs-track .dot{position:absolute;top:1.6px;transform:translate(-50%,-50%);width:12px;height:12px;border-radius:50%;background:var(--accent);border:2px solid #fff;box-sizing:border-box}
  .hs-phases{display:flex;gap:2.5px;margin-top:9px}
  .hs-phases span{font-family:var(--courier);font-size:8.5px;font-weight:700;line-height:1;text-transform:uppercase;letter-spacing:.03em;color:#5E5950}
  .hs-phases span.on{color:var(--ink)}
  /* v3.16 (Bet 1) — the Week Close card: ink, the record's voice, two doors and Close */
  /* v3.14 p4 — the Week Close BANNER: one ink line above the greeting; the card is its sheet */
  .hs-wcb{display:flex;align-items:center;gap:12px;width:100%;margin-top:16px;background:var(--ink);color:#fff;padding:0 16px;height:44px;text-align:left}
  .hs-wcb-eb{font-family:var(--courier);font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--volt);white-space:nowrap}
  .hs-wcb-h{flex:1;min-width:0;font-weight:900;font-size:14px;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .hs-wcb-arr{font-family:var(--courier);font-size:14px;font-weight:700}
  /* v3.15 — the banner on a short screen (found on the first Monday after v3.14 shipped: at 390×700 the
     Overview slide ran 15px past its height, the spacers already at their 8px floor). The hero number is
     the one element the slide already sizes by height, so it is the one that gives the banner its room —
     exactly as much as the fit needs and no more: the slide's fixed content with the banner is 559px and
     the countdown block is 61px + 1.64 × the number's font size, so font ≤ (100dvh − 559px) / 1.64. Above
     ~720px the 13.7dvh rule is the smaller term and nothing changes. */
  .hs-wcb~.hs-cd .hs-cd-grad{font-size:min(116px,29.5vw,13.7dvh,calc(61dvh - 341px))}
  .hs-go{font-family:var(--courier);font-size:15.5px;font-weight:700;line-height:1;text-transform:uppercase}
  .hs-norace{margin-top:30px}
  .hs-norace .eh{font-weight:900;font-size:21px}
  .hs-norace p{font-size:14px;color:var(--muted);margin:10px 0 14px;line-height:1.55}

  /* ── the slide CTA row — outlined courier buttons, pinned above the dock ── */
  .hs-cta{display:flex;gap:10.5px;margin-top:auto;padding-top:14px;padding-bottom:calc(min(107px,12.5dvh) + env(safe-area-inset-bottom,0px));flex:0 0 auto}
  .hs-btn{flex:1;height:47px;display:flex;align-items:center;justify-content:center;gap:6px;border:1.5px solid currentColor;background:transparent;font-family:var(--courier);font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;border-radius:var(--r-action);-webkit-tap-highlight-color:transparent;white-space:nowrap}
  .hs-btn:active{transform:scale(.97)}
  .hs-btn.t-red{color:var(--accent)} .hs-btn.t-purple{color:#5400DB} .hs-btn.t-black{color:#0A0A0A} .hs-btn.t-white{color:#fff}   /* v2.21.3 — Monitor→Recover wears black, not taupe */
  .hs-btn.off{opacity:.45}

  /* ── Train ── */
  .hs-quote{font-family:var(--courier);font-size:17px;font-weight:500;line-height:22px;text-transform:uppercase;color:var(--hs-ink)}
  .hs-quote-by{font-family:var(--courier);font-size:11.5px;font-weight:500;line-height:1;text-transform:uppercase;margin-top:min(21px,2.5dvh);color:var(--hs-ink)}
  .hs-quote-rule{height:1.3px;background:var(--hs-hair)}
  .hs-sess{flex:0 1 auto;min-height:0;margin-top:6px;padding-bottom:6px}   /* the padding absorbs button-baseline overhang — a 2px scroller would eat swipes */
  .hs-row{display:flex;align-items:baseline;gap:0;padding:23px 0 0;line-height:1;font-family:var(--courier);font-size:14px;font-weight:700;text-transform:uppercase;letter-spacing:.01em;color:var(--hs-ink)}
  .hs-row .n{flex:0 0 29px}
  .hs-row .t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}
  .hs-row .act{flex:0 0 auto;font-family:var(--courier);font-size:14px;font-weight:700;text-transform:uppercase;color:var(--hs-ink);padding:0 0 0 12px;-webkit-tap-highlight-color:transparent}
  .hs-row-rule{height:.8px;background:var(--hs-hair);margin-top:17px}
  .hs-add{display:block;font-family:var(--courier);font-size:14px;font-weight:700;line-height:1;text-transform:uppercase;letter-spacing:.01em;color:var(--hs-ink);margin-top:28px;text-align:left;padding:0;-webkit-tap-highlight-color:transparent}

  /* ── Fuel ── */
  .hs-bars{flex:0 1 auto;min-height:0;padding-bottom:6px}
  .hs-bar-row{margin-bottom:min(26px,3dvh)}
  .hs-bar-row .l{display:flex;justify-content:space-between;align-items:baseline;line-height:1.1;font-family:var(--courier);font-size:14px;font-weight:700;text-transform:uppercase;letter-spacing:.01em;color:var(--ink)}
  .hs-bar-row .l span:last-child{text-transform:none}   /* the comp's values keep their lowercase units: 3g / 180g */
  .hs-bar{height:3.2px;background:#E3DED6;margin-top:11px}
  .hs-bar i{display:block;height:100%;width:0;background:var(--accent);transition:width .8s var(--ease)}
  .hs-bar.hydro i{background:#0093E7}   /* the comp's water blue — hydration only, never a UI signal */
  .hs-bar.supp i{background:#5400DB}    /* supplements ride the spine's purple (--s3) */
  .hs-bar.hit i{background:var(--volt)} /* goal hit — same grammar as every goal bar in the app */
  /* v3.13 (audit V-1) — the whisper: what is left, in the small mono voice; over
     the target it speaks in brand red, on it in the hit colour */
  .hs-left{margin-top:7px;font-family:var(--courier);font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
  .hs-left.over{color:var(--accent)}
  .hs-left.hit{color:var(--ink)}

  /* ── Monitor ── */
  .hs-copy{font-family:var(--courier);font-size:17px;font-weight:500;line-height:22px;text-transform:uppercase;color:var(--hs-ink)}
  .hs-copy p{margin:0 0 22px}
  .hs-mon-stats{flex:0 1 auto;min-height:0;padding-bottom:6px}
  /* v2.21.2 — a list is a scroller ONLY while its content actually overflows (hsScrollSync
     flips .scrolls). An always-on overflow:auto + contain made every list an iOS touch trap:
     a swipe starting on it fed a scroller with nothing to scroll, and `contain` kept the
     gesture from ever chaining up to the snap stack — the screen simply didn't move
     (Arrick's phone pass, 08-15: the Monitor WHOOP block, but Train's list and Fuel's
     bars had the same dead zone). */
  .hs-sess.scrolls,.hs-bars.scrolls,.hs-mon-stats.scrolls{overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
  .hs::-webkit-scrollbar,.hs-sess::-webkit-scrollbar,.hs-bars::-webkit-scrollbar,.hs-mon-stats::-webkit-scrollbar{display:none}   /* a pager has no use for scrollbars */
  .hs,.hs-sess,.hs-bars,.hs-mon-stats{scrollbar-width:none}
  .hs-mon-stats .wh-badge{color:#fff;border-color:rgba(255,255,255,.45);background:transparent}
  .hs-monitor .wh-prime{margin-top:8px}
  .hs-monitor .wh-ring svg circle:first-of-type{stroke:rgba(255,255,255,.22)}
  .hs-monitor .wh-ring text{fill:#fff}
  .hs-monitor .wh-ring tspan[fill]{fill:rgba(255,255,255,.6)}
  .hs-monitor .wh-l{color:#fff}
  .hs-monitor .wh-sub{color:#D9D6D0}
  .hs-monitor .wh-tile{background:transparent;border:1px solid rgba(255,255,255,.28)}
  .hs-monitor .wh-k{color:#D9D6D0}
  .hs-monitor .wh-v{color:#fff}
  .hs-monitor .wh-v small{color:#D9D6D0}
  .hs-monitor .wh-s{color:#D9D6D0}

  /* ── Crew — v2.21.1: the coming-soon page. Volt on black, the slide grammar. ── */
  .hs-crew{--hs-ink:var(--volt);--hs-mut:var(--volt);--hs-hair:var(--volt);background:#0A0A0A}

  /* ══════════════════════════════════════════════════════════════════════
     THE PHONE PAGE · v3.2 — one language for every mobile surface
     ──────────────────────────────────────────────────────────────────────
     Today set the terms and the session recorder proved them. Below this
     line they are the app's ONLY mobile grammar. Ten primitives:

       .pg         the plate          .pg-card    the card
       .pg-chrome  the masthead       .pg-row     the list row
       .pg-head    the title block    .pg-field   label + field
       .pg-btn     the action         .pg-chip    the choice
       .pg-sec     the section        .pg-empty   the nothing-here

     Under them sits a BRIDGE: the app's own components (.card, .lf-chip,
     .log-search, .btn-line, .field, .mp-row) ARE these things, so they are
     restyled in place rather than forked. Where a component's STRUCTURE
     changed — the page header, the list row — the markup changed with it.
     Nothing on this page is drawn and then hidden.
     ══════════════════════════════════════════════════════════════════════ */

  /* ── the shell. Below Today the phone owns the whole screen: the app bar,
     the demo banner and the site footer are desktop furniture. `home-stack`
     additionally hands Today and Crew to the snap pager; `page-stack` is
     every other view, which simply scrolls. ── */
  body.page-stack .app-bar,body.page-stack .demobar,body.page-stack .ft{display:none}
  body.page-stack #appRoot>.page{padding:0;max-width:none}
  body.page-stack .view.on{padding:0;animation:none}
  body.page-stack{--hs-top:max(61px,calc(24px + env(safe-area-inset-top,0px)))}
  body.page-stack.solo .dock-wrap{display:none}   /* the recorder: nothing but the work */

  /* ── the plate. Plain paper carries the library and the account; Fuel's
     grid paper carries the working surfaces — anywhere you enter or read a
     record (recorder, planner, nutrition, log, progress). ── */
  body.page-stack #appRoot>.page{background:var(--paper);min-height:100dvh}
  body.page-stack.grid-plate #appRoot>.page{background-image:repeating-linear-gradient(180deg,transparent 0 18.8px,#E8EFF4 18.8px 19.4px),repeating-linear-gradient(90deg,transparent 0 18.8px,#E8EFF4 18.8px 19.4px)}
  .pg{--pg-grey:#B2B2B2;padding:0 32px calc(120px + env(safe-area-inset-bottom,0px))}
  body.solo .pg{padding-bottom:calc(36px + env(safe-area-inset-bottom,0px))}   /* no dock to clear */
  /* the instruments keep the page's gutter like everything else; the one
     thing that genuinely wants the full width is the CANVAS, so the canvas is
     the one thing that escapes it */
  .pg.bleed>.pg-body{margin-top:0}
  body.page-stack .pld-scroll,body.page-stack .plf-wk{margin-left:-32px;margin-right:-32px}
  /* a canvas that reaches the screen edge has no edges of its own to draw */
  body.page-stack .plf-wk{border-left:0;border-right:0;border-radius:0;box-shadow:none}

  /* ── the masthead. The weather block and THE avatar — one circle in the
     whole app. It scrolls with the page: these are documents, not slides. ── */
  /* v3.13 (audit T-2) — weather is Today's fact, and the page's masthead is gone with it:
     the avatar sits on the title row (.pg-head .pg-ava, below) and the page itself clears
     the status bar. #pageChrome stays display:none (02-shell) on every page now. */
  body.page-stack .pg{padding-top:var(--hs-top)}
  body.solo .pg{padding-top:0}   /* the recorder: the band clears the status bar itself */
  .pg-chrome{display:flex;justify-content:space-between;align-items:flex-start}
  .pg-chrome .hs-wx{--hs-ink:var(--ink);--hs-rule:#5400DB}
  .pg-ava{width:42px;height:42px;border-radius:50%;flex:0 0 auto;margin-top:2px;
    background:var(--hs-ava-bg,#0A0A0A);color:var(--hs-ava-ink,#fff);
    display:flex;align-items:center;justify-content:center;
    font-family:var(--courier);font-size:12px;font-weight:500;
    -webkit-tap-highlight-color:transparent;transition:background-color .3s var(--ease),color .3s var(--ease)}
  .pg-ava:active{transform:scale(.95)}

  /* ── the title block. Today's head, on every page: a 900 title, a mono
     slot on the right (Back, a page action, or the recorder's clock), and
     the rule under both. ── */
  /* v3.13 — one row: the title, the page's action, and THE avatar at the far right (36px on
     the title's line; Today's fixed chrome keeps the 42px circle). The rule "one avatar on
     screen, always the More door" holds — it just moved down a row. */
  .pg-head{display:flex;align-items:center;justify-content:space-between;gap:14px;min-height:36px}
  .pg-head .pg-h1{flex:1 1 auto}
  .pg-head .pg-ava{width:36px;height:36px;font-size:11px;margin-top:0}
  .pg-h1{font-family:var(--helv);font-weight:900;font-size:28px;letter-spacing:-.02em;line-height:.95;min-width:0;overflow-wrap:anywhere}
  .pg-side{flex:0 0 auto;padding:0;font-family:var(--courier);font-size:12px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;line-height:1;color:var(--ink);-webkit-tap-highlight-color:transparent}
  .pg-side.num{font-size:16px;letter-spacing:.02em;font-variant-numeric:tabular-nums}   /* the recorder's clock */
  .pg-rule{height:1.5px;background:var(--ink);margin-top:10px}
  .pg-body{margin-top:22px}
  .pg-intro{font-size:14px;line-height:1.55;color:var(--muted);margin:20px 0 0}

  /* ── the card. One definition: no border, a soft lift, bled 17px past the
     text gutter so its CONTENTS land on the page's own 32px line. ── */
  .pg-card{background:var(--paper);border:none;border-radius:var(--radius);box-shadow:0 2px 9px rgba(23,18,15,.10);
    margin:0 -17px 16px;padding:18px 19px 16px}
  .pg-card-h{display:flex;align-items:center;gap:10px;margin-bottom:2px}
  .pg-card-t{font-family:var(--helv);font-weight:900;font-size:15px;letter-spacing:-.01em;line-height:1.25;flex:1;min-width:0}
  .pg-card-t small{font-family:var(--courier);font-weight:500;font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--pg-grey)}
  .pg-card-f{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:30px}
  .pg-add,.pg-rm{font-family:var(--courier);font-size:12px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;padding:6px 0;-webkit-tap-highlight-color:transparent}
  .pg-add{color:#5400DB}
  .pg-rm{color:var(--accent)}
  .pg-add:active,.pg-rm:active{opacity:.6}
  .pg-tag{font-family:var(--courier);font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--ink);flex:1;min-width:0}
  /* the drag grip — square dots, 3×3, from the Push Day comp */
  .pg-grip{flex:0 0 auto;width:36px;height:36px;margin:-8px -9px -8px 0;display:flex;align-items:center;justify-content:flex-end;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}
  .pg-grip svg{width:14px;height:14px;display:block;fill:var(--ink)}

  /* ── the list row. Today's Train grammar minus the ordinal: these lists
     are searched and filtered, so a number would claim an order that isn't
     there (Arrick, 2026-08-21). ── */
  .pg-row{display:flex;align-items:baseline;padding:22px 0 0;line-height:1;font-family:var(--courier);font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.01em;color:var(--ink)}
  .pg-row-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left;padding-right:8px}
  .pg-act{flex:0 0 auto;padding:0 0 0 12px;font-family:var(--courier);font-size:13px;font-weight:700;text-transform:uppercase;color:var(--ink);-webkit-tap-highlight-color:transparent}
  .pg-act.mut{color:var(--muted)}
  .pg-act.del{color:var(--accent)}
  .pg-meta{font-family:var(--courier);font-size:9.5px;font-weight:500;letter-spacing:.06em;line-height:1.6;text-transform:uppercase;color:var(--muted);margin-top:8px;overflow:hidden;text-overflow:ellipsis}
  .pg-meta:not(:has(br)){white-space:nowrap}   /* one-line metas stay one line; a deliberate <br> wraps */
  .pg-hair{height:.8px;background:var(--line);margin-top:16px}
  /* v3.9.5 — the row target is sized by PADDING, never by min-height: how a flex
     BUTTON with align-items:baseline distributes min-height slack is engine lottery
     (iOS WebKit grew the first row of every More section; Chromium didn't). The 16px
     bottom padding and -16px margin cancel against .pg-hair's margin-top:16px, so the
     hairline sits exactly where the pre-3.9.3 div put it (16px under the text) while
     the tappable box is 22+13+16 ≥ 44px. Flex + baseline re-declared here on purpose —
     this rule must stand on its own, not lean on the class pairing. */
  button.pg-row{display:flex;align-items:baseline;-webkit-appearance:none;appearance:none;
    width:100%;background:none;border:0;text-align:left;cursor:pointer;
    padding:22px 0 16px;margin:0 0 -16px;-webkit-tap-highlight-color:transparent}
  button.pg-row:active{opacity:.5}
  button.pg-row .pg-act{pointer-events:none}
  /* the first row of a section: .pg-sec+.pg-row zeroes the top padding (the label
     already gave the air), which alone would shrink the box to 29px. Reach 9px up
     into the label's margin and 22px down past the hairline instead — the negative
     margins keep the visual identical and the box at 9+13+22 = 44px. */
  .pg-sec+button.pg-row{padding:9px 0 22px;margin:-9px 0 -22px}
  .pg-act.chev{color:var(--platinum);font-weight:400;font-size:15px}
  .pg-act.chev.del{color:var(--accent)}
  input.pg-in,select.pg-in,textarea.pg-in{width:100%;border-bottom:1.5px solid var(--ink);border-radius:0;background:transparent;
    font-family:var(--helv);font-weight:700;font-size:16px;letter-spacing:-.01em;color:var(--ink);
    padding:16px 0 6px;height:44px;min-height:0;line-height:22px}
  textarea.pg-in{height:auto;min-height:66px;padding-top:12px}
  .pg-in::placeholder{color:var(--pg-grey);font-weight:500}
  .pg-chip{display:inline-flex;align-items:center;min-height:36px;padding:9px 11px;border:1.5px solid var(--line);border-radius:var(--r-choice);background:transparent;color:var(--ink);
    font-family:var(--courier);font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;-webkit-tap-highlight-color:transparent}
  .pg-chip.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}

  /* ── the action. Today's button, unchanged: 47px, 1.5px, square, mono. ── */
  .pg-btn{width:100%;height:47px;display:flex;align-items:center;justify-content:center;gap:6px;border:1.5px solid currentColor;background:transparent;
    font-family:var(--courier);font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;border-radius:var(--r-action);white-space:nowrap;-webkit-tap-highlight-color:transparent}
  .pg-btn:active{transform:scale(.97)}
  .pg-btn.t-ink{color:var(--ink)}
  .pg-btn.t-purple{color:#5400DB}
  .pg-btn.t-red{color:var(--accent)}
  .pg-btn.t-black{color:#fff;background:#0A0A0A;border-color:#0A0A0A}
  .pg-btns{display:flex;flex-direction:column;gap:10.5px;margin-top:24px}
  .pg-btns+.pg-btns{margin-top:10.5px}   /* stacked action groups keep the row gap */
  .pg-btns.row{flex-direction:row}
  .pg-btns.row .pg-btn{flex:1}
  .pg-link{display:block;width:100%;text-align:center;padding:8px 0;margin-top:22px;font-family:var(--courier);font-size:11px;font-weight:500;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}

  /* ── the section, and the nothing-here ── */
  .pg-sec{font-family:var(--courier);font-size:10px;font-weight:700;letter-spacing:.13em;text-transform:uppercase;color:var(--muted);margin:34px 0 14px}
  .pg-sec:first-child{margin-top:0}
  .pg-sec+.pg-row{padding-top:0}   /* the section label already gave the row its air */
  .pg-empty{padding:26px 0 4px}
  .pg-empty .eh{font-family:var(--helv);font-weight:900;font-size:18px;letter-spacing:-.02em}
  .pg-empty p{font-size:14px;color:var(--muted);margin:8px 0 0;line-height:1.55}
  .pg-fine{font-family:var(--courier);font-size:9.5px;font-weight:500;letter-spacing:.05em;line-height:1.7;text-transform:uppercase;color:var(--muted);margin-top:28px}
  .pg-fine a{text-decoration:underline}

  /* ══ THE BRIDGE — the app's own components ARE these things ══
     Restyled in place, not re-implemented. A view that already reaches for
     the right component gets the new language for free. */
  body.page-stack .card{background:var(--paper);border:none;border-radius:var(--radius);box-shadow:0 2px 9px rgba(23,18,15,.10);margin:0 -17px 16px;padding:18px 19px 16px}
  /* v3.11.1 — the routine builder paints its cards straight into the view, with no .pg
     gutter to bleed past, so the −17px bleed put them at −17..407 and the page scrolled
     sideways (BACKLOG 2026-08-25). Sit them where every other page's card sits: 15..375. */
  body.page-stack #view-workouts>.card{margin-left:15px;margin-right:15px}
  /* …and a GROUP block's header — grip · "// Superset · alternate in this order" · rounds
     stepper · duplicate · remove — ran off the card at 360px. Let the controls drop to a
     second line, right-aligned, when the tag needs the first. (Audit, 2026-09-04.) */
  body.page-stack .blk-h{flex-wrap:wrap;justify-content:flex-end;row-gap:8px}
  body.page-stack .card-h{margin-bottom:12px}
  body.page-stack .ct{font-family:var(--courier);font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--ink)}
  body.page-stack .cmeta{font-family:var(--courier);font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}
  body.page-stack .sess{font-size:14px;line-height:1.55;color:var(--muted)}
  body.page-stack .lf-chip{min-height:36px;padding:9px 11px;border:1.5px solid var(--line);border-radius:var(--r-choice);font-size:10.5px;font-weight:700;background:transparent}
  body.page-stack .lf-chip.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
  body.page-stack .log-chips{gap:7px}
  body.page-stack .log-search{border:0;border-bottom:1.5px solid var(--ink);border-radius:0;background:transparent;padding:16px 0 6px;height:44px;min-height:0;font-weight:700;letter-spacing:-.01em;margin:0 0 6px}
  body.page-stack .log-search::placeholder{color:var(--pg-grey);font-weight:500}
  body.page-stack .row-btns{flex-direction:column;gap:10.5px;margin-top:24px}
  body.page-stack .btn-line{width:100%;height:47px;min-height:47px;display:flex;align-items:center;justify-content:center;padding:0 14px;border:1.5px solid currentColor;background:transparent;color:var(--ink);
    font-family:var(--courier);font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;border-radius:var(--r-action)}
  body.page-stack .btn-line:hover{background:transparent;color:var(--ink)}
  body.page-stack .btn-line.done{background:var(--volt);border-color:var(--volt);color:var(--ink)}
  body.page-stack .field>label{font-size:11px;font-weight:700;letter-spacing:.05em;color:var(--ink);margin-bottom:0}
  body.page-stack .field input,body.page-stack .field select,body.page-stack .field textarea{min-height:0;height:44px;padding:16px 0 6px;line-height:22px;font-family:var(--helv);font-weight:700;font-size:16px;letter-spacing:-.01em}
  body.page-stack .field textarea{height:auto;min-height:66px;padding-top:12px}
  body.page-stack .empty{padding:26px 0 4px}
  body.page-stack .empty .eh{font-family:var(--helv);font-weight:900;font-size:18px;letter-spacing:-.02em}
  body.page-stack .mp-eye{font-size:10px;font-weight:700;letter-spacing:.13em;padding:0;border-bottom:none;color:var(--muted)}
  body.page-stack .mp-row{padding:22px 0 0;min-height:0;border-bottom:none;font-family:var(--courier);font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.01em;align-items:baseline}
  body.page-stack .mp-row:active{background:transparent;opacity:.6}

  /* segmented controls and view switchers are all choices */
  body.page-stack .seg2,body.page-stack .seg2 button,body.page-stack .pv-nav button,
  body.page-stack .pld-modeseg,body.page-stack .pld-modeseg button,
  body.page-stack .pld-create{border-radius:var(--r-choice)}
  /* the desktop rail's 212px controls become the page's full-width pair */
  body.page-stack .pld-rail{gap:10.5px;margin-bottom:20px}
  body.page-stack .pld-modeseg{height:47px;border-width:1.5px}
  body.page-stack .pld-modeseg button{flex:1;padding:0;font-size:11.5px;letter-spacing:.06em}
  body.page-stack .pld-create{height:47px;box-shadow:none;
    font-family:var(--courier);font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}
  body.page-stack .seg2 button,body.page-stack .pv-nav .pv-today{font-weight:700}
  /* the planner's canvas was its own scroller inside a fixed-height box; on the
     phone page the PAGE scrolls, so the canvas simply takes the height it needs
     and the sticky toolbar keeps working above it */
  body.page-stack .pld-scroll{height:auto;min-height:0;overflow-y:visible}
  /* the ledger keeps its shape — badge, title, meta, time — in the page's type */
  body.page-stack .lg2{padding:16px 2px;border-bottom-width:.8px}
  body.page-stack .lg2-main b{font-family:var(--courier);font-size:12.5px;font-weight:700;text-transform:uppercase;letter-spacing:.01em}
  body.page-stack .lg2-main small{font-family:var(--courier);font-size:9.5px;font-weight:500;letter-spacing:.06em;text-transform:uppercase}

  /* ══ THE RECORDER — everything above is shared; only the set table is its
     own. `.sr-*` is now nine selectors, not sixty. ══ */
  .sr-mem{border-top:1px solid var(--line);margin-top:22px;padding-top:16px}
  .sr-mem:first-of-type{border-top:none;margin-top:10px;padding-top:0}
  .sr-mem .pg-card-f{margin-top:20px}
  .pg-card-f.grp{margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
  /* the set table itself — .sr-th / .sr-tr / .sr-in / .sr-chk / .sr-step — moved to
     css/17-setrow.css in v3.12: it is the same row on every surface, styled once. */

  /* ══ THE GYM CLOCK · v3.10 — the band under the head. Sticky at the top edge
     once the chrome scrolls away; escapes the page gutter the way the planner's
     canvases do. Ground = state: ink at rest, VOLT in work. ══ */
  .ck{position:sticky;top:0;z-index:20;display:block;width:calc(100% + 64px);margin:0 -32px 0;padding:10px 32px 12px;
    background:var(--ink);color:#fff;text-align:left;font-variant-numeric:tabular-nums;-webkit-tap-highlight-color:transparent;transition:background .25s ease,color .25s ease}
  /* v3.13 — THE BAND IS THE MASTHEAD (audit T-2 · Arrick's "title above the timer, all of it
     so low"). The recorder draws no head: the band starts at the top of the page, clears the
     status bar as its resting state, and carries the session's name and the ••• on its first
     line. Scrolled (.pinned), the name drops to the mono voice so the pinned band stays short. */
  body.solo .ck{padding-top:max(52px,calc(12px + env(safe-area-inset-top,0px)))}
  .ck-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:0 0 10px;min-height:34px}
  .ck-nm{font-family:var(--helv);font-weight:900;font-size:22px;letter-spacing:-.02em;line-height:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-transform:none}
  .ck-more{flex:0 0 auto;width:34px;height:34px;margin-right:-8px;display:inline-flex;align-items:center;justify-content:center;color:inherit;-webkit-tap-highlight-color:transparent}
  .ck-more::after{content:"";position:absolute;inset:-8px}.ck-more{position:relative}
  .ck-more svg{width:20px;height:20px;fill:currentColor}
  .ck.pinned .ck-bar{min-height:22px;margin-bottom:6px}
  .ck.pinned .ck-nm{font-family:var(--courier);font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;opacity:.75}
  .ck.pinned .ck-more{width:28px;height:22px}
  /* paused: ink ground, dimmed digits, the corner says resume */
  .ck.paused .ck-big{opacity:.55}
  .ck{transition:padding-top .18s ease,background .25s ease,color .25s ease}
  .ck-top{display:flex;justify-content:space-between;align-items:baseline;gap:12px;font-family:var(--courier);font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase}
  .ck-state{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ck-tot{flex:0 0 auto;opacity:.72}
  .ck-tot i{font-style:normal;font-size:15px;letter-spacing:.02em;margin-left:8px}
  .ck-tot{display:inline-flex;align-items:center;gap:0}
  /* v3.11 — the speaker glyph: mute only, never starts or stops anything; a 44px target on a 16px glyph */
  .ck-mute{position:relative;width:16px;height:16px;margin-left:10px;display:inline-flex;align-items:center;justify-content:center;color:inherit;opacity:1;-webkit-tap-highlight-color:transparent}
  .ck-mute::after{content:"";position:absolute;top:-14px;left:-14px;right:-14px;bottom:-14px}
  .ck-mute svg{width:16px;height:16px;fill:currentColor;stroke:none}
  .ck-mute svg .w{fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round}
  .ck-mute.off{opacity:.5}
  /* v3.11 — the target chip beside the label, and the rail that drains with a countdown */
  .ck-row{display:flex;align-items:baseline;gap:14px}
  /* v3.13 — the corner: the hint sits on the digits' baseline, right-aligned; running, it is
     the pause button (ink on the volt band), with a reach beyond its letters */
  .ck-row .ck-hint{margin:0 -8px 0 auto;padding:8px 8px 8px 16px;display:inline-block;position:relative;white-space:nowrap}
  .ck.work .ck-hint{color:var(--ink)} .ck.work.go .ck-hint{color:var(--volt)}
  .ck-chip{display:inline-block;padding:3px 7px;border:1px solid currentColor;opacity:.75;font-family:var(--courier);font-size:11px;font-weight:700;letter-spacing:.06em;position:relative;top:-8px}   /* the target, beside the digits — "of 1:30" */
  .ck-chip::before{content:"/ ";opacity:.7}
  .ck.go{transition:none}   /* the GO beat snaps to ink; the release eases to volt */
  .ck-rail{position:absolute;left:0;right:0;bottom:0;height:4px;background:rgba(255,255,255,.18)}
  .ck-rail i{display:block;height:100%;background:#fff;transition:width .9s linear}
  .ck.work .ck-rail{background:rgba(23,18,15,.15)}.ck.work .ck-rail i{background:var(--ink)}
  .ck.timed{padding-bottom:16px}
  .ck.work.go{background:var(--ink);color:var(--volt)}   /* the GO beat: ink with volt digits for a second, then the band is volt and running */
  .ck.work.go .ck-rail{background:rgba(255,255,255,.18)}.ck.work.go .ck-rail i{background:var(--volt)}
  @media(prefers-reduced-motion:reduce){.ck-rail i{transition:none}}
  .ck-big{font-family:var(--courier);font-weight:800;font-size:56px;line-height:1;letter-spacing:-.02em;margin-top:6px}
  .ck-hint{display:block;margin-top:6px;font-family:var(--courier);font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--volt)}
  .ck.ready .ck-big{opacity:.35}
  .ck.work{background:var(--volt);color:var(--ink)}
  .ck.ck-static{cursor:default}
  .ck.ck-static .ck-big{opacity:.35}
  .ck+.pg-body{margin-top:18px}
  /* 3 · 2 · 1 — the one piece of theatre; it is also the tap that unlocks sound and the wake lock */
  .ck-count{position:fixed;inset:0;z-index:200;background:var(--ink);display:flex;align-items:center;justify-content:center}
  .ck-count b{font-family:var(--courier);font-weight:800;font-size:min(46vw,200px);line-height:1;color:var(--volt)}
  .ck-count small{position:absolute;left:0;right:0;bottom:calc(28px + env(safe-area-inset-bottom,0px));text-align:center;font-family:var(--courier);font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:#fff;opacity:.7}

  /* ── the dock: Crew replaced More in v2.21.0 and went live in v2.21.1; on views
     without a tab of their own, the pill bows out instead of lying ── */
  .dock-ind.off{opacity:0}
}
