/* GENERATED by tools/loginpage.js from src/shell-top.html — do not edit.
   Edit the stylesheet in src/shell-top.html and run `npm run build`. */

:root{
  /* ══ ROULEUR · "indigo & mint" ══
     Surfaces are indigo — a cool, deep, slightly blue-violet neutral that reads
     as instrument glass rather than office grey. One accent, mint, and it never
     encodes data: the zone scale owns every data hue, which is exactly what
     frees mint to mean "interactive" and nothing else.

     Every value below is checked by `node tools/palette.js`, which runs as part
     of `npm test`. Do not hand-tune a colour without re-running it.

     Light-theme mint is deep (#0B7D68), not pastel: a pastel mint cannot clear
     3:1 on white, so "the accent" would have failed the one job it has. Dark
     theme gets the real thing (#5EEAD4) because it sits on near-black. */
  --bg:#F4F5FC; --surface:#FFFFFF; --raise:#EDEFF9; --sunk:#E4E7F4;
  --edge:#D5D9EC; --edge2:#A8AECD; --edgeSoft:#E7E9F5;
  --paper:#12142B; --muted:#4A4F70; --dim:#666C8C;
  --acc:#0B7D68; --accHi:#08604F; --accInk:#FFFFFF; --accSoft:#DDF5EF; --accLine:#7FD3C0;
  --ink:#12142B; --inkHi:#000000;
  /* Zone scale. Unchanged by the rebrand, and deliberately so: these seven are
     validated data colours (gold→orange→red is a fixed convention and z3↔z4
     collapsing under deuteranopia was a real defect once). Identity moved; the
     instrument's dials did not. z1 is low-chroma — recovery should read
     recessive — and z3/z4 keep text-safe twins, because the fill steps are too
     light to colour small text. */
  --z1:#5E7FA6; --z2:#137A4C; --z3:#C8A21F; --z4:#A63F07; --z5:#8A101C; --z6:#B02A80; --z7:#553099;
  --z3t:#7A6408; --z4t:#A63F07;
  --str:#5E6488; --okSoft:#DEF3E9; --okLine:#8FCDB2;
  /* "This one is done." A completed session's box carries this as its FILL, so
     a finished week reads at a glance without opening anything. It is
     deliberately low-chroma: a wall of completed sessions should be calm, and
     the eye should still be able to find the one that is not done.
     It is NOT the accent (mint means "interactive" everywhere and never encodes
     data) and it is NOT a zone colour (those seven are validated data colours).
     It is checked in test/smoke.js: body text stays ≥7:1 on it, and it holds
     ΔE ≥ 15 against every zone and against the accent under protanopia and
     deuteranopia, so "done" can never be confused with an intensity. */
  --done:#E4F1E9; --doneEdge:#A5CDB6;
  --bodybg:#F4F5FC;
  --sidebg:#E3E5F2; --topbg:rgba(244,245,252,.88);
  --hover:rgba(18,20,43,.05); --profbg:linear-gradient(180deg,transparent,rgba(18,20,43,.045));
  --sh1:0 1px 2px rgba(18,20,43,.06); --sh2:0 10px 30px rgba(18,20,43,.11);
  --shUp:0 -6px 26px rgba(18,20,43,.15); --grid:rgba(18,20,43,.035);
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,"DejaVu Sans Mono",monospace;
  --sans:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --r:12px;      /* cards */
  --r2:8px;      /* controls */
  /* Two widths, deliberately separate. --rail is the gutter the content keeps
     clear; --railw is how wide the rail is drawn right now. Expanding the rail
     changes only the second, so the page underneath never moves — it dims. */
  --rail:74px;
  --railw:74px;
  --railx:212px; /* the rail with its names showing */
  --ctxw:318px;  /* the context column */
}
html[data-theme=dark]{
  --bg:#0E1020; --surface:#171A2E; --raise:#212540; --sunk:#0A0C18;
  --edge:#2B2F4E; --edge2:#454B76; --edgeSoft:#232742;
  --paper:#E7E9F7; --muted:#A6ACCE; --dim:#868DB2;
  --acc:#5EEAD4; --accHi:#9FF5E6; --accInk:#04221C; --accSoft:#0F3129; --accLine:#1D6355;
  --ink:#E7E9F7; --inkHi:#FFFFFF;
  --z1:#6C86A6; --z2:#2FA76B; --z3:#D9B23C; --z4:#C55A18; --z5:#EE6257; --z6:#D060A8; --z7:#9B7BE8;
  --z3t:#D9B23C; --z4t:#EE8A52;
  --str:#8A90B4; --okSoft:#0F2A20; --okLine:#2C6B4C;
  --done:#172C23; --doneEdge:#2E5B45;
  --bodybg:#0E1020;
  --sidebg:#070813; --topbg:rgba(14,16,32,.88);
  --hover:rgba(255,255,255,.06); --profbg:linear-gradient(180deg,transparent,rgba(0,0,0,.28));
  --sh1:none; --sh2:0 10px 34px rgba(0,0,0,.55); --shUp:0 -10px 32px rgba(0,0,0,.62);
  --grid:rgba(255,255,255,.04);
}
/* The rail is the DARKEST SURFACE IN ITS OWN THEME — not black in both, which
   is what it used to be. A rail that stays near-black on a light page is a slab
   of night in the corner of a daylit app, and it is the one part of the chrome
   you look at all day. What actually gave it its identity is the relationship,
   not the hex: it is chrome rather than content, so it sits a step below the
   page and a step further below a card. That relationship is kept in both
   themes; only the values follow the theme now.

   These are SCOPED VARIABLE OVERRIDES, so every control inside the rail just
   works without knowing it is in a rail. Style rail content through them, never
   with a literal colour. `--sidebg` is the wall they are read against and
   tools/palette.js checks them against it — which is why paper, muted and acc
   are restated here even where they match the page. A rail that inherited them
   silently would be a rail the checker skips. */
.side{
  --paper:#12142B; --ink:#12142B; --inkHi:#000000; --muted:#4A4F70; --dim:#666C8C;
  --edge:#C7CBE2; --edge2:#A8AECD; --edgeSoft:#D3D7EA;
  --surface:#EDEFF9; --raise:#F6F7FC; --sunk:#D6DAEC;
  --hover:rgba(18,20,43,.06);
  --acc:#0B7D68; --accHi:#08604F; --accInk:#FFFFFF; --accSoft:#DDF5EF; --accLine:#7FD3C0;
  --sh1:none; --sh2:none;
  color:var(--paper);
}
/* Dark theme: the values the rail carried in both themes until 3 Aug 2026. The
   rail is still darker than the page (#070813 against #0E1020), so the step
   down that makes it read as chrome survives the change of yardstick. */
html[data-theme=dark] .side{
  --paper:#E7E9F7; --ink:#E7E9F7; --inkHi:#FFFFFF; --muted:#A6ACCE; --dim:#868DB2;
  --edge:#1E2238; --edge2:#343A5C; --edgeSoft:#161A2C;
  --surface:#0F1222; --raise:#191D33; --sunk:#080A14;
  --hover:rgba(255,255,255,.07);
  --acc:#5EEAD4; --accHi:#9FF5E6; --accInk:#04221C; --accSoft:#0F3129; --accLine:#1D6355;
  --okSoft:#0F2A20; --okLine:#2C6B4C; --z2:#2FA76B; --z4t:#EE8A52;
  --sh1:none; --sh2:none;
}
*{box-sizing:border-box;margin:0;padding:0}
html{background:var(--bg);scrollbar-color:var(--edge2) transparent}
body{color:var(--paper);font-family:var(--sans);font-size:15px;line-height:1.5;background:var(--bodybg);min-height:100vh}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}
.num{font-variant-numeric:tabular-nums}
.eyebrow{font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
button,select,input,textarea{font-family:inherit;font-size:14px;color:var(--paper);background:var(--surface);
  border:1px solid var(--edge);border-radius:var(--r2);padding:8px 11px;
  transition:background .12s,border-color .12s,box-shadow .12s,color .12s}
/* The reduced-motion query below covers .side/.body/.ctx/.raildim; it missed
   this one, and the gap was not cosmetic — it made the screenshot harness
   flaky. #srch, #menu (.burger) and #whoBtn are part of the STATIC shell
   (this file, parsed before the app's one inline script block runs), so on a
   dark-theme capture they can paint once under :root's LIGHT defaults and
   only pick up `data-theme=dark` a beat later, once applyTheme() runs — and
   this transition then cross-fades the flip over 120ms of real frame time,
   which a --virtual-time-budget does not bind. `--screenshot` sometimes
   lands mid-fade. Confirmed by sampling a flaky capture of #srch: its fill
   was an exact (to <1 unit per channel) 70.6% linear interpolation between
   --sunk light (#E4E7F4) and --sunk dark (#0A0C18) — a transition frame, not
   antialiasing noise. Nothing painted by render() hits this, because JS
   never creates a control before the theme is already set. */
@media (prefers-reduced-motion:reduce){button,select,input,textarea{transition:none}}
button{cursor:pointer;font-weight:550}
button:hover{background:var(--raise);border-color:var(--edge2)}
button:active{transform:translateY(.5px)}
select:hover,input:hover,textarea:hover{border-color:var(--edge2)}
:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.btn-p{background:var(--ink);border-color:var(--ink);color:var(--surface);font-weight:650}
html[data-theme=dark] .btn-p{color:var(--bg)}
.btn-p:hover{background:var(--inkHi);border-color:var(--inkHi)}
.btn-a{background:var(--acc);border-color:var(--acc);color:var(--accInk);font-weight:650}
.btn-a:hover{background:var(--accHi);border-color:var(--accHi);color:var(--accInk)}
.btn-s{padding:5px 10px;font-size:12.5px;border-radius:7px}
/* Destructive. Red, and it says so before you press it — deleting a session is
   the one button on the detail panel you cannot mean by accident. --z5 is the
   deepest red in the scale; it is used here as CHROME, not as data, which is
   why it is allowed where the accent would not be. */
.btn-d{background:transparent;border-color:var(--z5);color:var(--z5);font-weight:650}
.btn-d:hover{background:var(--z5);border-color:var(--z5);color:#fff}
html[data-theme=dark] .btn-d:hover{color:var(--bg)}
/* Strava's own orange (#FC4C02), not the app accent — this button's whole job is
   to be recognised at a glance as the real Strava connect action, which the mint
   accent cannot do. Chrome only, same reasoning as --done and --z5 above: a brand
   colour used as identity, never as data. No logomark — the sponsor-strip pipeline
   in tools/sponsors.js exists precisely because a hand-drawn approximation of a
   trademarked mark is worse than none, and that holds here too. */
.btn-strava{background:#FC4C02;border-color:#FC4C02;color:#fff;font-weight:700;
  letter-spacing:.2px;border-radius:999px;padding:9px 18px}
.btn-strava:hover{background:#E34402;border-color:#E34402;color:#fff}
.btn-strava:active{background:#C93C02;border-color:#C93C02}
.btn-q{background:transparent;border-color:transparent;color:var(--muted)}
.btn-q:hover{background:var(--hover);border-color:transparent;color:var(--paper)}

/* ============ SHELL ============
   Rail (icons only) · header · content · context column. The rail is a fixed
   74px so the eye never has to re-find navigation, and every section it points
   at declares its own sub-views, which appear in the header strip instead of
   as twenty entries in one list. */
.shell{display:flex;min-height:100vh}
.side{width:var(--railw);flex:none;background:var(--sidebg);border-right:1px solid var(--edge);
  position:fixed;inset:0 auto 0 0;z-index:60;display:flex;flex-direction:column;
  transition:transform .2s ease,width .16s ease,box-shadow .16s ease}
.side.hide{transform:translateX(-100%)}
.body{flex:1;min-width:0;margin-left:var(--rail);transition:margin .2s ease}
.body.wide{margin-left:0}
/* The page behind an expanded rail. Not a scrim you can click — it is there to
   push the page back a step visually while the names are over it, so it takes
   no pointer events and sits under the rail and over everything else. */
.raildim{position:fixed;inset:0;z-index:59;background:rgba(7,8,19,.3);opacity:0;
  pointer-events:none;transition:opacity .16s ease}
html[data-theme=dark] .raildim{background:rgba(0,0,0,.45)}
@media (prefers-reduced-motion:reduce){.side,.body,.ctx,.raildim{transition:none}}
/* --- the mark --- */
/* Fixed height for the same reason the buttons have one: expanding hides the
   username line and turns the stack into a row, which used to make the whole
   nav below it slide up by about thirty pixels — the buttons could be pinned
   perfectly and the rail would still jump, because everything sits under this. */
.brand{padding:14px 6px 11px;text-align:center;border-bottom:1px solid var(--edge);flex:none;
  min-height:96px;box-sizing:border-box}
.brand .mk{width:38px;height:38px;margin:0 auto;border-radius:11px;background:var(--accSoft);
  border:1px solid var(--accLine);color:var(--acc);display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:19px;font-weight:800;letter-spacing:-.05em;cursor:pointer}
.brand .mk:hover{background:var(--acc);color:var(--accInk);border-color:var(--acc)}
/* THE ONE WORDMARK. It used to be three: muted grey and mono in the rail, split
   two-tone (ROU in body ink, LEUR in mint) in the context column, and solid mint
   on the sign-in scene. The sign-in scene is the tell — it is drawn from
   13a-lockscene.js, copied verbatim into the online login page, so it is the one
   place this mark had to be right on its own; that makes it the intended
   treatment, not the accident. `.wordmark` is the single rule for identity —
   family, weight, letter-spacing, case, colour — everywhere the word ROULEUR is
   set as a mark rather than as prose. Only size is context-specific, on the
   selectors below. */
.wordmark{font-family:var(--mono);font-weight:800;letter-spacing:.18em;
  text-transform:uppercase;color:var(--acc)}
.brand h1.wordmark{font-size:8.5px;margin-top:8px}
/* Whose plan this is. It was 7.5px UPPERCASE MONO on one nowrap line, so an
   ordinary two-part name came out as "FIRSTNAME SURN…" — cut mid-word, in the one
   place that is on screen every second the app is open, and cut at BOTH widths
   because the expanded rule pads the content back to the collapsed width so the
   logo cannot slide sideways.
   Sentence case in the text face fits far more per pixel than spaced uppercase,
   and two clamped lines hold any ordinary name whole. The height is FIXED at two
   lines whether the name takes one or two, which is what keeps this block
   identical in both rail states — the brand not re-laying-out is the reason the
   nav under it stays still, and it is worth more than a tidy-looking gap. */
.brand .who{font-family:var(--sans);font-size:10px;line-height:1.25;letter-spacing:.005em;
  color:var(--dim);margin-top:5px;height:25px;overflow:hidden;word-break:break-word;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.brand .who i{font-style:normal;opacity:.55;font-size:9px}
/* --- icon nav --- */
nav.nav{padding:8px 6px;flex:1;overflow-y:auto;overflow-x:hidden;scrollbar-width:none}
nav.nav::-webkit-scrollbar{width:0}
nav.nav .grp{height:1px;background:var(--edge);margin:8px 8px}
/* THE ROW HEIGHT AND THE ICON POSITION ARE FIXED IN EVERY STATE.
   This used to be a column (icon over label, ~43px) that became a row (~34px)
   when the rail expanded — so brushing the rail with the mouse shrank all eight
   buttons and the whole rail jumped up about seventy pixels. A navigation bar
   that moves as you reach for it is a navigation bar you have to aim at twice.

   So: the button is a fixed-height row in BOTH states, and the icon sits in a
   lead block exactly as wide as the collapsed rail's inner width. The icon's
   centre is therefore at the same x AND the same y whether the rail is 74px or
   246px wide — expanding only extends the NAME horizontally, out from behind
   the icon, over the page. Nothing moves, in either axis. The small mono label
   stays under the icon when collapsed (absolutely positioned, so it costs the
   row no height) and becomes the readable name on the right when open. */
nav.nav button{display:flex;flex-direction:row;align-items:center;gap:0;width:100%;background:none;
  border:1px solid transparent;border-radius:10px;padding:0;min-height:46px;color:var(--muted);
  font-weight:600;position:relative}
nav.nav button:hover{background:var(--hover);color:var(--paper);border-color:transparent}
nav.nav button.on{background:var(--accSoft);color:var(--acc);border-color:var(--accLine)}
/* --rail minus nav's own 6px side padding: the lead block is the collapsed rail */
nav.nav button .ic{font-size:16px;line-height:1;opacity:.95;flex:none;text-align:center;
  width:calc(var(--rail) - 13px)}
nav.nav button .lb{position:absolute;left:0;right:0;bottom:5px;text-align:center;
  font-size:8.5px;font-family:var(--mono);letter-spacing:.04em;font-weight:700;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
nav.nav button .tail{position:absolute;top:5px;right:7px;font-family:var(--mono);font-size:8px;
  font-weight:800;color:var(--dim)}
nav.nav button.on .tail{color:var(--acc)}
nav.nav button.alert .tail{color:var(--z4t)}
/* --- rail with names ---
   Three ways the rail shows its names, and they share every layout rule:
     html[data-rail=labels]  pinned open by ☰
     .side.hover             a mouse is on it (set in JS, so a tap cannot stick)
     .side.show              the mobile off-canvas panel, which has the room anyway
   Expanding only changes --railw, so the rail grows OVER the page rather than
   pushing it: nothing reflows, nothing you were reading moves, and the page
   behind it dims instead. */
html[data-rail=labels]{--railw:var(--railx)}
.side.hover{width:var(--railx)}
html[data-rail=labels] .side,.side.hover{box-shadow:var(--sh2)}
html[data-rail=labels] .raildim,.side.hover~.raildim{opacity:1}
.side.hide~.raildim{opacity:0}
/* below the phone breakpoint the rail is off-canvas with its own scrim — a
   second dim on top of that one would just make the page unreadable */
@media(max-width:700px){ .raildim{display:none} }
/* Expanding changes NOTHING about the button box or the icon block — no
   flex-direction, no padding, no height, no icon width. The label simply stops
   being the small caption underneath and becomes the name on the right. That
   is the whole difference, and it is why nothing shifts. */
html[data-rail=labels] nav.nav button .lb,.side.show nav.nav button .lb,.side.hover nav.nav button .lb{
  position:static;flex:1;text-align:left;padding-right:8px;
  font-family:var(--sans);font-size:13px;letter-spacing:-.005em;font-weight:600}
html[data-rail=labels] nav.nav button .tail,.side.show nav.nav button .tail,.side.hover nav.nav button .tail{
  position:static;margin-left:auto;margin-right:11px;top:auto;right:auto;font-size:9.5px}
/* THE BRAND DOES NOT RE-LAY-OUT AT ALL. It used to become a horizontal row with
   the username hidden, which made it shorter — so the buttons could be pinned
   perfectly and the whole nav below still slid up, because everything sits
   under this block. Keeping it exactly as it is collapsed is both the simplest
   fix and the only one that is provably zero-shift: there is nothing left to
   change. The mark stays centred in the 74px gutter and the wordmark stays
   under it, which is legible at either width. The right pad below is what keeps
   it centred over the GUTTER rather than over the widened rail — without it the
   logo slides sideways as the names come in, which is the same complaint in the
   other axis. */
html[data-rail=labels] .brand,.side.show .brand,.side.hover .brand{
  padding-right:calc(6px + var(--railx) - var(--rail))}
html[data-rail=labels] .railfoot,.side.show .railfoot,.side.hover .railfoot{
  flex-direction:row;flex-wrap:wrap;gap:5px}
html[data-rail=labels] .railfoot button,.side.show .railfoot button,.side.hover .railfoot button{
  width:auto;flex:1;padding:7px 8px}
html[data-rail=labels] .railfoot .two,.side.show .railfoot .two,.side.hover .railfoot .two{flex:1}
html[data-rail=labels] .railpop,.side.hover~.railpop{left:calc(var(--railx) + 8px)}
/* --- rail foot + its popover --- */
.railfoot{padding:6px 6px 9px;border-top:1px solid var(--edge);display:flex;flex-direction:column;gap:4px;flex:none}
.railfoot button{width:100%;padding:6px 2px;border-radius:9px;background:none;border:1px solid transparent;
  color:var(--muted);font-size:13px;line-height:1.1}
.railfoot button:hover:not([disabled]){background:var(--hover);color:var(--paper);border-color:transparent}
.railfoot button[disabled]{opacity:.32;cursor:default}
.railfoot .two{display:flex;gap:4px}
.railfoot #cmdBtn{color:var(--acc);border-color:var(--edge)}
.railfoot button.warn{color:var(--z4t)}
.railpop{position:fixed;left:calc(var(--rail) + 8px);bottom:12px;z-index:75;width:236px;
  background:var(--surface);border:1px solid var(--edge);border-radius:var(--r);box-shadow:var(--sh2);
  padding:12px}
.railpop .footgrp{margin-bottom:11px}
.railpop .footgrp:last-of-type{margin-bottom:6px}
.footlbl{display:block;font-family:var(--mono);font-size:8.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--dim);font-weight:750;margin-bottom:6px}
.railpop .footgrp button{margin:0 5px 5px 0}
.footchips{display:flex;gap:5px;flex-wrap:wrap}
.scrim{position:fixed;inset:0;background:rgba(7,8,19,.45);z-index:55;display:none}
.scrim.on{display:block}

/* ============ HEADER ============
   Top bar, section sub-nav and the export/filter bar stick to the top as ONE
   block. Sticking them separately meant every row below had to know the exact
   height of the rows above it, and the panes strip was already wrong by 47px
   whenever the filter bar was hidden. */
.hdr{position:sticky;top:0;z-index:45;background:var(--topbg);backdrop-filter:blur(12px);
  border-bottom:1px solid var(--edge)}
.topbar{display:flex;align-items:center;gap:12px;padding:9px 20px}
.burger{width:36px;height:36px;padding:0;display:flex;align-items:center;justify-content:center;
  font-size:15px;border-radius:9px;flex:none}
.crumb{font-size:17px;font-weight:800;letter-spacing:-.03em;flex:none}
.crumb small{display:block;font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--dim);font-weight:700;margin-top:1px}
.topacts{margin-left:auto;display:flex;gap:7px;align-items:center;flex-wrap:wrap}
.subnav{display:flex;gap:2px;padding:0 20px 8px;flex-wrap:wrap;align-items:center}
.subnav:empty{display:none}
.subnav button{background:transparent;border:1px solid transparent;border-radius:999px;padding:5px 13px;
  font-size:12.5px;font-weight:650;color:var(--muted)}
.subnav button:hover{background:var(--hover);color:var(--paper);border-color:transparent}
.subnav button.on{background:var(--acc);border-color:var(--acc);color:var(--accInk);font-weight:750}
.subnav button .tail{font-family:var(--mono);font-size:9.5px;margin-left:6px;opacity:.8;font-weight:700}
.bar{border-top:1px solid var(--edgeSoft)}
.bar .in{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:9px 20px;max-width:none}
.bar select{background:var(--surface);font-weight:600}
.bar .sep{width:1px;align-self:stretch;background:var(--edge);margin:0 4px}
#selAll,#selNone{color:var(--muted)}
#selAll:hover,#selNone:hover{color:var(--acc);border-color:var(--acc)}
.chip{font-family:var(--mono);font-size:10px;letter-spacing:.07em;text-transform:uppercase;padding:4px 9px;
  border:1px solid var(--edge);border-radius:999px;color:var(--muted);background:var(--surface);font-weight:600}
.chip.ok{color:var(--z2);border-color:var(--okLine);background:var(--okSoft)}
.wrap{max-width:1120px;margin:0 auto;padding:0 20px 140px}
/* --- slim header KPIs --- */
.kpis{display:flex;gap:0;align-items:stretch}
.kpi-i{padding:2px 13px;border-left:1px solid var(--edge)}
.kpi-i:first-child{border-left:0}
/* A figure derived from placeholder anchors. Dimmed rather than hidden: the
   number is still what the plan is using, and hiding it would make the app look
   like it had no opinion when in fact it has a badly founded one. */
.kpi-i.est b{opacity:.55}
.kpi-i u{display:block;text-decoration:none;font-family:var(--mono);font-size:8.5px;letter-spacing:.11em;
  text-transform:uppercase;color:var(--dim);font-weight:700}
.kpi-i b{font-family:var(--mono);font-size:15px;font-weight:750;font-variant-numeric:tabular-nums;letter-spacing:-.02em}
@media(max-width:1100px){ .kpis{display:none} }

/* ============ CONTEXT COLUMN ============
   The three questions asked on every single visit — what am I doing, am I fit
   to do it, when can I do it — live here permanently instead of being a view
   you have to navigate to. */
/* It must fit. `overflow-y:auto` is the safety net for a very short window, and
   `overscroll-behavior:contain` stops a wheel over the column from carrying on
   into the page underneath once it reaches the end — which is what made
   scrolling here feel wrong. The bottom padding is small on purpose: a 90px
   dead zone was inventing a scrollbar all by itself. */
.ctx{position:fixed;top:0;right:0;bottom:0;width:var(--ctxw);z-index:40;background:var(--bg);
  border-left:1px solid var(--edge);overflow-y:auto;overscroll-behavior:contain;
  padding:12px 12px 14px;display:none;scrollbar-width:thin}
body.hasctx .ctx{display:block}
body.hasctx .body{margin-right:var(--ctxw)}
.ctxh{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.ctxh .wordmark{font-size:13px}
.ctxh .dt{margin-left:auto;font-family:var(--mono);font-size:9.5px;color:var(--dim);font-weight:700;
  letter-spacing:.08em;text-transform:uppercase}
.ccard{background:var(--surface);border:1px solid var(--edgeSoft);border-radius:var(--r);padding:10px 11px;
  margin-bottom:7px;box-shadow:var(--sh1)}
.ccard .ct{font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);font-weight:750;margin-bottom:5px;display:flex;align-items:center;gap:6px}
.ccard .ct .rt{margin-left:auto;color:var(--muted)}
.ccard .cv{font-size:14px;line-height:1.2}
.ccard .cv b{font-family:var(--mono);font-size:20px;font-weight:780;letter-spacing:-.03em}
.ccard .cs{font-size:11.5px;color:var(--muted);line-height:1.4;margin-top:3px}
.ccard.good{border-left:3px solid var(--z2)}
.ccard.warn{border-left:3px solid var(--z3)}
.ccard.bad{border-left:3px solid var(--z5)}
/* Today leads the column, so it is allowed to be the biggest thing in it. */
.ccard.big{padding:12px 13px}
.ccard.big .ct{font-size:9.5px;color:var(--muted);margin-bottom:8px}
/* A session row says WHAT, WHEN and whether it is done. It used to be a name
   and a duration in 11px type, which is how a column that is on screen all day
   still made you open the week to find out when to be on the bike. */
.ccard .crow{display:flex;align-items:center;gap:9px;padding:7px 0;
  border-top:1px solid var(--edgeSoft);font-size:12px;width:100%;background:none;
  border-left:0;border-right:0;border-bottom:0;color:var(--tx);text-align:left;cursor:pointer}
.ccard .crow:first-of-type{border-top:0}
.ccard .crow:hover .nm{color:var(--acc)}
.ccard .crow .zs{width:3px;align-self:stretch;min-height:30px;border-radius:2px;flex:none}
.ccard .crow .cb{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.ccard .crow .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:650;
  font-size:13px;line-height:1.25}
.ccard .crow .sub{font-family:var(--mono);font-size:10px;color:var(--muted);font-weight:650;
  letter-spacing:.02em}
.ccard .crow .mn{font-family:var(--mono);font-size:10.5px;color:var(--muted);font-weight:650}
.ccard .crow .tick{color:var(--z2);font-weight:800;flex:none}
.ccard .crow.dn .nm{color:var(--muted)}
/* "How you are": three labelled rows, not three competing headlines. */
.stlist{display:flex;flex-direction:column;gap:9px}
.strow{display:grid;grid-template-columns:auto 1fr;column-gap:9px;align-items:baseline}
.strow .sk{font-family:var(--mono);font-size:9px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--dim);font-weight:750}
.strow .sv{font-family:var(--mono);font-size:15px;font-weight:780;letter-spacing:-.02em;
  text-align:right;color:var(--paper)}
.strow .ss{grid-column:1/-1;font-size:11px;color:var(--muted);line-height:1.4}
.ctxacts{display:flex;gap:5px;flex-wrap:wrap;margin-top:9px}
.ctxacts .btn-s{padding:5px 10px;font-size:11.5px}
@media(max-width:1279px){ body.hasctx .ctx{display:none} body.hasctx .body{margin-right:0} }
/* ADMINISTRATION IS NOT A TRAINING PAGE. When the online shell opens the People
   view behind its own Admin button, the app is dressed for that room: no rail,
   no context column, no search across somebody's sessions, and above all no
   stat bar — an FTP, a W/kg and a season TSS belong to an athlete, and printing
   them along the top of the page where you change other people's roles is the
   same mixing the move exists to end. Nothing here is stored: the attribute is
   set on the frame while the tab is open and removed when you leave, exactly
   like the dark theme it travels with. The offline artifact never sets it. */
html[data-adminonly] .ctx,
html[data-adminonly] body.hasctx .ctx{display:none}
html[data-adminonly] body.hasctx .body{margin-right:0}
html[data-adminonly] .srchwrap,
html[data-adminonly] #srch,
html[data-adminonly] #srchBtn,
/* ☰ would put the training rail back on an administration page, and the user
   switcher is the training app's way of changing whose plan is loaded — which
   is not what you are doing here, and doing it from here would leave the shell
   showing one person's name over another person's data. */
html[data-adminonly] #menu,
html[data-adminonly] #whoBtn,
html[data-adminonly] #stats{display:none}

/* ============ PANES (sub-tabs within a view) ============ */
.panes{display:flex;gap:4px;flex-wrap:wrap;padding:12px 0 0;margin-bottom:-6px}
.pane{background:transparent;border:1px solid transparent;border-radius:8px 8px 0 0;padding:8px 14px;
  font-size:13px;font-weight:600;color:var(--muted);border-bottom:2px solid transparent;display:flex;
  align-items:center;gap:7px}
.pane:hover{background:var(--hover);border-color:transparent;border-bottom-color:var(--edge2);color:var(--paper)}
.pane.on{color:var(--acc);border-bottom-color:var(--acc);font-weight:750;background:transparent}
.pane .pb{font-family:var(--mono);font-size:9.5px;font-weight:700;padding:1px 6px;border-radius:999px;
  background:var(--sunk);color:var(--dim);border:1px solid var(--edgeSoft)}
.pane.on .pb{background:var(--accSoft);color:var(--acc);border-color:var(--accLine)}
.panes+*{margin-top:16px}

/* ============ DETAIL DRAWER ============ */
.drawer{position:fixed;top:0;right:0;bottom:0;width:min(460px,92vw);background:var(--surface);
  border-left:1px solid var(--edge);box-shadow:var(--shUp);z-index:58;display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform .18s ease;visibility:hidden}
.drawer.on{transform:none;visibility:visible}
@media (prefers-reduced-motion:reduce){.drawer{transition:none}}
.drawer-h{display:flex;align-items:center;gap:10px;padding:13px 16px;border-bottom:1px solid var(--edge);
  background:var(--raise);flex:none}
.drawer-h .dt{flex:1;min-width:0;font-size:14.5px;font-weight:800;letter-spacing:-.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.drawer-b{flex:1;overflow-y:auto;padding:4px 16px 90px}
.drawer-b .ses-b{border:0;padding:0}
body.drawn .scrim{display:block;background:rgba(7,8,19,.3);z-index:57}
/* On a wide screen the panel DOCKS: it becomes a column and the plan shrinks to
   sit beside it. The context column steps aside — three columns plus a drawer
   is one column too many. */
@media(min-width:1180px){
  body.drawn .body{margin-right:460px}
  body.drawn .scrim{display:none}
  body.drawn .ctx{display:none}
  .drawer{box-shadow:none}
}

/* ============ KOACH · ⌘K ============
   Not a second search box. Search finds things; Koach answers questions about
   your own data and runs commands — jump to a day, place a workout, log a
   session, export — all without the mouse. */
.cmdk{position:fixed;inset:0;z-index:100;background:rgba(7,8,19,.5);display:flex;
  align-items:flex-start;justify-content:center;padding:11vh 16px 16px}
.cmdk.hidden{display:none}
.cmdbox{width:min(660px,100%);background:var(--surface);border:1px solid var(--edge2);
  border-radius:var(--r);box-shadow:var(--sh2);overflow:hidden;display:flex;flex-direction:column;
  height:min(660px,78vh)}
/* --- header: who you are talking to --- */
.kch{display:flex;align-items:center;gap:10px;padding:11px 14px;border-bottom:1px solid var(--edge);
  background:var(--raise);flex:none}
.kch .av{width:30px;height:30px;border-radius:10px;background:var(--acc);color:var(--accInk);
  display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:14px;
  font-weight:800;flex:none}
.kch .ktitle{flex:1;min-width:0;font-size:14.5px;font-weight:800;letter-spacing:-.02em;line-height:1.2}
.kch .ktitle em{display:block;font-style:normal;font-family:var(--mono);font-size:9px;
  letter-spacing:.05em;color:var(--dim);font-weight:600;margin-top:2px}
.kch .ktab{font-size:12px}
.cmdk[data-tab=chat] .kt-chat,.cmdk[data-tab=cmd] .kt-cmd{background:var(--acc);border-color:var(--acc);
  color:var(--accInk);font-weight:750}
/* --- the transcript --- */
.kchat{flex:1;overflow-y:auto;padding:14px;display:flex;flex-direction:column;gap:11px;min-height:220px}
.cmdk[data-tab=cmd] .kchat,.cmdk[data-tab=cmd] .kchips{display:none}
.cmdk[data-tab=chat] .cmdlist{display:none}
.kb{display:flex;gap:9px;align-items:flex-start;max-width:92%}
.kb .av{width:24px;height:24px;border-radius:8px;background:var(--accSoft);border:1px solid var(--accLine);
  color:var(--acc);display:flex;align-items:center;justify-content:center;font-family:var(--mono);
  font-size:11px;font-weight:800;flex:none;margin-top:2px}
.kb .bub{background:var(--raise);border:1px solid var(--edgeSoft);border-radius:4px 12px 12px 12px;
  padding:10px 13px;font-size:13.5px;line-height:1.5}
.kb .bub b{font-weight:750}
.kb .bub .cs{font-size:12.5px;color:var(--muted);line-height:1.5;margin-top:5px}
.kb .bub .cs b{color:var(--paper)}
.kb .bub .polsum{margin-top:9px;padding:10px;background:var(--surface)}
.kb .bub table.zt{margin-top:6px}
.kb .bub .ctxacts{display:flex;gap:6px;flex-wrap:wrap;margin-top:9px}
/* The opening day card: one head line, the sessions in time order, then the
   one question. Deliberately plain — this is the first thing you see and it
   has to be read in about two seconds. */
.kb .bub .kdhead{font-family:var(--mono);font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--dim);font-weight:750}
.kb .bub .kdlist{margin-top:8px;display:flex;flex-direction:column;gap:5px}
.kb .bub .kdr{display:grid;grid-template-columns:44px 1fr auto;gap:9px;align-items:baseline}
.kb .bub .kdt{font-family:var(--mono);font-size:11.5px;color:var(--muted);font-weight:700}
.kb .bub .kdn{font-weight:650;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kb .bub .kdm{font-family:var(--mono);font-size:11.5px;color:var(--muted);font-weight:700}
.kb .bub .kok{color:var(--z2);font-weight:800}
.kb .bub .kdq{margin-top:11px;padding-top:10px;border-top:1px solid var(--edgeSoft);
  font-size:14.5px;font-weight:700}
.kb.me{margin-left:auto;flex-direction:row-reverse}
.kb.me .bub{background:var(--acc);color:var(--accInk);border-color:var(--acc);
  border-radius:12px 4px 12px 12px}
/* --- suggested replies --- */
.kchips{display:flex;flex-wrap:wrap;gap:6px;padding:0 14px 10px;flex:none}
.kchips:empty{display:none}
.kchip{font-size:12.5px;padding:6px 12px;border-radius:999px;border:1px solid var(--accLine);
  background:var(--surface);color:var(--acc);font-weight:650}
.kchip:hover{background:var(--acc);border-color:var(--acc);color:var(--accInk)}
/* --- the input row --- */
.kin{display:flex;gap:8px;align-items:center;padding:11px 14px;border-top:1px solid var(--edge);flex:none}
.cmdbox input{flex:1;font-size:15px;border-radius:999px;padding:9px 15px;background:var(--sunk)}
.cmdbox input:focus{outline:none;border-color:var(--acc);background:var(--surface)}
.kin button{flex:none;border-radius:999px;padding:9px 18px}
.cmdlist{overflow-y:auto;padding:5px 0}
.cmdlist .ch{font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);font-weight:750;padding:9px 15px 5px}
.cmdlist .ci{display:flex;align-items:center;gap:11px;width:100%;text-align:left;background:none;
  border:0;border-radius:0;padding:8px 15px;color:var(--paper)}
.cmdlist .ci:hover,.cmdlist .ci.on{background:var(--accSoft)}
.cmdlist .ci .cg{width:20px;text-align:center;flex:none;font-size:13px;opacity:.85}
.cmdlist .ci .ct{flex:1;min-width:0;font-size:13.5px;font-weight:600;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.cmdlist .ci .ct em{font-style:normal;color:var(--dim);font-family:var(--mono);font-size:10px;
  font-weight:600;margin-left:7px}
.cmdlist .ci .ck{font-family:var(--mono);font-size:10px;color:var(--dim);font-weight:700;flex:none}
.cmdempty{padding:22px 15px;text-align:center;color:var(--muted);font-size:13px}
/* Koach's answer. Visibly a different thing from the command list under it —
   one is what the app thinks, the other is what the app can do. */
.kans{margin:10px 12px;padding:13px 14px;border:1px solid var(--accLine);border-radius:var(--r);
  background:var(--accSoft)}
.kans .kh{display:flex;align-items:baseline;gap:8px;font-family:var(--mono);font-size:9px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--acc);font-weight:800;margin-bottom:7px}
.kans .kh span{letter-spacing:.06em;color:var(--dim);font-weight:600;font-size:8.5px}
.kans .kt{font-size:15px;font-weight:800;letter-spacing:-.02em;margin-bottom:8px}
.kans .cs{font-size:12.5px;color:var(--muted);line-height:1.5;margin-top:4px}
.kans .cs b{color:var(--paper);font-weight:700}
.kans .crow{display:flex;align-items:center;gap:8px;padding:5px 0;border-top:1px solid var(--accLine);font-size:12.5px}
.kans .crow:first-of-type{border-top:0}
.kans .crow .zs{width:3px;height:20px;border-radius:2px;flex:none}
.kans .crow .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.kans .crow .mn{font-family:var(--mono);font-size:10.5px;color:var(--muted);font-weight:650}
.kans .polsum{background:var(--surface);margin-top:10px;padding:11px}
.kans table.zt{margin-top:4px}
.kans .ctxacts{margin-top:10px}
.kans .ctxacts button{margin:0 5px 5px 0}
.cmdfoot{border-top:1px solid var(--edgeSoft);padding:8px 15px;display:flex;gap:14px;flex-wrap:wrap;
  font-family:var(--mono);font-size:9.5px;color:var(--dim);font-weight:650;background:var(--raise)}

/* ============ FOCUS MODE ============
   A phone propped on the hometrainer, read at arm's length: one target, huge,
   and the clock. Everything else is noise while the interval is running. */
.focus{position:fixed;inset:0;z-index:110;background:var(--bg);display:flex;flex-direction:column}
.focus.hidden{display:none}

/* ============ THE LOCK ============
   A door on a shared laptop, and it says so on itself. Sits above focus mode
   because it must be the first thing on screen when a passcode is set. */
/* A COLUMN, not a row, and that is not cosmetic. The only child normally in
   flow is `.lk-b` — the scene, the two corner buttons and the sponsor band are
   all absolute — so row and column look identical in the ordinary case. They
   stop looking identical the moment the band is taken out of absolute
   positioning, which the media query below has always done on a short screen:
   as a row it landed BESIDE the card. Nobody had ever seen it, because this
   screen was not screenshotted until 4 Aug 2026. */
.lock{position:fixed;inset:0;z-index:130;background:var(--bg);display:flex;
 flex-direction:column;align-items:center;justify-content:center;
 padding:24px 24px 96px;overflow:auto}
.lock.hidden{display:none}
.lk-b{position:relative;z-index:1;width:100%;display:flex;justify-content:center}
.lk-c{width:100%;max-width:440px;padding:26px;border:1px solid var(--edge);border-radius:18px;
 background:color-mix(in srgb,var(--card) 88%,transparent);
 box-shadow:0 24px 60px -30px rgba(0,0,0,.55)}
@supports not (background:color-mix(in srgb,red 50%,blue)){.lk-c{background:var(--card)}}

/* The scene. Drawn, never fetched — the offline rule has no exceptions, so the
   peloton is stroked SVG on three lanes at three speeds rather than a photo. */
.lk-scene{position:absolute;inset:0;overflow:hidden;pointer-events:none}
.lk-glow{position:absolute;inset:-20% -10% auto -10%;height:70%;
 background:radial-gradient(60% 100% at 50% 0%,var(--acc),transparent 70%);
 opacity:.13;filter:blur(30px)}
.lk-road{position:absolute;left:0;right:0;bottom:0;height:52%;
 background:repeating-linear-gradient(to bottom,transparent 0 46px,var(--edge) 46px 47px);
 opacity:.4;mask-image:linear-gradient(to bottom,transparent,#000 55%,transparent);
 -webkit-mask-image:linear-gradient(to bottom,transparent,#000 55%,transparent)}
/* Parallax at four depths. The far ridge is large, slow and faint; the near
   one is small, quicker and sharper — which is the whole illusion. Each layer
   is 200% wide and holds its ridge twice, so translating it by exactly -50%
   loops without a seam and needs no second element. */
.lk-par{position:absolute;left:0;bottom:0;width:200%;height:34%;
 animation-name:lkpar;animation-timing-function:linear;animation-iteration-count:infinite}
.lk-par svg{width:100%;height:100%;display:block}
.lk-par svg path{fill:currentColor}
.lk-par1{height:44%;color:var(--acc);opacity:.055;animation-duration:240s}
.lk-par2{height:32%;color:var(--acc);opacity:.075;animation-duration:130s}
.lk-par3{height:20%;color:var(--acc);opacity:.10;animation-duration:64s}
@keyframes lkpar{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* The peloton: one group per depth, each a single SVG of ten riders in
   staggered rows rather than a lone silhouette per lane. */
.lk-pelo{position:absolute;left:-900px;width:calc(760px * var(--s,1));color:var(--acc);
 animation-name:lkride;animation-timing-function:linear;animation-iteration-count:infinite}
.lk-pelo svg{width:100%;height:auto;stroke:currentColor;stroke-width:3.2;
 stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke}
@keyframes lkride{from{transform:translateX(0)}to{transform:translateX(calc(100vw + 960px))}}

.lk-brand{display:flex;align-items:center;gap:13px;margin-bottom:20px}
.lk-mark{width:38px;height:38px;flex:none;color:var(--acc);stroke:currentColor;
 stroke-width:2.2;animation:lkspin 26s linear infinite}
@keyframes lkspin{to{transform:rotate(360deg)}}
.lk-word b.wordmark{display:block;font-size:15px}
.lk-word em{display:block;font-style:normal;font-family:var(--mono);font-size:10px;
 letter-spacing:.14em;text-transform:uppercase;color:var(--dim);margin-top:3px}
.lk-s{font-size:22px;font-weight:800;letter-spacing:-.02em;margin:0 0 18px}

/* The sponsor strip is a BAND along the foot of the screen, not a block inside
   the card. Fourteen marks stacked under the passcode box made the one thing
   you came here to do the smaller half of the page; along the bottom they read
   as what they are — a backdrop behind the rider. */
.lk-sponsors{position:absolute;left:0;right:0;bottom:0;z-index:1;
 display:flex;flex-direction:column;align-items:center;gap:7px;
 padding:14px 20px 16px;pointer-events:none}
.lk-sponsors u{text-decoration:none;font-family:var(--mono);font-size:9px;letter-spacing:.16em;
 text-transform:uppercase;color:var(--dim);opacity:.8}
.lk-sponsors span{font-size:11.5px;font-weight:800;letter-spacing:.13em;color:var(--tx);opacity:.72}
.lk-sponsors i{font-style:normal;color:var(--dim);opacity:.5}
/* A light tile behind each mark, because seven of the fourteen are black marks
   and a black mark on a dark backdrop is an invisible one. Inverting them would
   be modifying somebody's trademark, so the backdrop moves instead of the mark.
   Fixed row height and free width: these are wordmarks of wildly different
   aspect, and forcing a common width would squash half of them. */
.lk-splist{display:flex;flex-wrap:wrap;justify-content:center;gap:5px;max-width:960px}
.lk-sp{display:inline-flex;align-items:center;justify-content:center;height:24px;
 padding:0 8px;border-radius:5px;background:#fff;border:1px solid rgba(0,0,0,.07);
 opacity:.8;transition:opacity .16s;pointer-events:auto}
.lk-sp:hover{opacity:1}
.lk-sp img{height:13px;width:auto;max-width:78px;object-fit:contain;display:block}
.lk-sptall img{height:19px}
/* THE RESERVATION IS A CONSTANT AND THE BAND IS NOT. `.lock` keeps 96px of
   bottom padding clear for a band that is absolutely positioned over it — which
   is right at 1440px, where the marks fit in two rows. At 520px they wrap into
   FOUR, the band grows to ~160px, and it comes up through the card: the last
   thing you read on the phone you actually sign in on was printed over a row of
   logos. A screenshot found it the first time this screen was ever captured.
   So the band comes out of absolute positioning on a narrow screen as well as a
   short one, and where it does, the screen stops centring and starts at the top
   — a centred flex column clips its own overflow at the top edge, which would
   trade this bug for a worse one. */
/* the narrow/short layout lives further down, AFTER .lk-adm and .lk-thm — see
   "THE RESERVATION IS A CONSTANT" below. Putting it here would have lost to
   those two rules on source order, which is exactly what happened first. */

/* A screen you meet every morning must not insist on animating at you. */
@media(prefers-reduced-motion:reduce){
 .lk-pelo,.lk-mark,.lk-par{animation:none}
 .lk-pelo{opacity:.1}
}
.lk-list{display:flex;flex-direction:column;gap:8px}
.lk-p{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;
 padding:11px 14px;border:1px solid var(--edge);border-radius:10px;background:var(--card);
 color:var(--tx);cursor:pointer;text-align:left;font:inherit}
.lk-p b{font-size:14px;font-weight:700}
.lk-p em{font-style:normal;font-size:11px;color:var(--dim);font-family:var(--mono)}
.lk-p.on{border-color:var(--acc);box-shadow:0 0 0 1px var(--acc) inset}
.lk-pin{display:flex;gap:8px;margin-top:14px}
.lk-pin input{flex:1}
.lk-form{display:flex;flex-direction:column;gap:11px}
.lk-f{display:flex;flex-direction:column;gap:5px}
.lk-f span{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;
 text-transform:uppercase;color:var(--dim)}
.lk-f input{width:100%}
.lk-go{margin-top:3px}
.lk-err{min-height:18px;margin-top:8px;font-size:12px;color:var(--z5)}
/* people on the left, the way into administration on the right — it is not
   one of the names above it, and it must not look like one */
.lk-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:16px}
.lk-adm{position:absolute;right:20px;bottom:18px;z-index:2;letter-spacing:.14em;
 font-weight:800;font-size:11.5px;opacity:.8}
.lk-adm:hover{opacity:1;border-color:var(--acc)}
/* Light/dark, bottom LEFT, opposite ADMIN. Same treatment as ADMIN so the two
   corners read as one pair of utilities rather than as two unrelated buttons —
   and neither competes with the one thing you came here to do. */
.lk-thm{position:absolute;left:20px;bottom:18px;z-index:2;display:flex;align-items:center;gap:7px;
 opacity:.72}
.lk-thm:hover{opacity:1;border-color:var(--acc)}
.lk-thm u{text-decoration:none;font-family:var(--mono);font-size:9px;letter-spacing:.14em;
 text-transform:uppercase}
@media(max-width:560px){ .lk-thm u{display:none} }
/* THE RESERVATION IS A CONSTANT AND THE BAND IS NOT. `.lock` keeps 96px of
   bottom padding clear for a band that is absolutely positioned over it — which
   is right at 1440px, where the marks fit in two rows. At 520px they wrap into
   FOUR, the band grows to ~160px, and it comes up through the card: the last
   thing you read on the phone you actually sign in on was printed over a row of
   logos. A screenshot found it the first time this screen was ever captured,
   on 4 Aug 2026.

   So the band comes out of absolute positioning on a narrow screen as well as a
   short one — and the two corner utilities come with it, because they are pinned
   to the VIEWPORT and the moment the screen scrolls they stop being in a corner
   of anything: they sit over whatever has scrolled under them, which is the
   band. Last in the flow instead; they are the two least important things here.

   Where any of that happens the screen stops centring and starts at the top: a
   centred flex column clips its own overflow at the TOP edge, which would trade
   this bug for a worse one.

   AFTER `.lk-adm` and `.lk-thm`, deliberately. Written above them — next to the
   band it also moves — it lost to them on source order and the buttons stayed
   in the corners, which looked exactly like the bug it was meant to fix. */
@media(max-height:760px),(max-width:560px){
 .lk-sponsors{position:static;width:100%;padding-top:18px;order:1}
 .lk-thm,.lk-adm{position:static;order:2;margin-top:9px}
 .lock{justify-content:flex-start;padding-bottom:24px}
}
.lk-note{margin-top:10px;font-size:11.5px;line-height:1.55;color:var(--dim)}
/* ---- the environments page --------------------------------------------- */
.envc{padding:0;overflow:hidden}
.envhead{display:flex;align-items:center;gap:10px;padding:14px 16px;flex-wrap:wrap}
.envc.open .envhead{border-bottom:1px solid var(--edge)}
.envname{font-size:15px;font-weight:800;letter-spacing:-.01em;max-width:230px;
 border:1px solid transparent;background:transparent;padding:5px 8px}
.envname:hover{border-color:var(--edge)}
.envname:focus{border-color:var(--acc);background:var(--card)}
.envsum{flex:1;min-width:160px;font-size:11.5px;color:var(--dim)}
.envbody{padding:4px 16px 18px}
.envbody h4{font-size:10px;font-family:var(--mono);letter-spacing:.14em;text-transform:uppercase;
 color:var(--dim);margin:18px 0 8px}
.envrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:12px}
/* A ticklist, not a stack of banners: fourteen full-width rows turned one
   environment into three screens of scrolling. */
.envkitg{margin-bottom:12px;display:grid;
 grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:7px}
.envkitg u{grid-column:1/-1;display:block;text-decoration:none;font-family:var(--mono);font-size:9px;
 letter-spacing:.13em;text-transform:uppercase;color:var(--dim);margin-bottom:1px}
.envkit{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 11px;
 border:1px solid var(--edge);border-radius:9px;font-size:12.5px;cursor:pointer;line-height:1.3}
.envkit.on{border-color:var(--acc);background:color-mix(in srgb,var(--acc) 7%,transparent)}
.envkit input{width:15px;height:15px;accent-color:var(--acc);flex:none}
.envkit em{font-style:normal;font-size:10.5px;color:var(--dim);flex-basis:100%;padding-left:23px}
/* What a piece of kit can do. Indented under the item it belongs to and only
   drawn once that item is ticked — every feature of every item on screen at
   once is a form nobody reads. Smaller than its parent, deliberately: it is
   detail about a thing, not another thing. */
.onb-feat{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:6px;
 margin:-2px 0 6px 22px;padding-left:11px;border-left:2px solid var(--edge)}
.envkit.sm{padding:5px 9px;font-size:11.5px;border-radius:7px;gap:6px}
.envkit.sm input{width:13px;height:13px}
.envkit.sm em{flex-basis:auto;padding-left:5px;font-size:10px}
.envhrs{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:8px;margin-top:4px}
.envh{display:flex;flex-direction:column;gap:4px}
.envh span{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
 color:var(--dim);text-align:center}
.envh input{width:100%;text-align:center;padding:7px 4px}
@media(max-width:720px){.envhrs{grid-template-columns:repeat(4,1fr)}}
/* Sign-up, offered under the form. It is the thing you do once; it must be
   findable without competing with the thing everybody does every day. */
.lk-new{margin-top:14px;padding-top:13px;border-top:1px solid var(--edge);
 display:flex;align-items:center;justify-content:space-between;gap:10px;
 font-size:12px;color:var(--dim)}
/* ---- the setup wizard --------------------------------------------------
   Above the sign-in screen (130) because it comes after it, and below dialogs
   (150) so the lab-report picker and any confirmation still land on top. */
.onb{position:fixed;inset:0;z-index:140;background:var(--bg);overflow:auto;
 display:flex;align-items:flex-start;justify-content:center;padding:26px 18px}
.onb.hidden{display:none}
.onb-b{width:100%;max-width:820px}
.onb-c{background:var(--card);border:1px solid var(--edge);border-radius:18px;
 box-shadow:0 24px 60px rgba(7,8,19,.14);overflow:hidden}
.onb-head{padding:20px 24px 0;display:flex;flex-direction:column;gap:14px}
.onb-steps{display:flex;gap:6px;flex-wrap:wrap}
.onb-steps span{font-family:var(--mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;
 color:var(--dim);border:1px solid var(--edge);border-radius:999px;padding:4px 10px}
.onb-steps .on{color:var(--acc);border-color:var(--acc);font-weight:700}
.onb-steps .done{color:var(--tx);border-color:var(--tx2,var(--edge))}
.onb-body{padding:18px 24px 24px}
.onb-body h2{font-size:23px;letter-spacing:-.02em;margin:6px 0 10px}
.onb-p{font-size:13px;line-height:1.6;color:var(--tx);margin:0 0 12px;max-width:66ch}
.onb-p.onb-dim{color:var(--dim);font-size:12px}
.onb-p.onb-ok{color:var(--acc)}
.onb-p.onb-bad{color:var(--z5)}
.onb-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:12px;margin-top:6px}
.onb-f{display:flex;flex-direction:column;gap:5px}
.onb-f span{font-family:var(--mono);font-size:9.5px;letter-spacing:.13em;
 text-transform:uppercase;color:var(--dim)}
.onb-f input,.onb-f select{width:100%}
.onb-or{margin:18px 0 10px;font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;
 text-transform:uppercase;color:var(--dim);display:flex;align-items:center;gap:10px}
.onb-or:after{content:"";flex:1;height:1px;background:var(--edge)}
.onb-pick{display:grid;gap:10px;margin-top:6px}
.onb-opt{text-align:left;display:flex;flex-direction:column;gap:3px;padding:14px 16px;
 border:1.5px solid var(--edge);border-radius:12px;background:var(--card);color:var(--tx);
 cursor:pointer;font:inherit}
.onb-opt:hover{border-color:var(--acc)}
.onb-opt.on{border-color:var(--acc);background:color-mix(in srgb,var(--acc) 8%,var(--card))}
.onb-opt b{font-size:13.5px}
.onb-opt em{font-style:normal;font-size:11.5px;color:var(--dim);line-height:1.5}
/* A place is now a TICK, not a button: you can have all of them, and most
   people do. The row has to hold a checkbox, a name and a remove button, so it
   is a grid rather than the plain column an exclusive choice needed. */
.onb-place{display:grid;grid-template-columns:1fr auto;gap:4px 10px;cursor:default}
.onb-place>em,.onb-place>.onb-pname{grid-column:1/-1}
.onb-tick{display:flex;align-items:center;gap:10px;cursor:pointer;font:inherit}
.onb-tick input{width:16px;height:16px;accent-color:var(--acc);flex:none}
.onb-x{align-self:start;padding:3px 8px;line-height:1;color:var(--dim)}
.onb-x:hover{color:var(--z5);border-color:var(--z5)}
.onb-pname{margin-top:6px;max-width:340px}
/* One folding panel per chosen place. Open by default — a setup step whose
   content is hidden behind a click is a setup step people skip. */
.onb-pl{border:1px solid var(--edge);border-radius:12px;padding:0 14px;margin:12px 0;
 background:color-mix(in srgb,var(--card) 60%,transparent)}
.onb-pl>summary{cursor:pointer;padding:12px 0;font-size:13.5px;list-style:none}
.onb-pl>summary::-webkit-details-marker{display:none}
.onb-pl>summary:before{content:"▾";color:var(--acc);margin-right:8px;font-size:11px}
.onb-pl:not([open])>summary:before{content:"▸"}
.onb-pl>h4{margin:14px 0 6px;font-size:12px}
.onb-pl>.help,.onb-pl>.hint{margin-bottom:10px}
.onb-pl>*:last-child{margin-bottom:14px}
.onb-foot{padding:14px 24px;border-top:1px solid var(--edge);display:flex;align-items:center;
 justify-content:space-between;gap:10px;background:var(--bg2,var(--card))}
/* ---- the tour ----------------------------------------------------------
   A card, not a curtain: the whole point is that you can see the page it is
   describing, so it never covers the middle of the screen and never blocks a
   click on what it is pointing at. */
.tour{position:fixed;right:22px;bottom:22px;z-index:145;max-width:360px}
.tour.hidden{display:none}
.tour-c{background:var(--card);border:1px solid var(--acc);border-radius:14px;padding:16px 18px;
 box-shadow:0 18px 46px rgba(7,8,19,.22)}
.tour-n{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;
 color:var(--acc)}
.tour-c h3{font-size:16px;margin:6px 0 7px}
.tour-c p{font-size:12.5px;line-height:1.6;color:var(--dim);margin:0 0 14px}
.tour-f{display:flex;align-items:center;justify-content:space-between;gap:10px}
@media(max-width:640px){.tour{left:14px;right:14px;bottom:14px;max-width:none}}
/* The "forgotten it" explainer. Set apart from the standing note under it, or
   the one paragraph somebody is actually hunting for reads as more small print. */
.lk-help{border-left:2px solid var(--acc);padding-left:11px;color:var(--tx)}
.lk-help code{font-family:var(--mono);font-size:11px;letter-spacing:.06em;color:var(--acc)}
/* An issued reset code, on the People page. It is read out loud, so it is set
   in mono at a size that survives being read off a laptop across a cabin. */
.rstc{font-family:var(--mono);font-size:12.5px;letter-spacing:.1em;font-weight:700;
 color:var(--acc);background:color-mix(in srgb,var(--acc) 10%,transparent);
 border:1px solid color-mix(in srgb,var(--acc) 35%,transparent);
 border-radius:7px;padding:4px 9px;white-space:nowrap}

/* Who is using this copy — in the top bar, because switching athlete is a thing
   you do before anything else, not something to go looking for in a settings
   page. The name hides under 720px; the mark stays, so it is still a target. */
.whobtn{display:flex;align-items:center;gap:7px;padding:6px 11px;border:1px solid var(--edge);
 border-radius:999px;background:var(--card);color:var(--tx);cursor:pointer;font:inherit;
 font-size:12.5px;font-weight:700;white-space:nowrap;max-width:190px}
.whobtn:hover{border-color:var(--acc)}
.whobtn .wa{color:var(--acc);font-size:11px}
.whobtn .wn{overflow:hidden;text-overflow:ellipsis}
@media(max-width:720px){.whobtn .wn{display:none}.whobtn{padding:6px 9px}}

/* Acting as somebody else. Deliberately loud: a coach with edit rights who
   forgets whose plan is open would make real changes to the wrong athlete. */
.actbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:14px;
 padding:10px 14px;border:1px solid var(--acc);border-radius:12px;background:var(--card)}
.actbar .ab-w{font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;
 text-transform:uppercase;color:var(--dim)}
.actbar .ab-n{flex:1;min-width:0;font-size:13px}
/* roster rows: a status dot and a row of small readouts */
.rdot{width:9px;height:9px;border-radius:50%;flex:none}
.rkpi{display:flex;flex-direction:column;gap:1px;min-width:58px}
.rkpi u{text-decoration:none;font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;
 text-transform:uppercase;color:var(--dim)}
.rkpi b{font-size:13px;font-weight:700}
@media(max-width:900px){.rkpi{min-width:46px}.rkpi u{font-size:9px}}

/* the lab-report drop box and its review table */
.labdrop{margin-top:12px;padding:20px;border:1.5px dashed var(--edge);border-radius:12px;
 background:var(--card);text-align:center;cursor:pointer;display:flex;flex-direction:column;gap:4px}
.labdrop:hover,.labdrop.on{border-color:var(--acc)}
.labdrop b{font-size:13.5px}
.labdrop em{font-style:normal;font-size:11.5px;color:var(--dim)}
.labtab td{vertical-align:middle}
.labtab .labctx{font-family:var(--mono);font-size:10.5px;color:var(--dim);line-height:1.45}

/* profiles view: the switcher rows, the code box and the message thread */
.prlist{display:flex;flex-direction:column;gap:8px}
.prrow{display:flex;align-items:center;gap:10px;padding:9px 12px;border:1px solid var(--edge);
 border-radius:10px;background:var(--card)}
.prrow.on{border-color:var(--acc)}
.prno{font-family:var(--mono);font-size:11px;color:var(--dim);min-width:26px}
.prn{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.prn b{font-size:13.5px;font-weight:700}
.prn em{font-style:normal;font-size:11px;color:var(--dim);font-family:var(--mono)}
.codebox{display:flex;gap:8px;align-items:center}
.codebox code{flex:1;min-width:0;overflow-x:auto;white-space:nowrap;padding:9px 12px;
 border:1px solid var(--edge);border-radius:8px;background:var(--card);
 font-family:var(--mono);font-size:11.5px}
.msgs{display:flex;flex-direction:column;gap:8px;max-height:340px;overflow-y:auto;
 overscroll-behavior:contain}
.msg{max-width:78%;padding:8px 12px;border:1px solid var(--edge);border-radius:12px;
 background:var(--card);align-self:flex-start}
.msg.me{align-self:flex-end;border-color:var(--acc)}
.msg .mh{font-family:var(--mono);font-size:10.5px;color:var(--dim);margin-bottom:3px}
.msg .mt{font-size:13px;line-height:1.5;white-space:pre-wrap}
.fk-h{display:flex;align-items:center;gap:12px;padding:12px 18px;border-bottom:1px solid var(--edge);flex:none}
.fk-h .ft{flex:1;min-width:0;font-size:15px;font-weight:800;letter-spacing:-.02em;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.fk-h .fe{font-family:var(--mono);font-size:11px;color:var(--dim);font-weight:700}
.fk-b{flex:1;overflow-y:auto;display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:18px;text-align:center;gap:6px}
.fk-step{font-family:var(--mono);font-size:11px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--dim);font-weight:750}
.fk-nm{font-size:clamp(20px,4.4vw,34px);font-weight:820;letter-spacing:-.03em;line-height:1.1}
.fk-tgt{font-family:var(--mono);font-size:clamp(44px,13vw,110px);font-weight:800;letter-spacing:-.05em;
  line-height:1;color:var(--acc);font-variant-numeric:tabular-nums}
.fk-u{font-family:var(--mono);font-size:13px;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);font-weight:700}
.fk-clock{font-family:var(--mono);font-size:clamp(30px,7vw,58px);font-weight:750;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;margin-top:6px}
.fk-mtr{width:min(620px,92%);height:8px;border-radius:4px;background:var(--sunk);overflow:hidden;margin-top:4px}
.fk-mtr i{display:block;height:100%;background:var(--acc)}
.fk-next{font-size:13px;color:var(--muted);margin-top:10px}
.fk-next b{color:var(--paper);font-weight:700}
.fk-map{display:flex;gap:2px;width:min(620px,92%);height:10px;margin-top:14px}
.fk-map i{display:block;flex:1 1 auto;border-radius:2px;opacity:.35}
.fk-map i.on{opacity:1}
.fk-map i.dn{opacity:.7}
.fk-f{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;padding:14px 18px 20px;flex:none;
  border-top:1px solid var(--edge)}
.fk-f button{min-width:104px;padding:12px 18px;font-size:15px;border-radius:10px}

/* ============ WEEK WORKSPACE ============ */
.wsbar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:14px 0 12px}
.wsbar .nav2{display:flex;gap:4px}
.wsbar .rng{display:flex;flex-direction:column;gap:1px}
.wsbar .rng b{font-size:15px;font-weight:800;letter-spacing:-.02em}
.wsbar .kpis{margin-left:auto;display:flex;gap:1px;background:var(--edge);
  border:1px solid var(--edge);border-radius:9px;overflow:hidden}
.wsbar .k{background:var(--surface);padding:6px 13px;min-width:64px}
.wsbar .k u{display:block;text-decoration:none;font-family:var(--mono);font-size:9px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--dim);font-weight:600}
.wsbar .k b{font-family:var(--mono);font-size:14px;font-weight:700;font-variant-numeric:tabular-nums}
.wgrid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:8px;align-items:start}
.wday{background:var(--surface);border:1px solid var(--edgeSoft);border-radius:var(--r);
  min-height:190px;display:flex;flex-direction:column;overflow:hidden}
.wday.today{border-color:var(--acc);box-shadow:0 0 0 1px var(--acc)}
.wday.past{opacity:.72}
.wday.none{background:transparent;border-style:dashed}
.wday.drop{border-color:var(--acc);background:var(--accSoft)}
.wh{display:flex;align-items:baseline;gap:6px;padding:8px 10px;border-bottom:1px solid var(--edgeSoft);
  background:var(--raise);flex-wrap:wrap}
.wh .dw{font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--dim);font-weight:700}
.wh .dn{font-family:var(--mono);font-size:16px;font-weight:750;letter-spacing:-.03em}
.wday.today .wh .dn{color:var(--acc)}
.wh .tt{margin-left:auto;font-family:var(--mono);font-size:10px;color:var(--muted);font-weight:600}
.wh .ev{font-size:11px;opacity:.75}
.wb{padding:7px;display:flex;flex-direction:column;gap:6px;flex:1}
.wempty{font-family:var(--mono);font-size:10px;color:var(--dim);text-align:center;padding:12px 4px;font-weight:600}
.chip2{background:var(--raise);border:1px solid var(--edge);border-left:3px solid var(--zstripe,var(--edge));
  border-radius:8px;padding:7px 8px;cursor:pointer;display:flex;flex-wrap:wrap;align-items:center;gap:5px}
.chip2:hover{border-color:var(--edge2);border-left-color:var(--zstripe,var(--edge));background:var(--surface)}
.chip2.on{border-color:var(--acc);box-shadow:0 0 0 1px var(--acc)}
/* the chip is the same statement as the card, in the week grid's space: the
   box turns light green. It used to only fade to opacity .8, which reads as
   "disabled" rather than "you did this". */
.chip2.dn{background:var(--done);border-color:var(--doneEdge)}
.chip2.dn:hover{background:var(--done)}
.chip2 .ic{font-size:12px;flex:none}
.chip2 .nm{font-size:11.5px;font-weight:650;line-height:1.25;flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chip2 .mt{width:100%;font-family:var(--mono);font-size:9.5px;color:var(--muted);font-weight:600}
.chip2 .fl{font-family:var(--mono);font-size:8.5px;font-weight:800;padding:0 4px;border-radius:3px;
  background:var(--sunk);color:var(--dim)}
.chip2 .fl.heat{background:var(--z4);color:#fff}
.chip2 .fl.q{background:var(--z5);color:#fff}
.chip2 .fl.dn{background:var(--doneEdge);color:var(--ink)}
/* A MISSED SESSION IS AN ABSENCE, NOT A CATEGORY — so it gets no colour of its
   own. --done and the seven zones are the only data fills here; muting the chip
   and marking it ✗ says "this was planned and did not happen" without adding an
   eighth thing the eye has to learn. */
.chip2.miss{opacity:.6;border-style:dashed;background:transparent}
.chip2.miss .nm{text-decoration:line-through;text-decoration-thickness:1px;text-decoration-color:var(--dim)}
.chip2 .fl.ms{background:var(--sunk);color:var(--dim);border:1px solid var(--edge)}
/* the mode switch on the calendar bar */
.calmodes{margin-left:auto;display:flex;gap:4px}
.calmodes .on{background:var(--accSoft);border-color:var(--accLine);color:var(--acc)}
.wsbar.wsk{padding-top:0}
/* The KPI strip is the only thing on this row now that the navigation moved to
   its own bar, so on a phone it wraps to full width and its own background used
   to show through beside five content-sized cells as a grey slab. The cells
   share the row instead. */
.wsbar.wsk .kpis{margin-left:0;flex:1}
.wsbar.wsk .k{flex:1}
/* Block bands. A block used to own a pill in the navigation strip, which is how
   it said "I am a period of training at a place" — inside the calendar it can
   say that where the days actually are. */
.calbands{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 12px}
.calband{display:flex;align-items:center;gap:8px;background:var(--surface);border:1px solid var(--edge);
  border-radius:999px;padding:5px 13px 5px 6px;font-size:12px;font-weight:650;cursor:pointer;color:var(--paper)}
.calband:hover{border-color:var(--acc)}
.calband em{width:9px;height:9px;border-radius:50%;background:var(--bc);display:block;flex:none}
.calband span{font-family:var(--mono);font-size:10px;color:var(--dim);font-weight:600}
/* The month grid. Real chips and real drop targets, unlike the dense three-month
   cells — a month is where you move something a fortnight. */
.mgrid{display:grid;grid-template-columns:30px repeat(7,minmax(0,1fr));gap:5px;align-items:stretch}
.mgrid .hd{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--dim);text-align:center;padding:5px 0;font-weight:750}
.mgrid .wn{font-family:var(--mono);font-size:9.5px;color:var(--dim);display:flex;align-items:center;
  justify-content:center;background:var(--sunk);border-radius:6px;font-weight:750}
.mcell{background:var(--surface);border:1px solid var(--edgeSoft);border-radius:9px;min-height:92px;
  padding:19px 5px 5px;position:relative;display:flex;flex-direction:column;gap:4px;overflow:hidden}
.mcell.dense{min-height:58px;padding:17px 6px 5px}
.mcell.out{background:transparent;border-color:transparent}
.mcell.none{background:transparent;border-style:dashed}
.mcell.past{opacity:.72}
.mcell.today{border-color:var(--acc);box-shadow:0 0 0 1px var(--acc)}
.mcell.drop{border-color:var(--acc);background:var(--accSoft)}
.mcell.dense{cursor:pointer}
.mcell.dense:hover:not(.out){border-color:var(--acc)}
.mcell .bnd{position:absolute;left:0;top:0;bottom:0;width:3px;border-radius:8px 0 0 8px}
.mcell .mn{position:absolute;left:8px;top:3px;font-family:var(--mono);font-size:10.5px;
  font-weight:750;color:var(--muted)}
.mcell.today .mn{color:var(--acc)}
.mcell .mm{position:absolute;right:7px;top:3px;font-family:var(--mono);font-size:9.5px;
  color:var(--dim);font-weight:700}
.mcell .mt2{font-family:var(--mono);font-size:11px;font-weight:700}
.mcell .s{display:flex;gap:2px;margin-top:4px}
.mcell .s i{height:4px;flex:1 1 auto;min-width:3px;border-radius:2px}
.mcell .bk{position:absolute;right:6px;bottom:4px;font-family:var(--mono);font-size:9px;
  color:var(--dim);font-weight:700}
.mcell .wempty{padding:4px}
.mcell .wadd{padding:2px;font-size:11px}
/* The training window, as a line of the Today card rather than a card of its
   own. Muted and mono because it is a constraint being reported, not a figure
   being celebrated — the number that matters on that card is the one above it. */
.dwin{display:inline-block;margin-top:3px;font-family:var(--mono);font-size:10.5px;
  color:var(--dim);font-weight:600}
.dcard.t-bad .dwin{color:var(--z5)}
/* "You made this one." Same reasoning as the ADMIN pill below: a word, in the
   chrome pair, because the accent means "interactive" everywhere and the seven
   zones are validated data colours. It is a fact about provenance, not a value
   on a scale, so it has no business borrowing either. */
.libmine{font-family:var(--mono);font-size:8px;font-weight:800;letter-spacing:.14em;
  padding:1px 4px;border-radius:3px;background:var(--sunk);color:var(--muted);
  border:1px solid var(--edge2);margin-left:6px;vertical-align:1px}
/* bottom-LEFT: .libtag already owns the top-right corner of the graphic, and two
   badges stacked there would fight for the same 62px the graphic reserves */
.libgfx .libmine{position:absolute;left:6px;bottom:6px;margin:0;background:var(--surface)}
/* ADMINISTRATION, IN WORDS. Not a colour: this app spends its colours on data,
   and a colour would have to work in both themes and for a colour-blind reader
   before it could mean anything. The pill borrows the muted/edge pair every
   other piece of chrome uses, and the bar states it again on the page for the
   deep link that never saw the tab. */
.admp{font-family:var(--mono);font-size:8px;font-weight:800;letter-spacing:.14em;
  padding:1px 4px;border-radius:3px;background:var(--sunk);color:var(--muted);
  border:1px solid var(--edge);margin-left:6px;vertical-align:1px}
#subnav button.adm .admp{background:transparent}
#subnav button.adm.on .admp{border-color:currentColor}
.admbar{display:flex;align-items:flex-start;gap:9px;background:var(--sunk);
  border:1px solid var(--edge);border-radius:var(--r);padding:10px 13px;
  font-size:12.5px;color:var(--muted);margin-bottom:14px;line-height:1.45}
.admbar .admp{margin-left:0;flex:none;margin-top:2px}
/* the Blocks list */
.blkrow{border-left:3px solid var(--bc)}
.blkrow.on{border-color:var(--acc);border-left-color:var(--bc);box-shadow:0 0 0 1px var(--acc)}
.blkh{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.blkh b{font-size:15px;font-weight:750;letter-spacing:-.01em}
.blkh .dot{width:10px;height:10px;border-radius:50%;background:var(--bc);flex:none}
.blkh .blkd{margin-left:auto;font-family:var(--mono);font-size:11px;color:var(--dim);font-weight:650}
.blkk{display:flex;gap:1px;background:var(--edge);border:1px solid var(--edge);border-radius:var(--r2);
  overflow:hidden;margin-top:11px;flex-wrap:wrap}
.blkk span{background:var(--surface);padding:6px 13px;min-width:62px;flex:1}
.blkk u{display:block;text-decoration:none;font-family:var(--mono);font-size:9px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--dim);font-weight:750}
.blkk b{font-family:var(--mono);font-size:14px;font-weight:700;font-variant-numeric:tabular-nums}
/* a chip in a ~120px month cell: the name and the marks, nothing else */
.chip2.mini{padding:3px 5px;gap:3px}
.chip2.mini .mt{display:none}
.chip2.mini .nm{font-size:10.5px;-webkit-line-clamp:1}
.wadd{background:transparent;border:1px dashed var(--edge);color:var(--dim);padding:5px;border-radius:8px;
  font-size:14px;line-height:1;font-weight:700}
.wadd:hover{border-color:var(--acc);color:var(--acc);background:var(--accSoft)}
@media(max-width:1100px){.wgrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:640px){.wgrid{grid-template-columns:1fr}.wsbar .kpis{margin-left:0;width:100%}}

/* ============ DASHBOARD ============ */
.dash{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:12px;padding:16px 0 0}
/* Three bands, three questions. The heading is deliberately the same 9.5px mono
   the card labels use rather than something louder: it is a divider, and a band
   title that outshouts the numbers under it has taken the attention it was added
   to organise. Each band carries its own grid, so a `wide` card spans inside its
   own question and never drags a neighbouring one across the page. */
.dbands{padding-top:2px}
.dband+.dband{margin-top:20px}
.dbt{font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--dim);font-weight:750;margin:0;padding:0 0 0 2px}
.dband .dash{padding-top:9px}
/* The section mark, read out of SECTIONS by dashIcon(). Sized and coloured as a
   label rather than as an illustration — it sits in the 9.5px header row next to
   the card title, and a glyph that competed with the 27px figure below it would
   be the opposite of the point. */
.dcard .di{font-size:12.5px;line-height:1;color:var(--dim);flex:none;opacity:.85}
.dcard{background:var(--surface);border:1px solid var(--edgeSoft);border-radius:var(--r);padding:15px;
  box-shadow:var(--sh1);display:flex;flex-direction:column;gap:5px}
.dcard.wide{grid-column:span 2}
@media(max-width:640px){.dcard.wide{grid-column:span 1}}
.dcard .dh{display:flex;align-items:center;gap:8px}
.dcard .dt{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);font-weight:700}
.dcard .dh button{margin-left:auto}
.dcard .dv{font-size:15px;line-height:1.15}
.dcard .dv b{font-family:var(--mono);font-size:27px;font-weight:750;letter-spacing:-.03em}
.dcard .dv .u{font-family:var(--mono);font-size:11px;color:var(--dim);font-weight:600}
.dcard .ds{font-size:12px;color:var(--muted);line-height:1.45}
.dcard.t-good{border-left:3px solid var(--z2)}
.dcard.t-warn{border-left:3px solid var(--z3)}
.dcard.t-bad{border-left:3px solid var(--z5)}
.dcard.t-quiet{opacity:.9}
.wkbars{display:flex;flex-direction:column;gap:7px;margin-top:4px}
.wkrow{display:grid;grid-template-columns:64px 1fr auto;gap:9px;align-items:center;font-size:11.5px}
.wkrow .mtr{height:6px;border-radius:3px;background:var(--sunk);overflow:hidden}
.wkrow .mtr i{display:block;height:100%}
.wkrow .mono{font-family:var(--mono);font-size:10px;color:var(--muted);font-weight:600}

/* ============ VOLUME CHART ============ */
.vchart{display:flex;gap:6px;align-items:flex-end;margin-top:14px;min-height:150px}
.vbar{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;gap:5px}
.vbar .vb{width:100%;height:120px;background:var(--sunk);border-radius:5px;display:flex;align-items:flex-end;overflow:hidden}
.vbar .vb i{display:block;width:100%;background:var(--acc);border-radius:5px 5px 0 0;min-height:2px}
.vbar .vl{font-family:var(--mono);font-size:9.5px;color:var(--dim);font-weight:600}
.vbar .vv{font-size:10px;color:var(--muted);font-weight:600}

/* ============ CONSISTENCY HEATMAP & RECORDS ============ */
.hmap{display:flex;gap:3px;overflow-x:auto;padding:12px 0 6px;align-items:flex-start}
.hmcol{display:flex;flex-direction:column;gap:3px;flex:none}
.hmcell{width:11px;height:11px;border-radius:2.5px;background:var(--sunk);cursor:default}
.hmcell.l1{background:var(--accLine)}
.hmcell.l2{background:var(--acc);opacity:.72}
.hmcell.l3{background:var(--acc)}
.hmcell.l4{background:var(--acc);box-shadow:inset 0 0 0 1px var(--paper)}
.hmcell.miss{background:transparent;box-shadow:inset 0 0 0 1px var(--edge)}
.hmcell.today{outline:1.5px solid var(--z4);outline-offset:1px}
.hmmon{display:flex;gap:3px;font-family:var(--mono);font-size:8.5px;color:var(--dim);font-weight:700;
  padding-bottom:4px}
.hmmon span{flex:none;width:11px}
.hmleg{display:flex;align-items:center;gap:6px;font-family:var(--mono);font-size:9.5px;color:var(--dim);
  font-weight:650;margin-top:8px}
.hmleg i{width:11px;height:11px;border-radius:2.5px;display:block}
.streaks{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:12px;margin-top:12px;
  padding:14px;background:var(--sunk);border-radius:var(--r)}
.streaks u{display:block;text-decoration:none;font-family:var(--mono);font-size:8.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--dim);font-weight:750}
.streaks b{font-family:var(--mono);font-size:20px;font-weight:780;font-variant-numeric:tabular-nums}
.prlist{display:grid;gap:1px;background:var(--edgeSoft);border:1px solid var(--edgeSoft);
  border-radius:var(--r2);overflow:hidden;margin-top:12px}
.prrow{display:flex;align-items:center;gap:11px;padding:9px 12px;background:var(--surface)}
.prrow .pd{font-family:var(--mono);font-size:11px;font-weight:750;color:var(--dim);width:52px;flex:none}
.prrow .pv{font-family:var(--mono);font-size:16px;font-weight:780;letter-spacing:-.02em;width:86px;flex:none}
.prrow .pb2{flex:1;min-width:60px;height:7px;border-radius:4px;background:var(--sunk);overflow:hidden}
.prrow .pb2 i{display:block;height:100%;background:var(--acc)}
.prrow .pn{font-size:11.5px;color:var(--muted);flex:none}
.prrow.empty{opacity:.5}
.prrow .pv.free{color:var(--muted);font-weight:600;font-size:13px}
/* The records page's "this block" vs "all-time" comparison — two independent
   .prlist columns (each already self-labels every row) under one header, so
   the header is its own small grid rather than trying to line up with rows
   that are not a grid at all. */
.prcmp-hd{display:grid;grid-template-columns:1fr 1fr;gap:14px;font-family:var(--mono);font-size:9px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--dim);font-weight:700;padding:0 2px 6px}
.prcols{display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:start}
.prcols .prlist{margin-top:0}
.prcols .prrow .pn{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media(max-width:720px){ .prcmp-hd,.prcols{grid-template-columns:1fr} }

/* ============ RACE BOARD ============ */
.raceh{display:flex;flex-wrap:wrap;align-items:flex-end;gap:20px;padding:6px 0 16px}
.raceh .cd{font-family:var(--mono);font-size:clamp(40px,9vw,74px);font-weight:800;letter-spacing:-.05em;
  line-height:.92;color:var(--acc);font-variant-numeric:tabular-nums}
.raceh .cdu{font-family:var(--mono);font-size:11px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--dim);font-weight:750;margin-top:6px}
.raceh .rn{font-size:22px;font-weight:820;letter-spacing:-.03em}
.raceh .rd{font-family:var(--mono);font-size:12px;color:var(--muted);font-weight:650;margin-top:3px}
.racesel{margin-left:auto}
.tband{position:relative;height:34px;border-radius:8px;background:var(--sunk);margin:14px 0 6px;overflow:hidden}
.tband .in{position:absolute;top:0;bottom:0;background:var(--okSoft);border-left:1px solid var(--okLine);
  border-right:1px solid var(--okLine)}
.tband .mk{position:absolute;top:0;bottom:0;width:2px;background:var(--acc)}
.tband .mk.now{background:var(--z4)}
.tband .lb{position:absolute;top:8px;font-family:var(--mono);font-size:10px;font-weight:750;
  transform:translateX(-50%);white-space:nowrap}

/* ============ WHAT-IF ============ */
.scn{display:grid;grid-template-columns:repeat(auto-fit,minmax(268px,1fr));gap:12px;margin-top:12px}
.scnc{background:var(--surface);border:1px solid var(--edgeSoft);border-radius:var(--r);padding:14px}
.scnc.a{border-top:3px solid var(--z1)}
.scnc.b{border-top:3px solid var(--acc)}
.scnc h4{margin:0 0 10px}
.scnv{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:10px;padding-top:10px;
  border-top:1px solid var(--edgeSoft)}
.scnv u{display:block;text-decoration:none;font-family:var(--mono);font-size:8.5px;letter-spacing:.11em;
  text-transform:uppercase;color:var(--dim);font-weight:750}
.scnv b{font-family:var(--mono);font-size:18px;font-weight:780;font-variant-numeric:tabular-nums}
.knob{display:flex;align-items:center;gap:10px;margin:9px 0}
.knob label{flex:1;font-size:12.5px;color:var(--muted)}
.knob input[type=range]{flex:1.4;padding:0;background:transparent;border:0;accent-color:var(--acc)}
.knob .kv{font-family:var(--mono);font-size:12px;font-weight:750;width:52px;text-align:right}

/* ============ HEAT ============ */
.heatgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:12px;margin-top:12px}
.heatd{display:flex;gap:3px;align-items:flex-end;height:96px;margin-top:14px}
.heatd .hb{flex:1;min-width:0;background:var(--sunk);border-radius:3px 3px 0 0;position:relative}
.heatd .hb i{position:absolute;left:0;right:0;bottom:0;border-radius:3px 3px 0 0;background:var(--z4)}
.heatd .hb.q i{background:var(--z5)}

/* ============ ROTATION ============ */
.rotstrip{display:flex;gap:3px;flex-wrap:wrap;margin-top:12px}
.rotw{flex:1 1 42px;min-width:42px;border-radius:7px;padding:7px 4px;text-align:center;
  border:1px solid var(--edgeSoft);background:var(--surface)}
.rotw.sea{background:var(--sunk);border-color:var(--edge)}
.rotw.now{border-color:var(--acc);box-shadow:0 0 0 1px var(--acc)}
.rotw u{display:block;text-decoration:none;font-family:var(--mono);font-size:8px;color:var(--dim);font-weight:750}
.rotw b{font-size:13px;display:block;margin-top:2px}
.rotw .wk{font-family:var(--mono);font-size:8.5px;color:var(--muted);font-weight:650}

/* ============ COLLAPSIBLE GROUP ============ */
.fold>summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:9px;padding:9px 2px;
  font-size:13px;font-weight:750;border-bottom:1px solid var(--edgeSoft);margin-top:6px}
.fold>summary::-webkit-details-marker{display:none}
.fold>summary::before{content:"▸";font-size:10px;color:var(--dim);transition:transform .12s;flex:none}
.fold[open]>summary::before{transform:rotate(90deg)}
.fold>summary:hover{color:var(--acc)}
.fold>summary .n{margin-left:auto;font-family:var(--mono);font-size:10px;color:var(--dim);font-weight:600}
.fold>summary .n b{color:var(--paper)}

/* ============ LAYOUT PREFERENCES ============ */
html[data-width=full] .wrap{max-width:none}
html[data-density=compact] body{font-size:14px}
html[data-density=compact] .panel{padding:13px;margin:13px 0}
html[data-density=compact] .panel h3{font-size:14px;margin-bottom:9px}
html[data-density=compact] .panel h4{margin:12px 0 7px}
html[data-density=compact] .ses{margin-bottom:6px}
html[data-density=compact] .week{margin-top:15px}
html[data-density=compact] .lib{gap:7px;grid-template-columns:repeat(auto-fill,minmax(232px,1fr))}
html[data-density=compact] .libc{padding:9px}
html[data-density=compact] .libc svg{height:22px;margin-bottom:6px}
html[data-density=compact] .libc .d{max-height:34px}
html[data-density=compact] .wrap{padding-bottom:90px}
html[data-density=compact] .help{font-size:12.5px;line-height:1.55}
html[data-density=compact] .day{padding:7px 0;gap:10px;grid-template-columns:70px 1fr}
html[data-density=compact] .dcol .dn{font-size:17px}
html[data-density=compact] .ses-h{padding:7px 10px;gap:8px}
html[data-density=compact] .week-h{padding:6px 0;gap:8px}
html[data-density=compact] .zbar{margin:6px 0 3px;height:5px}
html[data-density=compact] .rowbtns{margin-top:7px;gap:5px}

/* Library as a dense list instead of cards: same data, a fifth of the height. */
.librow{display:grid;grid-template-columns:34px minmax(0,2.2fr) auto auto;gap:10px;align-items:center;
  padding:7px 9px;border:1px solid var(--edgeSoft);border-radius:8px;background:var(--surface);margin-bottom:4px}
.librow:hover{border-color:var(--acc)}
.librow svg{width:34px;height:16px;display:block;border-radius:3px}
.librow .t{font-size:13px;font-weight:650;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.librow .m{font-family:var(--mono);font-size:10px;color:var(--muted);font-weight:600;white-space:nowrap}
.librow .b{display:flex;gap:4px}
@media(max-width:720px){.librow{grid-template-columns:28px minmax(0,1fr);row-gap:6px}
  .librow .m,.librow .b{grid-column:1/-1}}

/* ============ WEEK / DAY ============ */
.week{margin:22px 0 0}
.week-h{display:flex;align-items:center;gap:11px;padding:9px 0;border-bottom:2px solid var(--edge);flex-wrap:wrap}
.week-h .id{font-size:14px;letter-spacing:-.01em;font-weight:800;color:var(--paper)}
.week-h .rng{font-family:var(--mono);font-size:11px;color:var(--dim);font-weight:600}
.week-h .kv{font-family:var(--mono);font-size:11px;color:var(--muted)}
.week-h .kv b{color:var(--paper);font-weight:750;font-size:12.5px}
.tag{font-family:var(--mono);font-size:9px;padding:3px 8px;border-radius:999px;letter-spacing:.07em;text-transform:uppercase;font-weight:700}
.tag.dl{background:var(--accSoft);color:var(--acc);border:1px solid var(--accLine)}
.week-h .sp{margin-left:auto;display:flex;gap:6px}
.zbar{display:flex;gap:2px;height:7px;border-radius:4px;overflow:hidden;margin:9px 0 4px;background:var(--sunk)}
.zbar i{display:block;height:100%}
.zleg{display:flex;flex-wrap:wrap;gap:10px;font-family:var(--mono);font-size:10px;color:var(--dim);padding-bottom:4px;font-weight:600}
.zleg span{display:flex;align-items:center;gap:4px}
.zleg em{width:8px;height:8px;border-radius:2px;font-style:normal}
.day{display:grid;grid-template-columns:86px 1fr;gap:14px;padding:12px 0;border-bottom:1px solid var(--edgeSoft)}
.day.past{opacity:.55}
.dcol .dn{font-family:var(--mono);font-size:22px;font-weight:750;letter-spacing:-.035em;line-height:1}
.dcol .dw{font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-top:4px;font-weight:600}
.dcol .dx{font-family:var(--mono);font-size:10px;color:var(--acc);margin-top:3px;font-weight:700}
.dcol .dt{font-family:var(--mono);font-size:10px;color:var(--dim);margin-top:3px;font-weight:600}
.day.today .dn{color:var(--acc)}
.day.today .dcol{border-left:3px solid var(--acc);margin-left:-10px;padding-left:7px}

/* ============ SESSION ============ */
.ses{background:var(--surface);border:1px solid var(--edge);border-radius:var(--r);margin-bottom:9px;
  overflow:hidden;box-shadow:var(--sh1)}
.ses:hover{border-color:var(--edge2);box-shadow:var(--sh2)}
.ses.sel{border-color:var(--acc);box-shadow:0 0 0 1px var(--acc),var(--sh2)}
.ses.q{border-left:4px solid var(--z4)}
/* Done is the BOX, not the stripe. It used to repaint the left edge with --z2,
   which threw away the one thing that edge is for — the dominant zone — and
   spent a validated data colour on a state. The fill says "done" and the stripe
   goes on saying what kind of session it was. */
.ses.dn{background:var(--done);border-color:var(--doneEdge)}
.ses.sel.q{border-left-color:var(--acc)}
.ses-h{display:flex;align-items:center;gap:11px;padding:11px 13px;cursor:pointer}
/* --hover is translucent in both themes, so it darkens the done tint rather
   than replacing it — a completed card must not lose its colour under the mouse */
.ses-h:hover{background:var(--hover)}
.ses:not(.dn) .ses-h:hover{background:var(--raise)}
.ses-h input[type=checkbox]{accent-color:var(--acc);width:16px;height:16px;flex:none;cursor:pointer}
.ico{width:22px;text-align:center;flex:none;font-size:15px}
.ses-t{flex:1;min-width:0}
.ses-t .nm{font-size:14.5px;font-weight:700;letter-spacing:-.015em}
.ses-t .mt{font-family:var(--mono);font-size:10.5px;color:var(--muted);margin-top:4px;font-weight:600}
.ses-t .mt b{color:var(--z4t)}.ses-t .mt u{text-decoration:none;color:var(--z5)}
.ses-t .mt i{font-style:normal;color:var(--acc)}
.mets{display:flex;gap:13px;flex:none;text-align:right}
.mets div{font-family:var(--mono);font-variant-numeric:tabular-nums}
.mets u{display:block;text-decoration:none;font-size:9px;letter-spacing:.09em;text-transform:uppercase;color:var(--dim);font-weight:600}
.mets b{font-size:14.5px;font-weight:750}
.prof{display:block;width:100%;height:42px;background:var(--profbg)}
.ses-b{padding:14px;border-top:1px solid var(--edge);background:var(--raise)}
/* the step table needs about 640px to show what is typed in it; the drawer is
   460px. It scrolls in its own box rather than compressing the number fields
   into something you cannot read your own value out of. */
.stepwrap{overflow-x:auto;max-width:100%}
.stepwrap table.steps{min-width:790px}  /* +2 columns for §1b-str: exercise, reps */
table.steps{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:12px}
table.steps th{text-align:left;font-weight:700;color:var(--dim);font-size:9px;letter-spacing:.1em;
  text-transform:uppercase;padding:0 6px 7px 0;border-bottom:1px solid var(--edge)}
table.steps td{padding:5px 6px 5px 0;border-bottom:1px solid var(--edgeSoft);vertical-align:middle}
table.steps input,table.steps select{padding:4px 6px;font-size:11.5px;width:100%;font-family:var(--mono);border-radius:5px}
table.steps td.zc{width:5px;padding:0}
table.steps td.zc div{width:5px;height:24px;border-radius:3px}
td.res{font-size:11.5px;color:var(--acc);white-space:nowrap;font-weight:700}
.w-nm{width:18%}.w-n{width:56px}.w-t{width:74px}.w-a{width:78px}.w-p{width:58px}.w-r{width:46px}.w-e{width:120px}.w-i{width:88px}.w-x{width:26px}
.notes{width:100%;min-height:60px;margin-top:11px;font-size:13px;line-height:1.55;resize:vertical}
/* ---- the READ-ONLY session view ----
   Clicking a workout opens this, not the editor: what am I doing, how long,
   at what, and what do I eat. Editing is a separate mode behind the pen, so
   the thing you touch every day cannot be changed by a stray keystroke. */
.sv{padding:14px;border-top:1px solid var(--edge);background:var(--raise)}
.drawer-b .sv{border:0;padding:2px 0 0;background:transparent}
.sv-hd{display:flex;flex-wrap:wrap;gap:16px;padding-bottom:12px;border-bottom:1px solid var(--edge)}
.sv-hd div{font-family:var(--mono);font-variant-numeric:tabular-nums}
.sv-hd u{display:block;text-decoration:none;font-size:9px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--dim);font-weight:600}
.sv-hd b{font-size:17px;font-weight:750;letter-spacing:-.02em}
.sv-tg{display:grid;grid-template-columns:auto 1fr;gap:5px 14px;margin-top:12px;align-items:baseline}
.sv-tg dt{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--dim);font-weight:700}
.sv-tg dd{font-family:var(--mono);font-size:13px;font-weight:700}
.sv-tg dd.free{color:var(--muted);font-weight:600}
.sv-lbl{font-family:var(--mono);font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--dim);font-weight:700;margin:15px 0 6px}
table.svsteps{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:12px}
table.svsteps th{text-align:left;font-weight:700;color:var(--dim);font-size:9px;letter-spacing:.1em;
  text-transform:uppercase;padding:0 8px 6px 0;border-bottom:1px solid var(--edge)}
table.svsteps td{padding:6px 8px 6px 0;border-bottom:1px solid var(--edgeSoft);vertical-align:middle}
table.svsteps td.zc{width:5px;padding:0}
table.svsteps td.zc div{width:5px;height:22px;border-radius:3px}
table.svsteps td.tg{color:var(--acc);font-weight:700;white-space:nowrap}
table.svsteps td.ty{color:var(--muted);font-size:10.5px;text-transform:uppercase;letter-spacing:.06em}
table.svsteps td.rp{font-weight:750}
/* Planned-vs-completed and the min/avg/max table under a logged session —
   the layout borrowed from a TrainingPeaks activity screen, redrawn in this
   app's own furniture rather than copied wholesale. A row prints an em dash
   on either side where there is nothing to show, same as a blank cell there,
   because a guessed number is worse than an honest gap. */
.pvc{margin-top:14px;border:1px solid var(--edge);border-radius:var(--r2);overflow:hidden}
.pvc-hd{display:grid;grid-template-columns:1fr 100px 100px;background:var(--sunk);
  font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);
  font-weight:700;padding:7px 12px}
.pvc-hd span:nth-child(2),.pvc-hd span:nth-child(3){text-align:right}
.pvc-rows{display:grid;grid-template-columns:1fr 100px 100px;margin:0;padding:2px 12px}
.pvc-rows dt{grid-column:1;font-size:12px;font-weight:650;padding:6px 0;border-bottom:1px solid var(--edgeSoft)}
.pvc-rows dd{font-family:var(--mono);font-size:12.5px;font-weight:700;text-align:right;
  margin:0;padding:6px 0;border-bottom:1px solid var(--edgeSoft)}
.pvc-rows dd .free,.pvc-rows dd span.free{color:var(--muted);font-weight:600}
.mmtab{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:12px;margin-top:8px}
.mmtab th{text-align:right;font-weight:700;color:var(--dim);font-size:9px;letter-spacing:.08em;
  text-transform:uppercase;padding:0 0 6px 10px}
.mmtab th:first-child{text-align:left;padding-left:0}
.mmtab td{padding:5px 0 5px 10px;border-bottom:1px solid var(--edgeSoft);text-align:right}
.mmtab td:first-child{text-align:left;font-weight:650;padding-left:0}
.elevp{position:relative;margin-top:10px;border:1px solid var(--edge);border-radius:var(--r2);
  overflow:hidden;background:var(--sunk)}
.elevp svg{display:block;width:100%;height:36px}
.elevp-lo,.elevp-hi{position:absolute;right:8px;font-family:var(--mono);font-size:9px;
  color:var(--dim);font-weight:700;pointer-events:none}
.elevp-hi{top:3px}
.elevp-lo{bottom:3px}
.sv-done{display:inline-flex;align-items:center;gap:6px;margin-left:auto;align-self:center;
  font-family:var(--mono);font-size:10.5px;font-weight:750;padding:4px 9px;border-radius:999px;
  background:var(--done);border:1px solid var(--doneEdge)}
/* the pen. An icon button, so the row of actions does not read as five equal
   words with "Edit" buried among them. */
.btn-pen{font-size:14px;line-height:1;padding:5px 9px}
.rowbtns{display:flex;flex-wrap:wrap;gap:6px;margin-top:11px;align-items:center}
.log{display:grid;grid-template-columns:repeat(auto-fit,minmax(90px,1fr));gap:9px;margin-top:11px;padding:12px;
  background:var(--surface);border:1px solid var(--edge);border-radius:9px}
.log.on{background:var(--okSoft);border-color:var(--okLine)}
.log .fld label{font-size:9px}
.log input,.log select{width:100%;font-family:var(--mono);font-size:12px;padding:5px 7px}
.act{font-family:var(--mono);font-size:10px;color:var(--z2);font-weight:700}
.act.over{color:var(--z4t)}
.ses[draggable=true],.libc[draggable=true]{cursor:grab}
.ses.drag,.libc.drag{opacity:.35}
.day.drop{background:var(--accSoft);outline:2px dashed var(--acc);outline-offset:3px;border-radius:9px}
.placing .day,.placing .wday,.placing .mcell:not(.out){outline:2px dashed var(--acc);outline-offset:-3px;border-radius:9px;cursor:pointer}
.ses.picked,.libc.picked,.librow.picked{outline:2.5px solid var(--acc);outline-offset:2px}

/* ============ PANELS ============ */
.panel{background:var(--surface);border:1px solid var(--edgeSoft);border-radius:var(--r);padding:20px;margin:20px 0}
.panel h3{font-size:15px;font-weight:800;letter-spacing:-.02em;color:var(--paper);margin-bottom:13px;border-left:3px solid var(--acc);padding-left:10px;line-height:1.3}
.panel h4{font-size:13px;font-weight:750;margin:18px 0 9px;display:flex;align-items:center;gap:8px}
/* `.row` carried align-items/gap as an inline style at its one call site
   (the "What the app calls you" panel) with no `display:flex` behind it —
   which did nothing on a short name and let a long one run the "Change it"
   button underneath it on a narrow column, because plain inline flow does not
   wrap a bold name and an inline-block button the way flex does. The class is
   the real fix, not a one-off style: `min-width:0` lets its flex children
   shrink instead of overflowing, and `flex-wrap` drops the button to its own
   line rather than clipping or overlapping it when the name alone fills the
   row. */
.row{display:flex;flex-wrap:wrap;min-width:0}
.grid{display:grid;gap:12px}
.g4{grid-template-columns:repeat(auto-fit,minmax(116px,1fr))}
.bld{display:grid;grid-template-columns:repeat(auto-fit,minmax(152px,1fr));gap:12px}
.fld label{display:block;font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-bottom:5px;font-weight:700}
.fld input,.fld select{width:100%;font-family:var(--mono);font-variant-numeric:tabular-nums}
.kpi{font-family:var(--mono);font-size:22px;font-weight:800;font-variant-numeric:tabular-nums;letter-spacing:-.02em}
table.zt{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:12px}
table.zt th{text-align:left;color:var(--dim);font-size:9px;letter-spacing:.1em;text-transform:uppercase;padding:0 10px 8px 0;font-weight:750}
table.zt td{padding:6px 10px 6px 0;border-top:1px solid var(--edgeSoft);font-variant-numeric:tabular-nums}
table.zt tbody tr:hover{background:var(--raise)}
table.zt td.k{display:flex;align-items:center;gap:8px;font-weight:600}
table.zt i{width:10px;height:10px;border-radius:3px;display:block;flex:none}
/* ── Schedule a workout: the session on the left, a month on the right ──
   A dropdown of dates was the wrong control for choosing a day, because it
   hides everything that makes one day different from another. The calendar
   carries four signals the app already holds, and each is drawn as itself:
   what is planned (dots and a duration), whether it FITS (struck through),
   whether the day is already over its window (an amber edge), and today. */
.wsbox{background:var(--surface);border:1px solid var(--edge);border-radius:var(--r);
  box-shadow:var(--sh2);width:min(1040px,94vw);max-height:92vh;display:flex;flex-direction:column}
.wshead{display:flex;align-items:center;gap:10px;padding:12px 14px;border-bottom:1px solid var(--edgeSoft)}
.wsbody{display:grid;grid-template-columns:1fr 340px;gap:0;overflow:hidden;min-height:0}
.wsleft{padding:14px;overflow-y:auto;min-width:0}
.wsright{padding:14px;border-left:1px solid var(--edgeSoft);overflow-y:auto;background:var(--bg)}
@media(max-width:880px){ .wsbody{grid-template-columns:1fr}
  .wsright{border-left:0;border-top:1px solid var(--edgeSoft)} }
.wsmh{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}
.wsdow{display:grid;grid-template-columns:repeat(7,1fr);gap:3px;margin-bottom:3px}
.wsdow i{font-family:var(--mono);font-size:9px;color:var(--dim);text-align:center;font-style:normal;
  letter-spacing:.1em}
.wsgrid{display:grid;grid-template-columns:repeat(7,1fr);gap:3px}
.wsc{min-height:44px;border:1px solid var(--edgeSoft);border-radius:7px;background:var(--surface);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;padding:3px 1px;
  cursor:pointer;font-family:var(--mono)}
.wsc:hover{border-color:var(--acc)}
.wsc .dn{font-size:12px;font-weight:700;line-height:1}
.wsc .ds2{font-size:8.5px;color:var(--dim);line-height:1}
.wsc .dots{display:flex;gap:2px}
.wsc .dots i{width:3px;height:3px;border-radius:50%;background:var(--acc);display:block}
.wsc.out{opacity:.35}
.wsc.past{opacity:.5}
.wsc.now{border-color:var(--acc);box-shadow:inset 0 0 0 1px var(--acc)}
/* Struck through rather than hidden: envFits() is the app's one refusal and it
   already puts the number in words. Nothing disappears silently here either. */
.wsc.nofit .dn{text-decoration:line-through;color:var(--dim)}
.wsc.nofit{background:var(--raise)}
.wsc.over{border-color:var(--z3)}
.wsc.lv-red{box-shadow:inset 0 0 0 2px var(--z5)}
.wsc.lv-amber{box-shadow:inset 0 0 0 2px var(--z3)}
.wsc.lv-green{box-shadow:inset 0 0 0 2px var(--z2)}
.wsc.on{background:var(--acc);border-color:var(--acc)}
.wsc.on .dn,.wsc.on .ds2{color:var(--accInk)}
.wsc.on .dots i{background:var(--accInk)}
.wslegend{display:flex;flex-wrap:wrap;gap:10px;margin-top:8px;font-family:var(--mono);font-size:9px;
  color:var(--dim)}
.wslegend span{display:flex;align-items:center;gap:4px}
.wslegend i{width:9px;height:9px;border-radius:3px;display:block;border:1px solid var(--edge)}
.wslegend .l-now{border-color:var(--acc)}
.wslegend .l-no{background:var(--raise)}
.wslegend .l-p{background:var(--acc);border-color:var(--acc)}
.wslegend .l-ov{border-color:var(--z3)}
.wspick{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:12px}
.wspick div{background:var(--surface);border:1px solid var(--edgeSoft);border-radius:7px;padding:7px 9px}
.wspick u{display:block;font-family:var(--mono);font-size:8.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--dim);text-decoration:none}
.wspick b{font-size:12px}
/* .tb — THE CLASS THAT WAS NEVER DEFINED. Two views ask for it, the availability
   table and the daily-health history, and there has never been a rule for it
   anywhere in this stylesheet: no padding, no borders, no alignment, so nine
   right-aligned headers ran into one another as "HRVResting HRSleepSleep
   quality". It reads as a rendering fault rather than as a table.
   Styled as table.zt's sibling rather than as something new, because it is the
   same object doing the same job — a read-back grid of numbers — and a second
   look for the same thing is how two tables in one app stop matching. Numbers
   get tabular figures so columns line up; the first column is the row's handle
   and stays left. */
.tb{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:12px}
.tb th{text-align:right;color:var(--dim);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  padding:0 0 8px 14px;font-weight:750;white-space:nowrap}
.tb th:first-child,.tb td:first-child{text-align:left;padding-left:0}
.tb td{padding:6px 0 6px 14px;border-top:1px solid var(--edgeSoft);text-align:right;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.tb tbody tr:hover{background:var(--raise)}
/* A blank cell is a day you did not log, and it should recede rather than line
   up as a wall of dashes competing with the numbers beside it. */
.tb td.nil{color:var(--edge)}
/* The movements on a strength card, in place of a power profile that could not
   mean anything there. Sized as data rather than as a heading: the card's title
   is still the session, and these are what is in it. */
.mvs{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:2px}
.mvs .mv{font-family:var(--mono);font-size:10px;line-height:1.5;padding:2px 7px;border-radius:999px;
  background:var(--raise);border:1px solid var(--edgeSoft);color:var(--muted);white-space:nowrap;
  max-width:100%;overflow:hidden;text-overflow:ellipsis}
.mvs .mv b{font-weight:650;color:var(--paper)}
.mvs .mv em{font-style:normal;color:var(--str);font-weight:750;margin-left:3px}
.mvs .mv.more{color:var(--dim)}
.librow .mvs{margin:0;flex-wrap:nowrap;overflow:hidden;max-width:190px}
.lib{display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(268px,1fr))}
.libc{background:var(--surface);border:1px solid var(--edge);border-radius:var(--r);padding:12px;box-shadow:var(--sh1)}
.libc:hover{border-color:var(--acc);box-shadow:var(--sh2)}
.libc .t{font-size:14.5px;font-weight:750;letter-spacing:-.012em;margin-top:2px}
.libc .m{font-family:var(--mono);font-size:10px;color:var(--muted);margin:4px 0 7px;font-weight:600}
.libc .d{font-size:11.5px;color:var(--dim);line-height:1.45;margin-bottom:9px;max-height:52px;overflow:hidden}
.libc .b{display:flex;gap:5px;flex-wrap:wrap}
.libc .b.sec{margin-top:7px}
.libc svg{display:block;width:100%;height:30px;margin-bottom:8px;border-radius:5px}
/* The badge over the graphic and the icon-chip row are what the mock the owner
   liked actually is: the category read at a glance instead of buried in the
   type filter, and IF as its own figure instead of after a middot in mono
   text. Picked from the card's OWN data (L.tag, metrics()) — never a second
   opinion, same rule libMeta() already followed. */
.libgfx{position:relative}
.libgfx .mvs{padding-right:62px}
.libtag{position:absolute;top:6px;right:6px;background:rgba(0,0,0,.55);color:#fff;font-size:9px;
  font-weight:700;letter-spacing:.03em;padding:3px 8px;border-radius:999px;text-transform:uppercase;
  pointer-events:none;max-width:calc(100% - 12px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.libchips{display:flex;flex-wrap:wrap;gap:5px;margin:5px 0 8px}
.libchip{font-family:var(--mono);font-size:10px;font-weight:650;color:var(--muted);background:var(--sunk);
  border:1px solid var(--edge);border-radius:999px;padding:3px 8px;display:inline-flex;align-items:center;gap:3px}
.libchip.acc{color:var(--acc);border-color:var(--accLine);background:var(--accSoft)}
.libcta{width:100%;justify-content:center;display:flex;align-items:center;gap:5px;border-radius:999px}
.libcta span{display:inline-block;transition:transform .15s}
.libc:hover .libcta span{transform:translateX(2px)}
.filters{display:flex;flex-wrap:wrap;gap:7px;align-items:center;margin-top:6px}
.pillbtn{font-family:var(--mono);font-size:11px;letter-spacing:.03em;padding:6px 12px;border-radius:999px;
  border:1px solid var(--edge);background:var(--surface);color:var(--muted);font-weight:650}
.pillbtn:hover{border-color:var(--acc);color:var(--acc);background:var(--surface)}
.pillbtn.on{background:var(--acc);border-color:var(--acc);color:var(--accInk);font-weight:750}
.pillbtn.on:hover{background:var(--accHi);color:var(--accInk)}
/* calendar */
.cal{display:grid;grid-template-columns:38px repeat(7,1fr);gap:4px}
.cal .hd{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);text-align:center;padding:6px 0;font-weight:750}
.cal .wn{font-family:var(--mono);font-size:10px;color:var(--dim);display:flex;align-items:center;justify-content:center;
  background:var(--sunk);border-radius:6px;font-weight:750}
.cell{background:var(--surface);border:1px solid var(--edge);border-radius:8px;min-height:70px;padding:5px 7px;position:relative;cursor:pointer;box-shadow:var(--sh1)}
.cell.empty{background:transparent;border-color:transparent;cursor:default;box-shadow:none}
.cell:hover:not(.empty){border-color:var(--acc);box-shadow:var(--sh2)}
.cell.today{border-color:var(--acc);box-shadow:0 0 0 1px var(--acc)}
.cell .n{font-family:var(--mono);font-size:11px;color:var(--muted);font-weight:700}
.cell.today .n{color:var(--acc)}
.cell .t{font-family:var(--mono);font-size:11.5px;font-weight:700;margin-top:2px}
.cell .s{display:flex;gap:2px;margin-top:5px;flex-wrap:nowrap}
.cell .s i{height:5px;flex:1 1 auto;min-width:4px;border-radius:2px}
.cell .bk{position:absolute;right:6px;top:4px;font-family:var(--mono);font-size:9px;color:var(--dim);font-weight:700}
.cell .bd{position:absolute;left:0;top:0;bottom:0;width:4px;border-radius:7px 0 0 7px}
svg.chart{display:block;width:100%;height:240px}
svg.wbars{display:block;width:100%;height:175px}
.legend{display:flex;gap:15px;flex-wrap:wrap;font-family:var(--mono);font-size:10.5px;color:var(--dim);margin-top:10px;font-weight:600}
.legend span{display:flex;align-items:center;gap:6px}
.legend em{width:15px;height:3px;font-style:normal;display:block;border-radius:2px}
/* tray */
/* The shadow belongs to the tray only while the tray is up. Off-screen it was
   still casting a 26px gradient up the bottom of every page — invisible to the
   eye, and enough to make the screenshot harness measure every view as running
   the full height of its capture. */
.tray{position:fixed;left:var(--rail);right:0;bottom:0;z-index:50;background:var(--topbg);backdrop-filter:blur(12px);
  border-top:2px solid var(--acc);transform:translateY(115%);transition:transform .18s ease,left .2s ease}
.tray.up{transform:none;box-shadow:var(--shUp)}
.tray.full{left:0}
body.hasctx .tray{right:var(--ctxw)}
@media(max-width:1279px){ body.hasctx .tray{right:0} }
@media (prefers-reduced-motion:reduce){.tray{transition:none}}
.tray .in{max-width:1120px;margin:0 auto;padding:13px 18px;display:flex;flex-wrap:wrap;gap:9px;align-items:center}
.tray .cnt{font-family:var(--mono);font-size:12px;color:var(--acc);font-weight:750}
.warn{font-family:var(--mono);font-size:11px;color:var(--z4t);font-weight:600}
.help{font-size:13.5px;color:var(--muted);line-height:1.65}
.help b{color:var(--paper);font-weight:700}
.help p+p{margin-top:10px}
.help code{font-family:var(--mono);font-size:12px;background:var(--sunk);border:1px solid var(--edgeSoft);padding:2px 6px;border-radius:5px;color:var(--acc);font-weight:600}
.help ol{margin:8px 0 0 20px}.help li{margin:6px 0}
.hint{font-family:var(--mono);font-size:10px;color:var(--dim);margin-top:7px;font-weight:600}

/* --- athlete snapshot (now in the context column) --- */
.snap{background:var(--surface);border:1px solid var(--edgeSoft);border-radius:var(--r);overflow:hidden}
.snaptog{display:flex;align-items:center;justify-content:space-between;width:100%;background:none;border:0;
  border-radius:0;padding:11px 12px;font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dim);font-weight:750}
.snaptog:hover{background:var(--hover);color:var(--paper)}
.snapbody{padding:0 12px 12px}
.sgrp{font-family:var(--mono);font-size:8.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--acc);
  font-weight:750;margin:10px 0 5px;display:flex;justify-content:space-between;align-items:baseline}
.sgrp em{font-style:normal;color:var(--dim);letter-spacing:.06em;font-weight:600}
.sline{font-family:var(--mono);font-size:10px;color:var(--muted);margin:5px 0 0;font-weight:600}
table.stab{width:100%;border-collapse:collapse;font-family:var(--mono);font-variant-numeric:tabular-nums}
table.stab th{font-size:8px;letter-spacing:.06em;text-transform:uppercase;color:var(--dim);font-weight:750;
  text-align:right;padding:0 0 3px 4px}
table.stab th:first-child{text-align:left}
table.stab td{font-size:11px;font-weight:700;text-align:right;padding:2.5px 0 2.5px 4px;border-top:1px solid var(--edgeSoft)}
table.stab td.lb{text-align:left;color:var(--muted);font-size:9.5px;letter-spacing:.05em}
.snapedit{width:100%;margin-top:12px;font-size:11px}

/* --- global search --- */
.srchwrap{position:relative;flex:1;max-width:330px;margin-left:6px}
#srch{width:100%;padding:8px 12px;font-size:13.5px;background:var(--sunk);border-radius:999px;border-color:var(--edge)}
#srch:focus{background:var(--surface);border-color:var(--acc)}
.srchres{position:absolute;top:calc(100% + 7px);left:0;right:0;min-width:380px;background:var(--surface);
  border:1px solid var(--edge);border-radius:var(--r);box-shadow:var(--sh2);z-index:70;overflow:hidden;max-height:66vh;overflow-y:auto}
.srchres .sh{font-family:var(--mono);font-size:9px;letter-spacing:.13em;text-transform:uppercase;color:var(--dim);
  padding:10px 14px 6px;font-weight:750;background:var(--raise)}
.srchres .sr{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:none;border:0;
  border-radius:0;padding:9px 14px;border-bottom:1px solid var(--edgeSoft)}
.srchres .sr:hover,.srchres .sr.active{background:var(--accSoft)}
.srchres .sz{width:4px;height:30px;border-radius:3px;flex:none}
.srchres .st{flex:1;min-width:0;font-size:13.5px;font-weight:650;letter-spacing:-.01em}
.srchres .st em{display:block;font-style:normal;font-family:var(--mono);font-size:10px;color:var(--dim);font-weight:600;margin-top:2px}
.srchres .sm{font-family:var(--mono);font-size:11px;color:var(--muted);flex:none;font-weight:650}
/* --- keyboard overlay --- */
/* A dialog and a toast must outrank every overlay, including the sign-in
   screen (130) and focus mode (110). They did not, and the symptom was
   perfect: the ADMIN button 'did nothing', because its dialog opened
   underneath the very screen that launched it. */
.kover{position:fixed;inset:0;background:rgba(7,8,19,.5);z-index:150;display:flex;align-items:center;justify-content:center;padding:20px}
.kover.hidden{display:none}
.kbox{background:var(--surface);border:1px solid var(--edge);border-radius:var(--r);box-shadow:var(--sh2);
  padding:22px;max-width:440px;width:100%;max-height:86vh;overflow-y:auto}
.kbox h3{font-family:var(--mono);font-size:10px;letter-spacing:.15em;text-transform:uppercase;color:var(--acc);font-weight:750;margin-bottom:14px}
.krow{display:flex;align-items:center;gap:12px;padding:6px 0;border-bottom:1px solid var(--edgeSoft);font-size:13.5px}
.krow kbd{font-family:var(--mono);font-size:11.5px;background:var(--sunk);border:1px solid var(--edge);
  border-bottom-width:2px;border-radius:6px;padding:3px 8px;min-width:64px;text-align:center;font-weight:700}
/* --- the workout picker --- */
/* Wider than a .kbox because it holds a list AND a preview: choosing a workout
   without seeing its steps is what the old + asked you to do. Below 900px the
   two halves stack and the preview follows the list, which is the order you
   read them in on a phone. */
.wpbox{max-width:1080px;padding:20px 22px}
.wpfil{padding-bottom:10px;border-bottom:1px solid var(--edgeSoft)}
.wpfil .filters{margin-top:5px}
.wpfil .rowbtns{margin-top:10px}
.wphint{font-size:11.5px;color:var(--muted);margin:9px 0 4px;line-height:1.6}
.wphint kbd{font-family:var(--mono);font-size:10px;background:var(--sunk);border:1px solid var(--edge);
  border-radius:4px;padding:1px 5px;font-weight:700}
.wpgrid{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:16px;align-items:start}
.wplist{max-height:56vh;overflow-y:auto;overscroll-behavior:contain;padding-right:4px}
.wpprev{background:var(--sunk);border:1px solid var(--edge);border-radius:var(--r2);padding:14px;
  max-height:56vh;overflow-y:auto;overscroll-behavior:contain}
.wpprev h4{font-size:15px;font-weight:750;letter-spacing:-.015em;margin-bottom:7px}
.wpmeta{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:6px}
.wpmeta .tag{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  background:var(--surface);border:1px solid var(--edge);border-radius:5px;padding:2px 7px;font-weight:750;color:var(--muted)}
.wpmeta .tag.q{color:var(--z4t);border-color:var(--z4t)}
.wpempty{font-size:12.5px;color:var(--muted);line-height:1.6;padding:6px 2px}
.wpnote{font-size:12px;color:var(--muted);line-height:1.5;margin-top:9px}
.wpwarn{margin-top:10px;padding:9px 11px;border-radius:8px;background:var(--surface);
  border:1px solid var(--edge);font-size:12px;color:var(--muted);line-height:1.5}
.wpwarn b{display:block;font-family:var(--mono);font-size:9px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--z3t);font-weight:750;margin-bottom:3px}
.wpwarn.bad{border-color:var(--z5)}
.wpwarn.bad b{color:var(--z5)}
/* Shown, never hidden: a workout that will not fit here is dimmed and carries
   its own reason, in the words and numbers envFits() already produced. */
.librow.nofit,.libc.nofit{opacity:.5}
.librow.nofit:hover,.libc.nofit:hover{opacity:.8}
.librow .nof,.libc .nof{grid-column:2/-1;font-family:var(--mono);font-size:10px;color:var(--z5);
  font-weight:650;line-height:1.4;margin-top:2px}
.librow.wpon,.libc.wpon{border-color:var(--acc);box-shadow:0 0 0 1px var(--acc);opacity:1}
@media(max-width:900px){
  .wpgrid{grid-template-columns:1fr}
  .wplist{max-height:42vh}
  .wpprev{max-height:none}
  .wpbox{padding:16px 14px}
  /* A .librow is four columns wide and simply wraps in a phone-width modal:
     three workouts filled the whole list and the Add button sat on its own
     line. Name over meta, Add pinned to the right — one line each again. */
  .wplist .librow{grid-template-columns:34px minmax(0,1fr) auto;row-gap:1px;padding:7px 9px}
  .wplist .librow svg{grid-row:1/3}
  .wplist .librow .t{grid-column:2;grid-row:1;white-space:normal;font-size:12.5px;line-height:1.3}
  .wplist .librow .m{grid-column:2;grid-row:2;font-size:9.5px}
  .wplist .librow .b{grid-column:3;grid-row:1/3;align-self:center}
  .wplist .librow .nof{grid-column:2/-1;grid-row:3}
}
/* --- zone stripes on cards --- */
.ses{border-left:4px solid var(--zstripe,transparent)}
.ses.q{border-left-color:var(--z4)}
.libc{position:relative;padding-top:14px}
.libc::before{content:"";position:absolute;left:0;right:0;top:0;height:4px;background:var(--zstripe,var(--edge));
  border-radius:var(--r) var(--r) 0 0}
.libc.core{box-shadow:var(--sh1),inset 0 0 0 1px var(--accLine)}
/* --- misc --- */
@media(max-width:960px){ .srchwrap{max-width:none} .srchres{min-width:0} }
#srchBtn{display:none}
@media(max-width:700px){
  .srchwrap{display:none}
  #srchBtn{display:flex}
  .srchwrap.open{display:block;position:fixed;left:8px;right:8px;top:60px;z-index:80;margin:0;max-width:none}
  .srchwrap.open #srch{background:var(--surface);border-color:var(--acc);box-shadow:var(--sh2)}
}
/* --- plan check --- */
.panel.chk{border-left:4px solid var(--z2)}
.panel.chk h3{border-left:0;padding-left:0}
.panel.chk.warn{border-left-color:var(--z3)}
.panel.chk.bad{border-left-color:var(--z5)}
.chklist{display:grid;gap:1px;background:var(--edgeSoft);border:1px solid var(--edgeSoft);border-radius:var(--r2);overflow:hidden}
.chkrow{display:flex;align-items:flex-start;gap:10px;padding:9px 12px;background:var(--surface)}
.chkrow .dot{width:8px;height:8px;border-radius:50%;flex:none;margin-top:5px;background:var(--z3)}
.chkrow.lv2 .dot{background:var(--z5)}
.chkrow .cd{font-family:var(--mono);font-size:10.5px;color:var(--dim);flex:none;width:52px;font-weight:700;margin-top:2px}
.chkrow .ct{flex:1;min-width:0;font-size:13px}
.chkrow .ct b{display:block;font-weight:650}
.chkrow .ct em{display:block;font-style:normal;color:var(--muted);font-size:12px;margin-top:2px;line-height:1.45}

/* --- global error banner --- */
.errbar{position:fixed;left:0;right:0;top:0;z-index:120;background:var(--z5);color:#fff;
  font-size:13px;font-weight:600;padding:9px 14px;display:flex;gap:12px;align-items:center;box-shadow:var(--sh2)}
.errbar code{font-family:var(--mono);font-size:11.5px;background:rgba(0,0,0,.22);padding:2px 7px;border-radius:5px;
  max-width:46vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.errbar button{margin-left:auto;background:rgba(255,255,255,.14);border-color:transparent;color:#fff;
  padding:4px 11px;font-size:12px;border-radius:6px;flex:none}
.errbar button:hover{background:rgba(255,255,255,.26);border-color:transparent}
.toast{position:fixed;left:50%;bottom:96px;transform:translateX(-50%);z-index:155;background:var(--ink);
  color:var(--surface);font-size:13px;font-weight:650;padding:10px 18px;border-radius:22px;box-shadow:var(--sh2)}
html[data-theme=dark] .toast{color:var(--bg)}
.toast.hidden{display:none}
.fuel{margin-top:11px;padding:12px;border:1px solid var(--edge);border-radius:9px;background:var(--surface)}
.fh{font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--z3t);font-weight:750;margin-bottom:9px}
.fg{display:grid;grid-template-columns:repeat(auto-fit,minmax(84px,1fr));gap:9px}
.fg u{display:block;text-decoration:none;font-family:var(--mono);font-size:8.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--dim);font-weight:700}
.fg b{font-family:var(--mono);font-size:15px;font-weight:750;font-variant-numeric:tabular-nums}
.fn{font-size:12px;color:var(--muted);margin-top:10px;line-height:1.5}
.polbar{display:flex;gap:2px;height:8px;border-radius:4px;overflow:hidden;background:var(--sunk);min-width:110px}
.polbar i{display:block;height:100%}
.polsum{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:12px;margin-top:14px;
  padding:13px;background:var(--sunk);border-radius:9px}
.polsum u{display:block;text-decoration:none;font-family:var(--mono);font-size:8.5px;letter-spacing:.11em;
  text-transform:uppercase;color:var(--dim);font-weight:750}
.polsum b{font-family:var(--mono);font-size:17px;font-weight:750;font-variant-numeric:tabular-nums}
.calcbox{margin-top:12px;padding:11px 14px;background:var(--accSoft);border:1px solid var(--accLine);
  border-radius:9px;font-family:var(--mono);font-size:12px;color:var(--muted);font-weight:600}
.calcbox b{color:var(--paper);font-weight:750}
/* §GAINS honesty markers. A flag says a number is approximate, back-calculated
   or absent from the literature entirely, and it must read as CHROME rather than
   as a value: it borrows the muted/edge pair every other piece of chrome uses,
   exactly as the ADMIN pill does, and takes no zone variable and no accent. A
   caveat drawn in a data colour would be a caveat that looks like a reading. */
.gflag{display:inline-block;margin-top:9px;padding:3px 9px;border-radius:999px;
  border:1px dashed var(--edge);color:var(--muted);background:var(--sunk);
  font-family:var(--mono);font-size:10px;letter-spacing:.04em;font-weight:700}
/* §WRAP. A year read back to you, so the numbers are allowed to be large — this
   is the one page in the app whose job is that a figure lands. NOTHING HERE
   TAKES A ZONE VARIABLE: every quantity on it is written out in full, so colour
   encodes nothing and the chrome pair plus the accent is the whole palette. The
   one exception is the gain column in the PR table, which uses --z2 the way
   every other improvement in the app does. */
.wrp-grid{display:grid;gap:12px;margin-top:14px;
  grid-template-columns:repeat(auto-fit,minmax(132px,1fr))}
.wrp-stat{padding:14px 15px;background:var(--sunk);border:1px solid var(--edgeSoft);border-radius:10px}
.wrp-v{font-family:var(--mono);font-size:26px;font-weight:800;color:var(--paper);
  letter-spacing:-.03em;font-variant-numeric:tabular-nums;line-height:1.1}
.wrp-v span{font-size:14px;font-weight:700;color:var(--muted);letter-spacing:0}
.wrp-l{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);margin-top:6px;font-weight:700}
.wrp-s{font-size:12px;color:var(--muted);margin-top:5px}
.wrp-s b{color:var(--acc);font-weight:750}
.wrp-row{display:grid;gap:12px;margin-top:14px;
  grid-template-columns:repeat(auto-fit,minmax(184px,1fr))}
.wrp-big{padding:15px 16px;border:1px solid var(--edgeSoft);border-radius:10px;background:var(--surface)}
.wrp-bl{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);font-weight:700}
.wrp-bv{font-size:21px;font-weight:800;color:var(--paper);letter-spacing:-.02em;margin-top:7px}
.wrp-bs{font-size:12px;color:var(--muted);margin-top:5px;line-height:1.5}
/* §9a small charts. Sized by CSS, drawn by a viewBox — nothing here measures
   anything or needs re-running on resize. `preserveAspectRatio:none` is
   deliberate on the line charts: the shape of a trend is what is being read,
   not its gradient in degrees. */
.mchart{display:block;width:100%;margin-top:10px;overflow:visible}
.ch-form{height:56px}
.ch-vol{height:56px}
.ch-heat{height:42px}
.ch-zone{height:15px;border-radius:4px;overflow:hidden;margin-top:9px}
.chleg{display:flex;align-items:center;flex-wrap:wrap;gap:4px 9px;margin-top:6px;
  font-family:var(--mono);font-size:9px;letter-spacing:.05em;color:var(--dim);font-weight:650}
.chleg i{width:8px;height:8px;border-radius:2px;display:inline-block;margin-right:-4px}
.chleg em{font-style:normal;margin-left:auto;opacity:.75}
/* twenty-eight days, one square each — the consistency heatmap in miniature */
.ch28{display:grid;grid-template-columns:repeat(14,1fr);gap:3px;margin-top:10px}
.ch28 i{display:block;aspect-ratio:1;border-radius:2px;background:var(--grid)}
.ch28 i.e1{background:var(--z5);opacity:.5}
.ch28 i.e2{background:var(--z3t);opacity:.7}
.ch28 i.e3{background:var(--z2)}
/* §6b block builder: one row per weekday, and a seven-cell read-back of what
   the planner decided to do with them */
.bbgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(288px,1fr));gap:8px 16px;margin-top:10px}
.bbrow{display:grid;grid-template-columns:92px 78px 1fr;gap:7px;align-items:center}
.bbrow label{font-family:var(--mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);font-weight:700}
.bbrow .bbin{font-family:var(--mono);font-size:11px;font-variant-numeric:tabular-nums;width:100%}
.bbweek{display:grid;grid-template-columns:repeat(7,1fr);gap:5px}
.bbweek .bbcell{padding:7px 5px;border-radius:7px;background:var(--sunk);text-align:center;line-height:1.35}
.bbweek .bbcell b{display:block;font-family:var(--mono);font-size:9px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dim);font-weight:750}
.bbweek .bbcell span{display:block;font-family:var(--mono);font-size:12px;font-weight:750;color:var(--paper);
  font-variant-numeric:tabular-nums}
.bbweek .bbcell em{display:block;font-style:normal;font-family:var(--mono);font-size:8.5px;color:var(--muted);font-weight:650}
.bbweek .bbrest span,.bbweek .bbrest em{color:var(--dim)}
.bbdrop{margin-top:9px;padding:9px 11px;border-radius:8px;background:var(--sunk);border-left:3px solid var(--z4)}
.bbdrop ul{margin:5px 0 0;padding-left:17px}
.bbdrop li{margin:3px 0;color:var(--muted)}
@media(max-width:620px){ .bbweek{grid-template-columns:repeat(4,1fr)} }
/* §6c availability: one row, drawn above the week grid and on its own page.
   Every one of these numbers is editable and none of them looked it — a mono
   figure on a flat tile reads as a printed summary, and the strip above the
   week grid was a <details> with its marker hidden, so it read as a heading
   with nothing under it. The accent is the fix, and this is precisely what the
   accent is for here: it never encodes data, it means "you can touch this"
   everywhere else in the app, and it says the same thing here. */
.avrow{display:grid;grid-template-columns:repeat(7,1fr);gap:6px;margin-top:10px}
.avc{padding:8px 6px;border-radius:8px;background:var(--sunk);text-align:center;
  border:1px solid transparent;cursor:pointer;transition:background .12s,border-color .12s}
.avc:hover{background:var(--raise);border-color:var(--accLine)}
.avc b{display:block;font-family:var(--mono);font-size:9px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dim);font-weight:750;margin-bottom:5px}
/* the number sits IN something: a field with an accent hairline and its unit
   beside it, so it reads as a box you type in rather than as a printed figure */
.avfld{display:flex;align-items:center;justify-content:center;gap:3px;cursor:text;
  border:1px solid var(--accLine);border-radius:7px;background:var(--surface);
  padding:0 5px 0 3px;transition:border-color .12s,box-shadow .12s}
.avfld span{font-family:var(--mono);font-size:8px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--acc);font-weight:750;flex:none}
.avc .avin{width:100%;min-width:0;font-family:var(--mono);font-size:12px;font-weight:750;
  text-align:center;font-variant-numeric:tabular-nums;padding:4px 0;
  background:transparent;border:0;border-radius:0;color:var(--paper);cursor:text}
.avc .avin:hover{border:0}
.avc:hover .avfld{border-color:var(--acc)}
/* one ring, on the box, rather than the global focus outline landing on a
   borderless input and drawing straight through the field around it */
.avfld:focus-within{border-color:var(--acc);box-shadow:0 0 0 2px var(--accSoft)}
.avfld .avin:focus-visible{outline:none}
.avc em{display:block;font-style:normal;font-family:var(--mono);font-size:8.5px;color:var(--muted);
  font-weight:650;margin-top:5px}
.avc u{display:block;text-decoration:none;font-family:var(--mono);font-size:8px;letter-spacing:.07em;
  text-transform:uppercase;color:var(--dim);font-weight:750;margin-top:2px}
.avc.avtoday{border-color:var(--accLine)}
.avc.avover{border-color:var(--z5)}
.avc.avover em{color:var(--z5)}
.avc.avtight em{color:var(--z4t)}
/* the strip above the week grid. "▸" is the same marker .fold uses — a glyph
   already proven to render here rather than a new one that comes out as tofu. */
.avpan{margin-bottom:12px}
.avpan>summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:9px;padding:1px 0}
.avpan>summary::-webkit-details-marker{display:none}
.avpan>summary::before{content:"▸";font-size:13px;line-height:1;color:var(--acc);
  transition:transform .12s;flex:none}
.avpan[open]>summary::before{transform:rotate(90deg)}
.avpan>summary::after{content:"Edit";margin-left:auto;flex:none;font-family:var(--mono);font-size:9px;
  letter-spacing:.08em;text-transform:uppercase;font-weight:750;color:var(--acc);
  background:var(--accSoft);border:1px solid var(--accLine);border-radius:999px;padding:3px 10px}
.avpan>summary:hover{color:var(--acc)}
.avpan>summary:hover::after{background:var(--acc);border-color:var(--acc);color:var(--accInk)}
.avpan summary b{margin-right:0}
@media(max-width:760px){ .avrow{grid-template-columns:repeat(4,1fr)} }
/* §6e the morning log where you actually meet it — the top of the landing page.
   Modelled on .avpan rather than invented, because it is the same object: a
   panel that reads back one line and opens into the form behind it. The readback
   sits on its own row (flex-basis:100%) so a summary carrying three numbers does
   not squeeze the chip off the end on a phone. */
/* The nine morning fields. auto-fit rather than a fixed count, so the same form
   is four columns on the dashboard, three in a narrower panel and one on a
   phone, without any surface knowing which it is — this is drawn in three places
   and none of them should have an opinion about its layout.
   The label sits ABOVE its control: side by side, "Sleep quality (1–10)" and
   "HRV (ms)" are wildly different widths, so every control started at a
   different x and the form read as nine unrelated things rather than one. */
.hlgrid{display:grid;gap:10px 14px;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));
  align-items:end;margin-top:2px}
.hlf{display:flex;flex-direction:column;gap:4px;min-width:0}
.hlf .hll{font-size:11.5px;color:var(--muted);font-weight:600;line-height:1.25}
.hlf .hll em{color:var(--dim);font-style:normal;font-weight:500}
.hlform .hlin{width:100%;min-width:0}
.hldash{margin-bottom:14px}
.hldash>summary{cursor:pointer;list-style:none;display:flex;align-items:center;flex-wrap:wrap;
  gap:9px;padding:1px 0}
.hldash>summary::-webkit-details-marker{display:none}
.hldash>summary::before{content:"▸";font-size:13px;line-height:1;color:var(--acc);
  transition:transform .12s;flex:none}
.hldash[open]>summary::before{transform:rotate(90deg)}
.hldash>summary .hlst{font-size:14.5px;font-weight:700;letter-spacing:-.01em}
/* NOT margin-left:auto, which is what .avpan does. That panel's summary is a
   narrow row, so pushing the chip to the far end keeps it next to its text; this
   one is the full width of the page, and an auto margin stranded it six hundred
   pixels from the title it belongs to, reading as a stray button. It sits
   directly after the count instead. */
.hldash>summary::after{content:"Fill it in";flex:none;font-family:var(--mono);
  font-size:9px;letter-spacing:.08em;text-transform:uppercase;font-weight:750;color:var(--acc);
  background:var(--accSoft);border:1px solid var(--accLine);border-radius:999px;padding:3px 10px}
.hldash[open]>summary::after{content:"Close"}
/* ORDER, not source order. ::after is the last flex child, and .hint is a full
   width row, so without this the chip wrapped onto a third line on its own —
   which reads as a stray button under the panel rather than as part of its
   heading. The chip belongs on the title row; the readback belongs under it. */
.hldash>summary::after{order:1}
.hldash>summary .hint{order:2;flex-basis:100%;margin:0 0 0 22px}
.hldash>summary:hover{color:var(--acc)}
.hldash>summary:hover::after{background:var(--acc);border-color:var(--acc);color:var(--accInk)}
/* §6d the re-plan proposal — nothing here has happened yet, and it reads that way */
.rpl{border-left:3px solid var(--acc)}
.rplist{list-style:none;margin:12px 0 0;padding:0}
.rplist li{padding:9px 12px;border-radius:8px;background:var(--sunk);margin-bottom:6px;
  border-left:3px solid var(--edge2)}
.rplist li b{display:block;font-size:12.5px;font-weight:700;color:var(--paper)}
.rplist li span{display:block;font-family:var(--mono);font-size:10.5px;color:var(--muted);
  font-weight:600;margin-top:3px}
.rplist li.rp-move{border-left-color:var(--z2)}
.rplist li.rp-shorten{border-left-color:var(--z3t)}
.rplist li.rp-swap{border-left-color:var(--z4t)}
.rplist li.rp-drop{border-left-color:var(--z5)}
#undoBtn:not([disabled]){color:var(--acc)}
.hidden{display:none!important}
@media(max-width:700px){
  .side{transform:translateX(-100%);box-shadow:var(--sh2)}
  .side.show{transform:none}
  .body{margin-left:0}
  .tray{left:0}
}
/* --- print --- */
@media print{
  :root,html[data-theme=dark]{
    --bg:#fff; --surface:#fff; --raise:#fff; --sunk:#f2f2f2;
    --edge:#c9c9c9; --edge2:#aaa; --edgeSoft:#e2e2e2;
    --paper:#000; --muted:#444; --dim:#666; --ink:#000; --inkHi:#000;
    --acc:#00594A; --accSoft:#fff; --accLine:#9FD3C7;
    --bodybg:#fff; --sidebg:#fff; --topbg:#fff; --profbg:none;
    --sh1:none; --sh2:none; --shUp:none; --grid:#f4f4f4;
  }
  html,body{background:#fff}
  .side,.scrim,.hdr,.tray,.toast,.kover,.srchwrap,.ctx,.cmdk,.focus,
  .rowbtns,.week-h .sp,.hint,button,select.btn-s,input[type=checkbox]{display:none!important}
  .body{margin-left:0!important;margin-right:0!important}
  .wrap{max-width:none;padding:0 4mm}
  .day.past{opacity:1}
  .ses,.panel,.libc,.day{break-inside:avoid;page-break-inside:avoid;box-shadow:none}
  .week{break-before:auto}
  .week-h{border-bottom-color:#000}
  .ses{border-color:#bbb}
  a{color:inherit;text-decoration:none}
}
@media(max-width:680px){
  .day{grid-template-columns:56px 1fr;gap:10px}
  .mets{display:none}.w-nm{width:auto}
  .cal{grid-template-columns:26px repeat(7,1fr);gap:3px}
  .cell{min-height:52px;padding:3px 4px}
  .wrap,.bar .in,.topbar,.subnav{padding-left:12px;padding-right:12px}
  .crumb{font-size:15px}
}
