/* Fallback tokens. theme_style() (lib.php) emits a <style id="theme"> AFTER this sheet that
   overrides all of these from the user's Config, and decides dark/light from the CARD COLOUR
   they chose rather than from the OS. These are what a page gets before that lands, and the
   prefers-color-scheme block below is the only OS-driven rule in the file.
   --good/--warn/--bad/--neutral, --card-bg, --hover and --mono were referenced throughout this
   sheet and defined nowhere, so every consumer fell back to a literal of its own. */
:root{
  --accent:#2563eb;--bg:#f1f5f9;--card:#fff;--card-bg:#fff;--ink:#0f172a;--muted:#64748b;
  --border:#e2e8f0;--pos:#16a34a;
  --good:#0f8248;--warn:#b06a04;--bad:#c6303c;--neutral:#5d6d83;
  --fam-endure:#1b6ed0;--fam-strength:#b06a04;--fam-recover:#0f8248;--fam-event:#937006;
  --fam-neutral:#5d6d83;
  --r-sm:8px;--r-md:11px;--r-lg:14px;--r-pill:999px;
  --s-1:4px;--s-2:8px;--s-3:12px;--s-4:16px;--s-5:24px;
  --ctl:34px;      /* one square control: .ib, .drow-cv, the .bfold chevron. 38px on phones */
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --hover:rgba(148,163,184,.10);--inner:rgba(148,163,184,.055)}
@media (prefers-color-scheme: dark){:root{
  --bg:#0f172a;--card:#1e293b;--card-bg:#1e293b;--ink:#e6edf5;--muted:#93a4bb;--border:#334155;
  --accent:#3b82f6;
  --good:#3ddc84;--warn:#f0a23c;--bad:#f2626b;--neutral:#7b8ca6;
  --fam-endure:#4b9fff;--fam-strength:#f0a23c;--fam-recover:#3ddc84;--fam-event:#e0b33d;
  --fam-neutral:#7b8ca6;
  --inner:rgba(148,163,184,.07)}}
*{box-sizing:border-box}
/* The hidden ATTRIBUTE only works because the UA sheet says [hidden]{display:none} — any
   author `display` on the same element silently beats it. Making it !important here means an
   element with hidden is always actually hidden, whatever else its class says. */
[hidden]{display:none!important}
/* ---- TYPE
   Six steps, not the fourteen that had grown in the wild (40/34/30/26/22/19/17/16/15/14/13/
   12/11.5px): 25px display · 19px title · 16px body-lead · 14px body · 12.5px meta ·
   10.5px uppercase micro-label. Large numbers get var(--mono) with tabular-nums so a column
   of them lines up and a changing one does not reflow. Headlines get text-wrap:balance.
   No webfont: the site is deliberately offline-capable and -apple-system is the Apple look. */
body{margin:0;background:var(--bg);color:var(--ink);line-height:1.5;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,sans-serif}
a{color:var(--accent);text-decoration:none}
.topnav{position:sticky;top:0;z-index:10;background:var(--card);border-bottom:1px solid var(--border);
  display:flex;justify-content:space-between;align-items:center;padding:10px 16px;gap:12px;flex-wrap:wrap}
.topnav .brand{font-weight:800;color:var(--ink)}
.topnav a{margin-left:14px;font-weight:600}
.wrap{max-width:1160px;margin:0 auto;padding:16px}
#ttip{position:absolute;display:none;z-index:200;max-width:300px;background:var(--card);color:var(--ink);
  border:1px solid var(--border);border-radius:8px;padding:7px 10px;font-size:12px;line-height:1.5;
  white-space:pre-line;box-shadow:0 6px 20px rgba(15,23,42,.28);pointer-events:none}
h1{font-size:22px;margin:var(--s-2) 0;font-weight:700;letter-spacing:-.02em;text-wrap:balance}
/* h2 is an EYEBROW, not a heading-sized heading — it labels the card below it. */
h2{font-size:14px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);
  margin:var(--s-5) 0 var(--s-2)}
.card{background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:var(--s-4);margin-bottom:var(--s-3);box-shadow:0 1px 3px rgba(15,23,42,.06)}
.hint{color:var(--muted);font-size:12px;font-weight:400}
/* A labelled setting row: name and hint on the left, the control on the right. Lived in
   settings.php's own <style>, which is why the Plan page could not use it. */
.crow{display:flex;justify-content:space-between;align-items:center;gap:14px;padding:11px 0;
  border-bottom:1px solid var(--border)}
.crow:last-child{border-bottom:none}
.crow label.k{font-weight:600;font-size:14px}
.crow .hint{display:block}
.crow input[type=number],.crow input[type=date],.crow input[type=text],.crow select{
  width:170px;max-width:48vw}
.crow input[type=color]{width:54px;height:32px;padding:2px;border:1px solid var(--border);
  border-radius:var(--r-sm);background:none}
.crow input[type=checkbox]{transform:scale(1.3)}
/* A sub-heading inside a card — the same eyebrow convention as h2, one level down. */
h4.bsec{margin:var(--s-4) 0 6px;font-size:13px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted)}
h4.bsec .hint{text-transform:none;letter-spacing:0;margin-left:6px}

/* ---- Shared primitives ----------------------------------------------------------------
   One inner card and one pill. There were FIVE copies of each — .bikecard / .pdcard / .mprog /
   .rm-card / .rm-tcard all described the same quiet panel inside a .card, and .mchip / .mpill /
   .sportpill / .ctxchip / .lib-nav a all described the same pill. Both live here now, so a
   component added to any of the 13 pages inherits the look instead of re-inventing it. */
.inner{border:1px solid var(--border);border-radius:var(--r-md);padding:11px 13px;
  background:var(--inner);min-width:0}
.pill{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:var(--r-pill);
  border:1px solid var(--border);background:var(--card);color:var(--ink);text-decoration:none;
  font-size:13.5px;line-height:1.35;white-space:nowrap;box-shadow:var(--emboss-lo)}
.pill:hover{border-color:var(--c,var(--accent))}
/* The active state is an inset ring rather than a fill, so the pill keeps its own colour and
   a row of them does not turn into a row of solid blocks. */
.pill.on{border-color:var(--c,var(--accent));font-weight:600;
  box-shadow:var(--emboss-lo),0 0 0 1px var(--c,var(--accent)) inset}
.err{background:color-mix(in srgb,var(--bad) 14%,transparent);color:var(--bad);
  border:1px solid color-mix(in srgb,var(--bad) 40%,transparent);border-radius:var(--r-sm);
  padding:10px 12px;margin:10px 0;font-size:14px}
.ok{color:var(--pos);font-weight:700}
input,select,textarea,button{font:inherit;color:var(--ink)}
input,select,textarea{background:var(--card);border:1px solid var(--border);border-radius:8px;padding:8px 10px}
textarea{width:100%}
button.primary,.primary{background:var(--accent);color:#fff;border:none;border-radius:10px;padding:11px 18px;font-weight:700;cursor:pointer}
.btn{display:inline-flex;align-items:center;justify-content:center;background:rgba(148,163,184,.22);
  color:var(--ink);border:none;border-radius:var(--r-sm);padding:8px 12px;font-size:14px;
  font-weight:600;cursor:pointer;text-decoration:none}
.btn.disabled{opacity:.35;pointer-events:none}
.dash-head h1{margin-bottom:0}
.goal-top{display:flex;justify-content:space-between;align-items:baseline;font-weight:700}
.goal-top .pct{font-size:26px}
.bar{height:12px;border-radius:99px;background:rgba(148,163,184,.25);overflow:hidden;margin:10px 0}
.bar>span{display:block;height:100%;background:var(--accent)}
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(90px,1fr));gap:10px;margin-top:8px}
.kpis.wide{grid-template-columns:repeat(auto-fit,minmax(110px,1fr))}
.kpi{background:var(--hover);border-radius:var(--r-md);padding:10px 12px;text-align:center}
.kpi b{display:block;font-size:22px;font-weight:700;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.kpi span{font-size:11px;color:var(--muted)}

/* ---- The arc: where am I in this ------------------------------------------------------
   Context, not a card. The math lived at the bottom of plan.php under the Print button, so the
   page you land on knew nothing about the 14 months it exists to serve. One line, then a bar. */
.arc{margin:10px 0 18px}
.arc-r{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s-2) var(--s-5)}
.arc-r>span{display:flex;align-items:baseline;gap:6px;min-width:0}
.arc-r b{font-size:15px;font-weight:700;color:var(--ink);white-space:nowrap}
.arc-r b small{font-size:11px;font-weight:600;color:var(--muted);margin-left:1px}
.arc-r i{font-style:normal;font-size:11.5px;color:var(--muted)}
.arc-ph b{color:var(--accent)}
.arc-pct{margin-left:auto}
.arc-bar{height:4px;border-radius:var(--r-pill);background:var(--hover);margin-top:var(--s-2);
  overflow:hidden}
.arc-bar span{display:block;height:100%;border-radius:var(--r-pill);background:var(--accent)}
@media (max-width:620px){ .arc-pct{margin-left:0} .arc-r{gap:var(--s-2) var(--s-4)} }

/* ---- Achieved: a result, not a progress bar ---------------------------------------------
   A met goal rendered as a 100% ring is the flattest possible way to report an achievement, and
   it keeps a dead deadline on screen. State it as done, in its own units, with the margin. */
.wongrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:10px;margin-top:8px}
.won{display:flex;align-items:center;gap:var(--s-3);padding:11px 13px;border-radius:var(--r-md);
  background:color-mix(in srgb,var(--good) 9%,var(--hover));
  border:1px solid color-mix(in srgb,var(--good) 28%,transparent)}
.won-k{flex:none;width:26px;height:26px;display:grid;place-items:center;border-radius:var(--r-pill);
  background:var(--good);color:#fff;font-size:14px;font-weight:700;line-height:1}
.won-b{min-width:0;display:flex;flex-direction:column;gap:1px}
.won-b b{font-size:14px;font-weight:650;line-height:1.2}
.won-b span{font-size:11.5px;color:var(--muted)}
@media print{
  .won{background:none!important;border-color:#000!important}
  .won-k{background:none!important;color:#000!important;border:1px solid #000}
}

/* ---- A metric that reports its own verdict ---------------------------------------------
   Eight identical grey boxes is precisely the "flattened goal feedback" Garmin users said
   weakened their motivation. Colour here is EARNED signal, not decoration: it appears only when
   the value is judged against his own 60-day norm. Categories stay calm; status speaks. */
.sigrow{align-items:stretch}
.kpi.sig{display:flex;flex-direction:column;justify-content:flex-start;gap:2px;
  border-top:2px solid transparent}
.kpi.sig em{font-style:normal;font-size:10px;line-height:1.25;color:var(--muted);
  margin-top:2px;text-wrap:balance}
.kpi.sig-good{border-top-color:var(--good);background:color-mix(in srgb,var(--good) 8%,var(--hover))}
.kpi.sig-warn{border-top-color:var(--warn);background:color-mix(in srgb,var(--warn) 10%,var(--hover))}
.kpi.sig-bad {border-top-color:var(--bad); background:color-mix(in srgb,var(--bad) 12%,var(--hover))}
.kpi.sig-good b{color:var(--good)}
.kpi.sig-warn b{color:var(--warn)}
.kpi.sig-bad  b{color:var(--bad)}
@media print{
  .kpi.sig{border-top-color:#000!important;background:none!important}
  .kpi.sig-good b,.kpi.sig-warn b,.kpi.sig-bad b{color:#000!important}
  .arc-bar span{background:#000!important}
}
/* today's fuel bars */
.fuelgrid{display:flex;flex-direction:column;gap:11px}
.fuel-row{display:grid;grid-template-columns:76px 1fr 132px;gap:12px;align-items:center}
.fuel-lab{font-weight:600;font-size:13px}
.fuel-bar{position:relative;height:16px;border-radius:99px;background:rgba(148,163,184,.18);overflow:hidden}
.fuel-bar span{display:block;height:100%}
/* PLANNED fuel — food logged for today but not eaten yet. It picks up exactly where the eaten
   fill stops, in the same accent at low opacity over a hatch, so the bar reads as "this much is
   in, this much is spoken for, this much is still free" without inventing a second colour. */
.fb-plannedfill{position:absolute;top:0;height:100%;
  background-color:color-mix(in srgb,var(--accent) 34%,transparent);
  background-image:repeating-linear-gradient(135deg,rgba(255,255,255,.30) 0 3px,transparent 3px 7px)}
/* The amount LEFT is the only number here anyone acts on, so it leads and carries the weight.
   "eaten / target unit" sits under it as one uniform, quiet phrase. Both lines are nowrap — on a
   single line this wrapped mid-phrase ("64 oz to / goal"). */
.fuel-val{display:flex;flex-direction:column;align-items:flex-end;justify-content:center;
  line-height:1.25;font-variant-numeric:tabular-nums;min-width:0}
.fuel-val .fb-status{color:var(--ink);font-size:15px;font-weight:700;white-space:nowrap;letter-spacing:-.01em}
.fuel-val .fb-ctx{color:var(--muted);font-size:11.5px;white-space:nowrap}
/* Sits between the headline figure and the eaten/target context: of what the target still
   allows, how much is not already committed to a planned meal. */
.fuel-val .fb-plan{color:var(--accent);font-size:11.5px;font-weight:600;white-space:nowrap}
.fuel-val .fb-have{color:inherit;font:inherit}
@media(max-width:640px){.fuel-row{grid-template-columns:64px 1fr}
  .fuel-val{grid-column:2/-1;flex-direction:row;align-items:baseline;justify-content:flex-start;gap:8px}}
/* goal cards */
.goalgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}
.goalcard{display:flex;align-items:center;gap:12px;background:rgba(148,163,184,.10);border-radius:12px;padding:12px 14px}
.goalcard .gring{width:66px;height:66px;flex:0 0 66px}
.goalcard .grpct{font-size:20px;font-weight:700;fill:var(--ink)}
.goalcard .goalmeta{min-width:0}
.goalcard .goalname{font-weight:700;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.goalcard .goalnum{font-size:13px;color:var(--muted);margin-top:2px}
.goaltbl td{vertical-align:top}
.btn.mv{padding:4px 9px;font-size:12px}
/* journal meals & snacks (grouped items) */
.mealcard{border:1px solid var(--border);border-radius:12px;padding:10px 12px;margin-bottom:10px;background:rgba(148,163,184,.06)}
.mealhead{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:6px}
.mealhead .mtype{font-weight:700;padding:5px 8px} .mealhead .mtime{width:96px}
.mealhead .mealsub{margin-left:auto;font-size:12px}
.mealitems{display:flex;flex-direction:column;gap:3px}
.mealitem{display:flex;gap:4px;flex-wrap:wrap;align-items:center}
.mealitem .mfood{flex:1;min-width:110px}
.mealitem .mserv{width:56px} .mealitem .mkcal{width:64px}
.mealitem .mp,.mealitem .mc,.mealitem .mf{width:48px}
.mealitem .xi{padding:4px 9px}
.additem{margin-top:6px;font-size:12px;padding:4px 10px}
.mealsearch{margin-top:8px}
.mealsearch .msq{width:100%;max-width:340px}
.mf-macros{display:grid;grid-template-columns:repeat(auto-fit,minmax(84px,1fr));gap:8px}
.mf-macros label{display:flex;flex-direction:column;font-size:11px;color:var(--muted);gap:2px}
.mf-macros input{width:100%}
#rc_items{display:flex;flex-direction:column;gap:3px;margin-bottom:6px}
.mfgrp{cursor:pointer} .mfgrp td{font-weight:600;background:rgba(148,163,184,.14)}
.mfgtog{display:inline-block;width:16px;text-align:center;font-weight:800;color:var(--accent)}
.quicklog{display:flex;flex-wrap:wrap;align-items:center;gap:14px;margin-top:12px}
.quicklog .ql-grp{display:inline-flex;align-items:center;gap:6px}
.quicklog .ql-lab{font-size:16px}
.quicklog .btn{padding:5px 11px}
.quicklog .ql-minus{opacity:.7;padding:5px 9px}

/* Training Plan page */
.plan-bar{height:6px;border-radius:var(--r-pill);background:rgba(148,163,184,.22);
  overflow:hidden;margin:var(--s-2) 0}
.plan-bar>span{display:block;height:100%;background:var(--accent);border-radius:var(--r-pill)}
.plan-bar.goal>span{background:var(--good)}
.race-kpi{border-left:3px solid var(--accent)}
.phase-list{display:flex;flex-direction:column}
.phase-row{display:flex;gap:14px;position:relative;padding:0 8px 16px 8px}
.phase-row::before{content:"";position:absolute;left:13px;top:16px;bottom:0;width:2px;background:rgba(148,163,184,.28)}
.phase-row:last-child::before{display:none}
.phase-dot{flex:0 0 12px;width:12px;margin-top:3px;z-index:1}
.phase-dot::before{content:"";display:block;width:12px;height:12px;border-radius:50%;border:2px solid rgba(148,163,184,.5);background:var(--card-bg,#fff);box-sizing:border-box}
.phase-row.done .phase-dot::before{background:rgba(148,163,184,.6);border-color:rgba(148,163,184,.6)}
.phase-row.current .phase-dot::before{background:var(--accent);border-color:var(--accent)}
.phase-row.current{background:rgba(37,99,235,.07);border-radius:10px}
.phase-row.future{opacity:.82}
.phase-body{flex:1;min-width:0}
.phase-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px}
.phase-when{font-size:12.5px;color:var(--muted)}
.phase-badge{font-size:12px;font-weight:700;color:var(--accent);background:rgba(37,99,235,.12);padding:1px 8px;border-radius:20px}
.phase-badge.ev{color:var(--fam-event);background:color-mix(in srgb,var(--fam-event) 16%,transparent)}
.phase-fuel{color:var(--accent);font-weight:600}
.ol-toggle{display:inline-flex;gap:2px;background:var(--inner);padding:3px;
  border:1px solid var(--border);border-radius:10px;margin-bottom:var(--s-4)}
.ol-btn{border:0;background:transparent;padding:6px 15px;border-radius:7px;font:inherit;
  font-size:13px;font-weight:600;cursor:pointer;color:var(--muted)}
.ol-btn:hover{color:var(--ink)}
.ol-btn.active{background:var(--accent);color:#fff}
/* modality color chips + legend */
.cal-legend{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:14px}
/* The month key. Three entries, so each can afford to say what it covers — the twelve icons
   inside the cells are what tell the disciplines apart. Same pill recipe as .pill. */
.cal-legend .mchip{display:inline-flex;align-items:baseline;gap:7px;font-size:11.5px;
  padding:5px 11px;border-radius:var(--r-pill);border:1px solid var(--border);
  background:var(--card);color:var(--muted);line-height:1.4;white-space:nowrap;
  box-shadow:var(--emboss-lo)}
.cal-legend .mchip i{width:7px;height:7px;border-radius:var(--r-pill);background:var(--c);
  flex:none;align-self:center}
.cal-legend .mchip b{color:var(--c);font-weight:650}
.mchip{display:inline-flex;align-items:center;gap:3px;font-size:11.5px;font-weight:600;padding:2px 7px;border-radius:var(--r-pill);line-height:1.5;white-space:nowrap}
/* week blocks + calendar grid */
.cal-wk{margin-bottom:16px}
.cal-wk-h{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin:0 0 6px}
.cal-wk.curw .cal-wk-h b{color:var(--accent)}
.week-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:7px}
.cal-cell{position:relative;border:1px solid rgba(148,163,184,.28);border-radius:9px;padding:7px 8px;min-height:88px}
.cal-cell.today{border-color:var(--accent);background:rgba(37,99,235,.08)}
.cal-cell.done{opacity:.6}
.cal-h{font-weight:700;font-size:12.5px;margin-bottom:5px;white-space:nowrap}
.cal-h span{font-weight:400;color:var(--muted)}
/* A week cell speaks the same language as the day view: one small box per item. */
.cminis{display:flex;flex-direction:column;gap:3px}
.cmini{display:flex;align-items:flex-start;gap:5px;padding:4px 6px;border-radius:6px;
  background:rgba(148,163,184,.10);border:1px solid rgba(148,163,184,.16);font-size:11.5px;
  line-height:1.25;min-width:0}
.cmini i{font-style:normal;font-size:12px;flex:none}
.cmini b{font-weight:600;min-width:0;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical}
.cmini.ev{background:color-mix(in srgb,var(--fam-event) 14%,transparent);
  border-color:color-mix(in srgb,var(--fam-event) 40%,transparent)}
.cmini.st-done{opacity:.45}
.cmini.st-done b{text-decoration:line-through}
.cmini.st-skipped{opacity:.38}
.cmini.st-partial{border-color:color-mix(in srgb,var(--warn) 50%,transparent)}
.cal-none{color:var(--neutral);font-size:12px}
/* month-grid calendar (Month view) */
.mcal-wrap{display:flex;flex-wrap:wrap;gap:20px}
.mcal{flex:1 1 320px;min-width:280px}
.mcal-title{font-weight:700;font-size:15px;margin-bottom:8px}
.mcal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}
.mcal-dow{font-size:11px;font-weight:700;color:var(--muted);text-align:center;padding-bottom:2px}
.mcal-day{position:relative;border:1px solid rgba(148,163,184,.22);border-radius:7px;padding:4px;min-height:66px}
.mcal-day.empty{border:0}
.mcal-day.out{opacity:.35;min-height:46px}
.mcal-day.today{border-color:var(--accent);background:rgba(37,99,235,.08)}
.mcal-day.done{opacity:.55}
.mcal-n{font-size:11.5px;font-weight:700;color:var(--muted);margin-bottom:3px}
.mcal-day.today .mcal-n{color:var(--accent)}
@media(max-width:820px){.week-grid{grid-template-columns:repeat(2,1fr)}}
/* clickable / selected / event calendar cells */
.cal-cell.clk{cursor:pointer}
.cal-cell.clk:hover{border-color:var(--accent)}
.cal-cell.sel{border-color:var(--accent);box-shadow:0 0 0 2px rgba(37,99,235,.25)}
.cal-cell.event{border-color:var(--fam-event)}
/* The day's chrome — Back-to-today and Print. It sits BELOW the day, because the hero has to
   be the first thing on the page and neither of these is something you reach for first. */
.brief-bar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-2);
  margin:var(--s-4) 0 0;padding-top:var(--s-3);border-top:1px solid var(--border)}
.brief-bar .btn{margin-left:auto}
.brief-bar .btn:first-child{margin-left:0}
.brief-t{width:100%;border-collapse:collapse}
.brief-t th{text-align:left;vertical-align:top;font-weight:700;padding:4px 12px 4px 0;white-space:nowrap;width:1%;color:var(--muted)}
.brief-t td{padding:4px 0;vertical-align:top;line-height:1.42}
.brief-t.zt th{color:inherit;font-weight:600}
.brief-t.zt td{white-space:nowrap;padding-right:12px}
/* status glyphs — shape carries the meaning, colour only reinforces it */
.g-done{color:var(--good);font-weight:800}
.g-skip{color:var(--bad);font-weight:800}
.g-part{color:var(--warn);font-weight:800}
.g-past{color:var(--neutral)}
.sp-pick{display:flex;align-items:center;gap:9px;margin-bottom:10px;font-size:12.5px;color:var(--muted)}
.sp-pick label{font-weight:600;text-transform:uppercase;letter-spacing:.04em;font-size:11px}
.sp-pick select{font:inherit;font-size:13px;padding:5px 9px;border:1px solid var(--border);
  border-radius:8px;background:var(--card);color:inherit;max-width:min(460px,72vw)}
.rmap>summary{cursor:pointer;list-style:none;display:flex;align-items:baseline;gap:12px;
  flex-wrap:wrap;padding:4px 0}
.rmap>summary::-webkit-details-marker{display:none}
.rmap>summary h2{display:inline;margin:0}
.rmap>summary::after{content:'\25B8';color:var(--muted);font-size:12px;transition:transform .15s;
  display:inline-block;margin-left:auto}
.rmap[open]>summary::after{transform:rotate(90deg)}
@media print{.rmap>summary::after{display:none}.rmap>*{display:block!important}}
/* ---- Journal: copy a meal forward ---- */
#cppanel{margin-top:12px;border:1px solid var(--border);border-radius:10px;background:var(--card);
  max-height:min(60vh,460px);display:flex;flex-direction:column;overflow:hidden}
.cphead{display:flex;gap:8px;padding:10px;border-bottom:1px solid var(--border);flex:none}
.cphead input{flex:1;min-width:0}
#cplist{overflow-y:auto;padding:4px 10px 10px}
.cpday{margin-top:10px}
.cpdate{font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);padding:6px 0 4px;display:flex;align-items:center;gap:10px;
  position:sticky;top:0;background:var(--card);z-index:1}
.cprow{display:flex;align-items:flex-start;gap:10px;padding:7px 0;border-top:1px solid var(--border)}
.cpmeta{min-width:0;flex:1}
.cpfoods{margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.btn.cpgo{flex:none}
.btn.cpall{font-size:11px;padding:2px 8px;text-transform:none;letter-spacing:0}
/* Dose count beside a supplement name on the journal checklist — "Potassium (2)". Quiet, because
   the name is what you scan for; the count only matters once you have found the row. */
.supp-dose{color:var(--muted);font-size:12px;font-variant-numeric:tabular-nums}
/* Settings: pills-per-dose sits inline with the supplement name, narrow enough to read as a count. */
.supphead .sdose{width:52px;text-align:center;font-variant-numeric:tabular-nums}
.mealcard.justcopied{outline:2px solid var(--pos);outline-offset:2px;transition:outline-color 1s}
/* A planned meal is a different KIND of row, not a styled variant of an eaten one: dashed edge,
   no fill, so scanning the journal never mistakes an intention for a record. */
.mealcard.planned{border-style:dashed;border-color:var(--accent);background:transparent}
.mealcard.planned .mealsub{color:var(--accent)}
.mealhead .planbtn{font-size:11.5px;padding:4px 9px;letter-spacing:.02em;text-transform:lowercase}
.mealhead .planbtn.on{border-color:var(--accent);color:var(--accent);font-weight:700}
@media (max-width:620px){ .cpfoods{white-space:normal} }
/* ==========================================================================
   PLAN — THE DAY
   One card, one focal point, in the order the question is actually asked:
   where am I (date + phase) → what am I doing (hero + duration) → how hard
   (zone band) → the list → what happened → everything else, folded.
   ========================================================================== */
.bhead{display:flex;flex-direction:column;gap:3px;padding-bottom:var(--s-3);
  border-bottom:1px solid var(--border);margin-bottom:var(--s-2)}
.bhead-r{display:flex;align-items:center;gap:var(--s-1)}
.bhead-sp{flex:1}
.bdate{font-size:19px;font-weight:650;letter-spacing:-.015em}
.bphase{font-size:12.5px;color:var(--muted);line-height:1.45}
.bphase b{color:var(--ink);font-weight:600}

/* The hero: the one answer the page exists to give. The duration is what you act on, so it
   gets the display treatment — mono and tabular, so 45 and 150 sit on the same grid. */
.hero{display:flex;align-items:flex-end;gap:var(--s-4);flex-wrap:wrap;
  margin-top:var(--s-4);padding-top:var(--s-4);border-top:1px solid var(--border)}
.hero-main{flex:1 1 220px;min-width:0}
.hero-fam{display:flex;align-items:center;gap:7px;margin-bottom:5px}
.hero-fam i{width:9px;height:9px;border-radius:var(--r-pill);background:var(--c);flex:none}
.hero-fam span{font-size:11px;letter-spacing:.1em;text-transform:uppercase;font-weight:650;
  color:var(--c)}
.hero-t{font-size:25px;line-height:1.15;font-weight:650;letter-spacing:-.02em;margin:0;
  text-wrap:balance}
.hero-dur{text-align:right;flex:none}
.hero-dur b{display:block;font-family:var(--mono);font-size:50px;line-height:.92;font-weight:700;
  letter-spacing:-.04em;font-variant-numeric:tabular-nums}
.hero-dur span{font-size:10.5px;letter-spacing:.11em;text-transform:uppercase;color:var(--muted)}

/* The zone, as a band. "133-146 bpm" as prose says nothing about where that sits in your own
   range; five segments with one lit say it before you have read a digit. */
.zband{margin-top:var(--s-5)}
.zband-l{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-3);
  margin-bottom:7px}
.zband-l b{font-size:12px;font-weight:650;color:var(--c)}
.zband-l span{font-size:11.5px;color:var(--muted);font-variant-numeric:tabular-nums}
.zband-b{display:flex;gap:2px;height:7px}
.zband-b i{flex:1;border-radius:2px;background:rgba(148,163,184,.25)}
.zband-b i.hit{background:var(--c)}
.zband-e{display:flex;justify-content:space-between;margin-top:5px;font-size:10.5px;
  color:var(--muted);font-variant-numeric:tabular-nums}

/* The week, as seven taps — the Day view's whole context without leaving the day. Dots only:
   at ~50px a label is unreadable, and one dot per distinct FAMILY is the honest summary. */
.wkstrip{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;margin:0 0 var(--s-4)}
.wd{display:flex;flex-direction:column;align-items:center;gap:5px;padding:8px 2px 9px;
  border-radius:var(--r-md);text-decoration:none;color:inherit;border:1px solid transparent}
.wd:hover{background:var(--hover)}
.wd-w{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.wd-n{font-size:15px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--muted)}
.wd-d{display:flex;gap:3px;min-height:6px;align-items:center}
.wd-d i{width:6px;height:6px;border-radius:var(--r-pill);background:var(--c,var(--neutral))}
.wd-rest{width:7px;height:2px;border-radius:2px;background:var(--muted);opacity:.55}
.wd.past{opacity:.62}
.wd.on{background:var(--card);border-color:var(--border);opacity:1;box-shadow:var(--emboss-lo)}
.wd.on .wd-n{color:var(--ink)}
.wd.now .wd-w{color:var(--accent);font-weight:700}

/* What actually happened, as numbers rather than a run-on string. Five facts joined by
   middots is one fact you have to parse; a grid is five you can find. */
.bact{margin:var(--s-5) 0 0;padding:13px 14px;border-radius:var(--r-md);
  border:1px solid var(--border);background:var(--inner)}
.bact-h{display:flex;align-items:center;gap:7px;font-size:10.5px;letter-spacing:.11em;
  text-transform:uppercase;color:var(--muted);font-weight:650;margin-bottom:10px}
.bact-h i{width:7px;height:7px;border-radius:var(--r-pill);background:var(--good);flex:none}
.bact-n{font-size:13.5px;font-weight:600;margin:14px 0 7px}
.bact-h+.bact-n{margin-top:0}
.bstats{display:grid;grid-template-columns:repeat(auto-fit,minmax(72px,1fr));gap:12px 10px}
.bstat b{display:block;font-family:var(--mono);font-size:18px;font-weight:700;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1.1}
.bstat span{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}

/* Folds. Each is one hairline row, and each puts in its summary the thing you would have
   opened it to check — the fuel's scale, the day's tally. */
.bfold{border-bottom:1px solid var(--border)}
.bfold>summary{display:flex;align-items:center;gap:var(--s-2);padding:13px 2px;cursor:pointer;
  list-style:none;font-size:13.5px;font-weight:600;color:var(--muted)}
.bfold>summary::-webkit-details-marker{display:none}
.bfold>summary::after{content:'\203A';font-size:17px;line-height:1;color:var(--muted);
  transition:transform .16s;display:inline-block;flex:none;width:var(--ctl);text-align:center}
.bfold>summary:hover{color:var(--ink)}
.bfold[open]>summary{color:var(--ink)}
.bfold[open]>summary::after{transform:rotate(90deg)}
.bfold-x{font-size:11.5px;font-weight:400;color:var(--muted);margin-left:auto}
.bkv{margin:0;padding:0 0 var(--s-4)}
.bkv-r{display:flex;gap:var(--s-4);padding:6px 0;align-items:baseline}
.bkv dt{flex:none;width:66px;font-size:10.5px;letter-spacing:.07em;text-transform:uppercase;
  color:var(--muted);font-weight:650}
.bkv dd{margin:0;flex:1;min-width:0;font-size:13.5px;line-height:1.45}
@media (max-width:620px){
  .hero-dur b{font-size:40px}
  .hero-t{font-size:21px}
  .bdate{font-size:17px}
  .bkv-r{flex-direction:column;gap:2px}
  .bkv dt{width:auto}
}
/* ---- The day as uniform rows: one per line, same shape for every kind ----
   HAIRLINES, NOT BOXES. A dozen bordered, shadowed boxes stacked inside a bordered, shadowed
   card was most of what made this page read as a spreadsheet. The family-tinted icon tile and
   the type carry everything the border used to, at a fraction of the ink. */
.drows{display:flex;flex-direction:column;margin:var(--s-5) 0 0;border-top:1px solid var(--border)}
.drow{border-bottom:1px solid var(--border);transition:opacity .15s}
.drow>summary{display:flex;align-items:center;gap:var(--s-3);padding:11px 2px;cursor:pointer;
  list-style:none}
.drow>summary::-webkit-details-marker{display:none}
.drow.nodet>summary{cursor:default}
.drow>summary:hover .drow-t{color:var(--accent)}
/* The expand affordance. At 12px muted it read as a stray dot rather than a control — it
   needs the same footprint as the buttons beside it to look like it belongs to them. */
.drow-cv{flex:none;width:var(--ctl);height:var(--ctl);display:grid;place-items:center;
  border-radius:var(--r-sm);color:var(--muted);font-size:15px;line-height:1;
  border:1px solid transparent;
  transition:transform .15s,color .15s,background .15s,border-color .15s}
/* A detail-less row still reserves the slot, so every row's buttons land in one column. */
.drow.nodet .drow-cv{visibility:hidden}
.drow>summary:hover .drow-cv{color:var(--ink);background:rgba(148,163,184,.12);
  border-color:var(--border)}
.drow[open] .drow-cv{transform:rotate(180deg);color:var(--accent)}
/* the detail, in the same language as the row it belongs to */
.drow-d{padding:2px 2px 14px 44px}
.drow-why{font-size:13px;color:var(--muted);line-height:1.5;margin:10px 0 4px}
.drow-grp{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);margin:12px 0 5px}
.drow-mv{display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  padding:5px 0;border-bottom:1px solid var(--border);font-size:14px}
.drow-mv:last-of-type{border-bottom:0}
.drow-mv b{flex:none;color:var(--accent);font-size:13px}
.drow-rule{font-size:13px;color:var(--muted);line-height:1.5;margin:10px 0 0}
.drow-start{display:block;margin-top:12px;padding:11px;border-radius:var(--r-sm);
  border:1px solid color-mix(in srgb,var(--good) 45%,transparent);
  background:color-mix(in srgb,var(--good) 10%,transparent);color:var(--good);
  font-weight:700;font-size:14px;text-align:center;text-decoration:none}
.drow-start:hover{background:color-mix(in srgb,var(--good) 18%,transparent)}
@media (max-width:620px){.drow-d{padding-left:14px}}
@media print{.drow>summary{cursor:auto}.drow-d{display:block!important}.drow-cv{display:none}}
/* Colour and icon in one mark: the tile is the family tint, the glyph is the discipline.
   Three colours tell you what kind of work; twelve icons tell you which. */
.drow-ic{flex:none;width:30px;height:30px;display:grid;place-items:center;font-size:15px;
  line-height:1;border-radius:var(--r-sm);
  background:color-mix(in srgb,var(--c,var(--neutral)) 17%,transparent)}
.drow-b{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.drow-t{font-size:16px;font-weight:650;line-height:1.25;text-decoration:none;color:inherit}
a.drow-t:hover{color:var(--accent)}
.drow-go{font-size:13px;color:var(--muted)}
a.drow-t:hover .drow-go{color:var(--accent)}
.drow-s{font-size:12.5px;color:var(--muted);line-height:1.3}
.drow-st{display:flex;gap:4px;flex:none}
.ib{width:var(--ctl);height:var(--ctl);border:1px solid var(--border);
  border-radius:var(--r-sm);background:none;
  color:var(--muted);font-size:14px;line-height:1;cursor:pointer;padding:0}
.ib:hover{color:var(--ink);border-color:var(--muted)}
.ib.on{color:#fff;font-weight:700}
.drow-st .ib:nth-child(1).on{background:var(--good);border-color:var(--good)}
.drow-st .ib:nth-child(2).on{background:var(--warn);border-color:var(--warn)}
.drow-st .ib:nth-child(3).on{background:var(--neutral);border-color:var(--neutral)}
/* a decided row recedes, so what is left to do is what stands out. The status marks sit on
   the icon tile rather than on a border — there is no border left to colour. */
.drow.st-done{opacity:.5}
.drow.st-done .drow-t{text-decoration:line-through}
.drow.st-partial .drow-ic{box-shadow:0 0 0 1.5px var(--warn) inset}
.drow.st-skipped{opacity:.45}
.drow.st-skipped .drow-t{text-decoration:line-through}
@media (max-width:620px){
  .drow-t{font-size:15px}
  .drow>summary{gap:var(--s-2)}
  :root{--ctl:38px}
}
@media print{.drow{break-inside:avoid}}
.bact{margin:0 0 14px;padding:11px 13px;border-radius:10px;border:1px solid var(--border);
  background:rgba(34,197,94,.06);font-size:14px}
.bact-r{margin-top:5px}
/* ---- Finishing with the day: status, note and the way into the editor, together ---- */
.dlog{margin-top:16px;padding-top:14px;border-top:1px solid var(--border);
  display:flex;flex-direction:column;gap:9px}
.dlog-r{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.dlog-l{font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.dlog-st{font-size:12.5px;color:var(--muted)}
.dlog-st em{font-style:normal;opacity:.75}
.dlog-edit{margin-left:auto}
.dlog-note{flex:1;min-width:0}
.dlog .btn.lg{transition:opacity .15s,background .15s,border-color .15s}
.dlog.has-pick .btn.lg{opacity:.38}
.dlog.has-pick .btn.lg.on{opacity:1}
.dlog .btn.lg.on{color:#fff;font-weight:700}
.dlog .btn.lg-done.on{background:var(--good);border-color:var(--good)}
.dlog .btn.lg-part.on{background:var(--warn);border-color:var(--warn)}
.dlog .btn.lg-skip.on{background:var(--neutral);border-color:var(--neutral)}
.dlog .btn.lg:hover{opacity:1}
@media (max-width:620px){ .dlog-edit{margin-left:0;flex:1 1 100%} }
.rt-go{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:10px 0 4px;padding:12px 14px;
  border-radius:var(--r-md);border:1px solid color-mix(in srgb,var(--good) 45%,transparent);
  background:color-mix(in srgb,var(--good) 10%,transparent);color:var(--good);
  font-weight:700;font-size:15px;text-decoration:none}
.rt-go:hover{background:color-mix(in srgb,var(--good) 18%,transparent)}
.rt-go-s{font-weight:400;font-size:12.5px;color:var(--muted)}
@media (max-width:720px){ .rt-go{padding:14px;font-size:16px} }
.routine summary{position:relative;padding-right:34px}
.rt-pop{position:absolute;right:4px;top:50%;transform:translateY(-50%);text-decoration:none;
  font-size:17px;line-height:1;color:var(--muted);padding:5px 7px;border-radius:7px}
.rt-pop:hover{color:var(--accent);background:rgba(59,130,246,.12)}
.lib-nav{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 18px}
.lib-nav a{gap:7px;padding:7px 13px;font-size:13px;font-weight:600}
.lib-n{font-size:11px;color:var(--muted);font-weight:700}
/* named mobility routines in the day brief */
.routine{margin:12px 0;border:1px solid var(--border);border-radius:10px;padding:10px 13px;background:var(--card)}
.routine summary{cursor:pointer;font-size:14px;list-style:none}
.routine summary::-webkit-details-marker{display:none}
.routine summary::before{content:'\25B8 ';color:var(--accent);font-weight:700}
.routine[open] summary::before{content:'\25BE '}
.rt-why{margin:8px 0 4px}
.rt-h{font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--accent);margin:12px 0 4px}
.rt-t th{font-weight:600;color:var(--ink);width:auto}
.rt-t .rt-dose{font-family:var(--mono,monospace);white-space:nowrap;font-weight:600}
.rt-vidcell{width:1%;white-space:nowrap;text-align:right;vertical-align:middle}
.rt-vid{font-size:16px;line-height:1;text-decoration:none;opacity:.65;
  display:inline-block;padding:2px 3px;border-radius:5px}
.rt-vid:hover,.rt-vid:focus-visible{opacity:1;background:rgba(148,163,184,.18)}
.rt-rule{margin-top:10px;padding-top:8px;border-top:1px solid var(--border)}
/* micros: window slider */
.mk-win{display:flex;align-items:center;gap:10px;margin:6px 0 12px;font-size:12.5px;color:var(--muted)}
.mk-win label{font-weight:600;letter-spacing:.03em;text-transform:uppercase;font-size:11px}
.mk-win input[type=range]{flex:1 1 auto;max-width:420px;accent-color:var(--accent);height:20px}
.mk-winlbl{font-family:var(--mono,monospace);font-variant-numeric:tabular-nums;white-space:nowrap;
  color:var(--ink);font-weight:600}
/* Config → Training plan editor */
.cfg-h{font-size:13px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin:20px 0 6px}
.pl-form{margin-bottom:6px}
.pl-inline{display:flex;flex-wrap:wrap;align-items:end;gap:10px}
.pl-race{padding:8px 0;border-bottom:1px solid var(--border)}
.pl-race:last-of-type{border-bottom:0}
.pl-race .k{display:block;margin-bottom:6px}
.pl-firm{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);white-space:nowrap}
.arc-tbd abbr{border:0;text-decoration:none;font-size:9.5px;font-weight:700;letter-spacing:.06em;
  padding:1px 4px;border-radius:var(--r-sm);background:var(--hover);color:var(--muted);margin-left:3px}
.pl-eq{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:8px}
.pl-eq label{display:flex;align-items:center;gap:6px;font-size:13px}
.pl-phase{border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin-bottom:10px}
.pl-phase.pl-new{border-style:dashed}
.pl-row{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:6px}
.pl-phase label{display:flex;flex-direction:column;gap:3px;font-size:11px;color:var(--muted)}
.pl-phase label.gr{flex:1 1 100%;margin-bottom:6px}
.pl-phase input,.pl-phase textarea{font:inherit;font-size:13px;color:inherit}
.pl-days{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:6px;margin-bottom:6px}
.pl-del{flex-direction:row!important;align-items:center;gap:5px;align-self:end;padding-bottom:8px}
/* readiness suggestion banner — only rendered when the day is actually off-normal */
.rd-card{border-radius:10px;padding:10px 12px;margin:0 0 12px;font-size:13px;
  border:1px solid rgba(148,163,184,.35);background:rgba(148,163,184,.08)}
.rd-card.rd-red{border-color:color-mix(in srgb,var(--bad) 55%,transparent);
  background:color-mix(in srgb,var(--bad) 9%,transparent)}
.rd-card.rd-amber{border-color:color-mix(in srgb,var(--warn) 50%,transparent);
  background:color-mix(in srgb,var(--warn) 9%,transparent)}
.rd-sig{margin:6px 0 8px;padding-left:20px;color:var(--muted);font-size:12.5px}
.rd-sig li{margin:1px 0}
.rd-card .btn{padding:4px 12px}
.nowbtn{padding:2px 8px;font-size:11px;font-weight:600;margin-left:6px;line-height:1.6}
.adj-state{flex:1 0 100%;font-size:12px;font-weight:600;color:var(--accent);margin-top:2px}
/* ---- Print / Save PDF: plain black-on-white, activities told apart by ICON not colour ----
   The whole app is CSS-variable driven, so re-pointing the variables flips every page at once,
   dark themes included. !important is required: the per-profile theme injects its own :root in a
   <style> AFTER this sheet, and the modality pills carry inline background/color. */
@media print{
  :root{--bg:#fff!important;--card:#fff!important;--card-bg:#fff!important;--ink:#000!important;
        --muted:#333!important;--border:#999!important;--accent:#000!important;--pos:#000!important;
        --topbar:#fff!important;--topbar-fg:#000!important;--sidebar:#fff!important;
        /* status and family hues collapse to ink: paper tells things apart by shape and glyph */
        --good:#000!important;--warn:#000!important;--bad:#000!important;--neutral:#555!important;
        --fam-endure:#000!important;--fam-strength:#000!important;--fam-recover:#000!important;
        --fam-event:#000!important;--fam-neutral:#000!important;
        --inner:transparent!important;--hover:transparent!important}
  html{color-scheme:light!important}
  body{background:#fff!important;color:#000!important}
  a{color:#000!important;text-decoration:none}
  .card,.brief,.cal-cell,.mcal-day{background:#fff!important;box-shadow:none!important}
  /* screen-only chrome */
  .topnav,.no-print,.ol-toggle,.brief-bar,.wkstrip,
  button,.btn,.sharebtn,#ttip,#caltip{display:none!important}
  [hidden]{display:none!important}
  .wrap{max-width:none!important;padding:0!important}
  /* activity = icon, not colour */
  .mchip{background:#fff!important;color:#000!important;border:1px solid #666!important}
  /* the day rows' family tile is pure colour, so on paper it would print as a grey square
     around the glyph that already does the telling */
  .drow-ic{background:none!important;box-shadow:none!important}
  /* keep structure legible without fills */
  .cal-cell{border:1px solid #666!important;break-inside:avoid}
  .cal-cell.today,.cal-cell.event{border:2px solid #000!important;background:#fff!important}
  .cal-cell.done{opacity:1!important;color:#555!important}   /* the ✓ glyph already marks these */
  .brief{break-inside:avoid}
  .brief-t th{color:#333!important}
  .bfold>summary::after,.drow-cv{display:none!important}
  .bfold>summary{color:#000!important}
  .plan-bar,.bar{border:1px solid #666!important;background:#fff!important}
  .plan-bar>span,.bar>span{background:#000!important}
  /* Emoji are colour glyphs, so black text alone doesn't make them mono. font-variant-emoji asks
     for the text presentation where it's supported; grayscale() is the fallback, applied only to
     the small inline carriers — a filter on a big container can clip printed content to one page. */
  body{font-variant-emoji:text}
  .mchip,.cal-h,.mcal-n,.drow-ic,.brief-t td{filter:grayscale(1)}
  /* status glyphs: shape carries the meaning (✓ done · ✗ skipped · ◐ partial), so drop the colour.
     Past-but-unlogged stays grey so it still reads apart from a logged ✓. */
  .g-done,.g-skip,.g-part{color:#000!important}
  .g-past{color:#888!important}
}
.msresults{display:flex;flex-direction:column;gap:3px;margin-top:5px}
.msr{text-align:left;font-weight:400;font-size:12.5px;background:rgba(148,163,184,.12);white-space:normal;line-height:1.5}
.msr b{font-weight:700}
/* nutrition report: range toggle + macro split bar */
.pf-rangehead{display:flex;justify-content:flex-end;margin:6px 0 10px}
.pf-range{display:inline-flex;gap:2px;background:rgba(148,163,184,.14);border-radius:99px;padding:3px}
.pf-range button{border:none;background:none;color:var(--muted);font:inherit;font-size:12px;font-weight:600;padding:4px 11px;border-radius:99px;cursor:pointer}
.pf-range button.on{background:var(--accent);color:#fff}
.macrobar{display:flex;height:22px;border-radius:99px;overflow:hidden;background:rgba(148,163,184,.15)}
.macrobar span{display:block;height:100%}
/* micros view */
#mkedit{display:grid;grid-template-columns:repeat(auto-fill,minmax(165px,1fr));gap:6px;margin-bottom:10px}
.snut{display:flex;align-items:center;gap:4px;font-size:12px}
.snut .snl{flex:1;min-width:0;color:var(--muted)} .snut .snu{width:24px;color:var(--muted);font-size:11px}
.mkt{width:66px}
.mkrow{display:grid;grid-template-columns:132px 1fr 168px;gap:10px;align-items:center;padding:5px 0;border-bottom:1px solid var(--border)}
.mkrow:last-child{border-bottom:none}
.mkname{font-weight:600;font-size:13px}
.mkbar{height:14px;border-radius:99px;background:rgba(148,163,184,.18);overflow:hidden}
.mkbar span{display:block;height:100%}
.mkval{font-size:12px;color:var(--muted);text-align:right;font-variant-numeric:tabular-nums}
@media(max-width:640px){.mkrow{grid-template-columns:96px 1fr}.mkval{grid-column:1/-1;text-align:left}}
.verdict{font-size:14px;line-height:1.5}
table{width:100%;border-collapse:collapse;font-size:13px}
th,td{text-align:left;padding:7px 8px;border-bottom:1px solid var(--border);white-space:nowrap}
th{color:var(--muted);font-weight:600}
.table-wrap{overflow-x:auto}
.spark{width:100%;height:180px} .spark .sl{fill:var(--muted);font-size:11px}
.auth{max-width:380px;margin:40px auto}
.auth form,.grid{display:grid;gap:12px}
.auth label,.grid label{display:flex;flex-direction:column;gap:4px;font-weight:600;font-size:14px}
.grid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.grid label input,.grid label select{max-width:180px}
.datebar{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.radios{display:inline-flex;gap:8px;flex-wrap:wrap;font-weight:600;align-items:center}
.radios label{display:inline-flex;gap:3px;align-items:center;font-weight:600}
.supp{width:100%} .supp th,.supp td{text-align:center;padding:6px} .supp td:first-child,.supp th:first-child{text-align:left}
.symrow{display:flex;gap:8px;align-items:center;margin-bottom:6px} .symrow .symname{flex:1}
.savebar{position:sticky;bottom:0;background:linear-gradient(transparent,var(--bg) 40%);padding:12px 0}
.jr-head{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px}
/* ---- Log page section headings. The page is long by design (everything you enter is on it), so
   the headings do the work the retired tab bar used to do: they are the landmarks you scroll
   between. Bigger and heavier than a card <h2> so they read as dividers, not as another card. ---- */
.logh{font-size:15px;font-weight:800;letter-spacing:.01em;margin:22px 0 8px;
  display:flex;align-items:baseline;gap:7px;flex-wrap:wrap}
.logh:first-of-type{margin-top:12px}
.logx>summary{cursor:pointer;font-size:14px;list-style:none}
.logx>summary::-webkit-details-marker{display:none}
.logx>summary::before{content:'\25B8';display:inline-block;width:1em;color:var(--muted);
  transition:transform .12s ease}
.logx[open]>summary::before{transform:rotate(90deg)}
@media print{.logx{display:none!important}}
/* ---- The left rail. ONE implementation, two naming sets: Fitness/Performance call it
   .tabshell/.tabnav, Config calls it .cfg-shell/.cfg-nav, and they were two copies of the same
   thing with different breakpoints — so between 640 and 720px Config showed a desktop rail on
   a phone. Same rules, one breakpoint, both names. ---- */
.tabshell,.cfg-shell{display:flex;gap:var(--s-4);align-items:flex-start}
.tabnav,.cfg-nav{position:sticky;top:60px;flex:0 0 176px;display:flex;flex-direction:column;
  gap:2px;background:var(--sidebar);border-radius:var(--r-lg);padding:var(--s-2)}
.tabnav button,.cfg-nav button{text-align:left;background:none;border:none;
  border-radius:var(--r-sm);padding:9px 12px;font-weight:600;font-size:14px;color:var(--ink);
  cursor:pointer;opacity:.72}
.tabnav button:hover,.cfg-nav button:hover{opacity:1;background:var(--hover)}
.tabnav button.active,.cfg-nav button.active{background:var(--accent);color:#fff;opacity:1}
/* ---- The Trends hub rail. Same rail, but the items are real links (each panel has its own URL,
   so a chart is bookmarkable and the back button works) and they carry group headings, because the
   point of the hub is that all 22 reports are READABLE AT ONCE. Grouping is what makes a 22-item
   list scannable instead of a wall. ---- */
.hubnav a{display:block;text-align:left;border-radius:var(--r-sm);padding:7px 12px;font-weight:600;
  font-size:13.5px;color:var(--ink);text-decoration:none;opacity:.72}
.hubnav a:hover{opacity:1;background:var(--hover)}
.hubnav a.active{background:var(--accent);color:#fff;opacity:1}
.hubgrp{font-size:10.5px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);padding:12px 12px 4px;opacity:.85}
.hubgrp:first-child{padding-top:4px}
.navsp{flex:1}
@media print{.hubnav,.hubgrp{display:none!important}}
.tabmain,.cfg-panels{flex:1;min-width:0}
.tabpanel,.cfg-panel{display:none}
.tabpanel.active,.cfg-panel.active{display:block}
.chart h3{font-size:13px;margin:0 0 8px;font-weight:700}
svg.cw{width:100%;height:auto;display:block}
.cl{fill:var(--muted);font-size:11px}
/* chart hover: rects/points show the shared #ttip; line-trend dots stay hidden until hovered */
svg.cw [data-tip]{cursor:pointer}
svg.cw circle.dot{opacity:0;transition:opacity .08s}
svg.cw circle.dot:hover{opacity:1}
.zone-toggle{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 10px}
.zone-toggle .zchip{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;
  padding:5px 11px;border-radius:99px;border:1px solid var(--border);cursor:pointer;user-select:none;color:var(--ink)}
.zone-toggle .zchip i{width:10px;height:10px;border-radius:3px;display:inline-block}
.zone-toggle .zchip.off{opacity:.4;text-decoration:line-through}
.clg{display:flex;gap:12px;flex-wrap:wrap;margin-top:6px}
.clg .lg{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--muted)}
.clg .lg i{width:10px;height:10px;border-radius:2px;display:inline-block}
.grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:12px}
.mini b{font-size:20px}
.pmc-toggle label{display:inline-flex;align-items:center;gap:4px;cursor:pointer;font-size:12px;color:var(--muted)}
.pmc-toggle i{width:10px;height:10px;border-radius:2px;display:inline-block}
.zpbar{display:flex;gap:10px;align-items:center;margin-bottom:6px;flex-wrap:wrap}
.zpbar input[type=range]{flex:0 0 150px;accent-color:var(--accent)}
/* phone: the rail becomes a scrolling strip across the top — see the 720px block below */

/* ==========================================================================
   MOBILE
   One stylesheet, not a second site. Everything below reshapes the shared
   primitives — nav, wide tables, input rows, fixed grids — so every page
   benefits at once and no page has a phone-only twin to keep in sync.
   ========================================================================== */

/* ---- iOS zooms the whole page when a focused input is under 16px. That single
   rule is responsible for a lot of what reads as "clunky". ---- */
@media (max-width:900px){
  input,select,textarea,button{font-size:16px}
}

/* ---- Nav: row on desktop, drawer on phones ---- */
.navtoggle{display:none;flex-direction:column;justify-content:center;gap:5px;width:44px;height:44px;
  padding:0 11px;background:none;border:0;cursor:pointer;margin-left:-11px}
.navtoggle span{display:block;height:2px;background:var(--topbar-fg,var(--ink));border-radius:2px;transition:transform .2s,opacity .2s}
.topnav.open .navtoggle span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.topnav.open .navtoggle span:nth-child(2){opacity:0}
.topnav.open .navtoggle span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
.navscrim{position:fixed;inset:0;background:rgba(2,6,23,.55);z-index:19;border:0}
body.navlock{overflow:hidden}
/* .topnav is position:sticky with a z-index, so it forms a stacking context — the drawer's
   own z-index is trapped inside it and cannot rise above the scrim on its own. Lift the whole
   nav above the scrim while it is open, or the scrim swallows every tap on the menu. */
.topnav.open{z-index:30}

@media (max-width:900px){
  .navtoggle{display:flex}
  .topnav{display:flex;align-items:center;gap:10px;padding:8px 14px;
    padding-top:calc(8px + env(safe-area-inset-top))}
  .topnav .brand{font-size:16px}
  .topnav #navlinks{position:fixed;top:0;left:0;bottom:0;width:min(78vw,300px);z-index:20;
    background:var(--card);border-right:1px solid var(--border);
    padding:calc(18px + env(safe-area-inset-top)) 0 18px;
    display:flex;flex-direction:column;gap:0;overflow-y:auto;
    transform:translateX(-102%);transition:transform .22s ease;box-shadow:2px 0 18px rgba(2,6,23,.3)}
  .topnav.open #navlinks{transform:none}
  .topnav #navlinks a{margin:0;padding:15px 22px;font-size:16px;border-bottom:1px solid var(--border)}
  .topnav #navlinks a[aria-current]{background:rgba(59,130,246,.12);
    box-shadow:inset 3px 0 0 var(--accent)}
}
@media (min-width:901px){ .navscrim{display:none} }
@media (prefers-reduced-motion:reduce){
  .topnav #navlinks{transition:none}
  .navtoggle span{transition:none}
}

/* ---- Wide tables → one card per row (labels injected by app.js) ---- */
@media (max-width:720px){
  .rtable,.rtable tbody,.rtable tr{display:block;width:auto}
  .rtable .rt-head{display:none}
  .rtable tr{border:1px solid var(--border);border-radius:12px;padding:11px 13px;
    margin-bottom:10px;background:var(--card)}
  .rtable td,.rtable th{display:flex;justify-content:space-between;align-items:baseline;gap:16px;
    padding:5px 0;border:0;text-align:right;font-weight:400}
  .rtable td::before,.rtable th::before{content:attr(data-label);color:var(--muted);font-weight:600;
    flex:none;text-align:left}
  .rtable tr>*:first-child{display:block;text-align:left;font-weight:700;font-size:16px;
    padding:0;margin:0}
  .rtable tr>*:first-child::before{display:none}
  /* the name of the thing, sitting under its date/id as a subtitle */
  .rtable tr>.rt-sub{display:block;text-align:left;font-weight:400;color:var(--muted);
    padding:2px 0 9px;margin-bottom:6px;border-bottom:1px solid var(--border)}
  .rtable tr>.rt-sub::before{display:none}
  /* no subtitle? the title carries the divider itself */
  .rtable tr>*:first-child:not(:has(+.rt-sub)){padding-bottom:9px;margin-bottom:6px;
    border-bottom:1px solid var(--border)}
  .rtable td:empty,.rtable th:empty{display:none}
}

/* ---- Anything still too wide scrolls inside itself, never the page ---- */
@media (max-width:720px){
  .tw{overflow-x:auto;-webkit-overflow-scrolling:touch}
  body{overflow-x:hidden}
}

/* ---- Journal meal rows: 6 inputs side by side is unusable on a phone ---- */
@media (max-width:720px){
  .mealitem{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;align-items:center;
    padding:10px;border:1px solid var(--border);border-radius:10px;margin-bottom:8px}
  .mealitem .mfood{grid-column:1/-1;min-width:0}
  .mealitem .mserv{grid-column:1/2}
  .mealitem .mkcal{grid-column:2/3}
  .mealitem .mp{grid-column:3/4}
  .mealitem .mc{grid-column:4/5}
  .mealitem .mf{grid-column:1/2}
  .mealitem .xi{grid-column:4/5;justify-self:end}
  .mealitem input{width:100%}
  .mealhead{display:grid;grid-template-columns:1fr auto;gap:8px;align-items:center}
  .mealhead .mealsub{grid-column:1/-1}
}

/* ---- Fixed multi-column rows stack instead of squeezing ---- */
@media (max-width:720px){
  .fuel-row,.mkrow{grid-template-columns:1fr;gap:4px}
  .fuel-val,.mkval{grid-column:1/-1;text-align:left}
}

/* ---- The 7-day week grid becomes a list; the month keeps 7 but shrinks ---- */
@media (max-width:720px){
  /* A week view has to read as a week — seven columns, like every calendar. At 390px
     that is ~50px per day, which fits a day label and modality icons but not prose, so
     the pills go icon-only and the session moves to a tap-opened sheet. */
  .week-grid{grid-template-columns:repeat(7,1fr);gap:3px}
  .week-grid .cal-cell{min-height:60px;padding:4px 2px;text-align:center;border-radius:6px}
  .week-grid .cal-h{font-size:10px;white-space:normal;margin-bottom:3px;line-height:1.1}
  .week-grid .cal-h span{display:block;font-size:9px}
  /* ~50px per day cannot hold a label, so the boxes keep their shape but show icons only.
     The day itself is one tap away, where the full rows live. */
  .week-grid .cminis{flex-direction:row;flex-wrap:wrap;justify-content:center;gap:2px}
  .week-grid .cmini{padding:2px 4px;gap:0}
  .week-grid .cmini b{display:none}
  .week-grid .cmini i{font-size:13px}
  .week-grid .cal-none{font-size:10px}
  .mcal{min-width:0;flex:1 1 100%}
  .mcal-grid{gap:2px}

}

/* ---- Touch targets and breathing room ---- */
@media (max-width:720px){
  .wrap{padding:12px 12px calc(24px + env(safe-area-inset-bottom))}
  .card{padding:13px;border-radius:12px}
  .btn{min-height:40px;padding:9px 13px}
  /* Six sub-columns so evenGrid() in app.js can hand an item a third (span 2) or a half
     (span 3) and always land on full rows — never one box marooned beside a dead gap. */
  .kpis,.kpis.wide,.cal-strip,.pl-days{grid-template-columns:repeat(6,1fr);gap:8px}
  .kpis>*,.cal-strip>*,.pl-days>*{grid-column:span 2}
  .eg-half{grid-column:span 3}
  .eg-full{grid-column:1/-1}
  /* order:-1 lifts it above the countdowns on phones without touching the DOM order,
     so the desktop row keeps the arrangement it already had. */
  .kpi-full{grid-column:1/-1;order:-1;display:flex;align-items:baseline;justify-content:center;
    gap:10px;flex-wrap:wrap;text-align:center}
  .kpi-full b{font-size:16px!important}
  .kpi-full span{font-size:12px}
  .kpi{padding:10px 9px}
  .kpi b{font-size:20px;text-wrap:balance}
  .kpi span{font-size:11px;overflow-wrap:break-word;hyphens:none}
  h1{font-size:22px} h2{font-size:17px}

  #mkedit{grid-template-columns:1fr 1fr}
}

/* ---- Passkeys ---- */
.pk-or{display:flex;align-items:center;gap:12px;margin:16px 0 12px;color:var(--muted);font-size:13px}
.pk-or::before,.pk-or::after{content:'';flex:1;height:1px;background:var(--border)}
.pk-btn{width:100%;justify-content:center;min-height:44px}
.pk-msg{margin:8px 0 0;min-height:1em}
.pk-row{display:flex;align-items:center;gap:12px;padding:11px 0;border-bottom:1px solid var(--border)}
.pk-meta{flex:1;min-width:0}
@media (max-width:720px){ .pk-row{flex-wrap:wrap} }

/* A KPI value that is a phrase rather than a number — sized to read, not to shout. */
.kpi b.kpi-words{font-size:14px;line-height:1.25;font-weight:700;text-wrap:balance}
@media (max-width:620px){ .kpi b.kpi-words{font-size:13px} }

/* ==========================================================================
   MOBILE — fixes from the 390px audit
   ========================================================================== */
@media (max-width:720px){
  /* Routine move tables were the worst offender: 4 columns of prose stretching to 944px
     on a 390px screen. Too few columns for the generic card rule, so they get their own —
     each move becomes a block with its dose and cue stacked under the name. */
  .rt-t,.rt-t tbody,.rt-t tr,.rt-t th,.rt-t td{display:block;width:auto}
  .rt-t tr{border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin-bottom:8px;
    position:relative;padding-right:44px}
  .rt-t th{text-align:left;font-weight:700;font-size:15px;padding:0 0 3px}
  .rt-t td{padding:2px 0;border:0}
  .rt-t .rt-dose{font-weight:700;color:var(--accent);font-size:14px}
  .rt-t td.hint{font-size:13px;line-height:1.45}
  .rt-t .rt-vidcell{position:absolute;top:8px;right:8px;padding:0}
  .rt-t .rt-vid{display:grid;place-items:center;width:36px;height:36px;font-size:19px}

  /* A 176px sticky sidebar beside a panel does not fit on a phone — stack it and let the
     section list scroll across the top instead. Both rails, one rule. */
  .cfg-shell,.tabshell{flex-direction:column;gap:10px}
  .cfg-nav,.tabnav{position:static;flex:none;width:100%;top:0;flex-direction:row;flex-wrap:nowrap;
    overflow-x:auto;-webkit-overflow-scrolling:touch;gap:6px;padding-bottom:4px}
  .cfg-nav button,.tabnav button{white-space:nowrap;flex:none;padding:9px 14px;min-height:40px}
  /* 23 links in a nowrap scroller would just be a sideways hunt. Wrap them into grouped rows:
     the heading breaks the line, its items flow underneath, so the whole map is on screen. */
  .hubnav{flex-wrap:wrap;overflow:visible;gap:5px}
  .hubnav a{white-space:nowrap;flex:none;padding:7px 11px;min-height:36px;font-size:13px;
    display:flex;align-items:center;background:var(--card);border:1px solid var(--border)}
  .hubnav a.active{border-color:var(--accent)}
  .hubgrp{width:100%;flex:0 0 100%;padding:8px 2px 1px;border-left:none}
  .hubgrp:first-child{padding-top:2px}
  .cfg-panels,.tabmain{width:100%;min-width:0}
  .cfg-panel,.tabpanel{max-width:100%;overflow-x:hidden}

  /* Tap targets the audit flagged as too small to hit reliably */
  .ol-btn{padding:9px 16px;min-height:40px}
  .rt-pop{width:40px;height:40px;display:grid;place-items:center;top:50%}
  .rt-vid{min-width:34px;min-height:34px}
  input[type=checkbox],input[type=radio]{width:20px;height:20px}
  .pct,
  /* 9px is below what anyone reads on a phone */
  .week-grid .cal-h span{font-size:10px}

  /* Nothing may push the page sideways */
  .wrap,.card,.cfg-panel,section,main{max-width:100%}
  table:not(.rtable):not(.calmonth):not(.calyear):not(.rt-t){max-width:100%}
}

@media (max-width:720px){
  /* A file input carries a wide intrinsic size ("Choose File — no file selected"), which
     pushed the upload rows past the screen. Let it wrap and cap it. */
  .pf-uprow{width:100%}
  .pf-uprow input[type=file]{max-width:100%;flex:1 1 160px;min-width:0;font-size:13px}
  .pf-uprow .btn{flex:none}
}

/* ---- Plan: the day editor ---- */
.bedit{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:14px;
  padding-top:14px;border-top:1px solid var(--border)}
.bedit-flag{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;
  color:var(--accent);border:1px solid var(--accent);border-radius:99px;padding:1px 8px}
.pe-bar{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.pe-list{display:flex;flex-direction:column;gap:8px}
.pe-item{display:flex;align-items:center;gap:10px;padding:11px 12px;border:1px solid var(--border);
  border-radius:10px;background:var(--card)}
.pe-item.dragging{opacity:.4}
.pe-item.over{border-color:var(--accent);box-shadow:0 -2px 0 var(--accent) inset}
.pe-grip{cursor:grab;color:var(--muted);font-size:18px;flex:none;padding:6px 8px;margin:-6px -4px -6px -8px;
  touch-action:none;user-select:none;-webkit-user-select:none}
.pe-item.dragging{opacity:.55;border-color:var(--accent);background:rgba(59,130,246,.10)}
.pe-ic{font-size:20px;flex:none}
.pe-txt{flex:1;min-width:0;display:flex;flex-direction:column}
.pe-txt b{font-size:15px;line-height:1.25}
.pe-txt .hint{font-size:12px}
.pe-ord{display:flex;gap:4px;flex:none}
.pe-ord .btn{min-width:34px;min-height:34px;padding:0}
.pe-preview{margin-top:12px;padding-top:10px;border-top:1px dashed var(--border);font-size:14px}
.pe-rep{display:flex;gap:10px;align-items:flex-start;margin-bottom:12px;font-size:14px}
.pe-rep input{margin-top:3px;flex:none}
.pe-actions{display:flex;gap:8px;flex-wrap:wrap}
.pe-move{display:flex;gap:14px;flex-wrap:wrap}
.pe-move label{display:flex;flex-direction:column;gap:4px;font-size:13px;color:var(--muted)}
/* picker sheet */
.pe-modal{position:fixed;inset:0;z-index:50;background:rgba(2,6,23,.6);display:flex;
  align-items:center;justify-content:center;padding:20px}
.pe-sheet{background:var(--card);border:1px solid var(--border);border-radius:14px;
  width:min(560px,100%);max-height:min(86vh,700px);display:flex;flex-direction:column;
  overflow:hidden;box-shadow:0 20px 60px rgba(2,6,23,.5)}
/* On a phone a centred dialog wastes the screen — dock it to the bottom instead. */
@media (max-width:620px){
  .pe-modal{align-items:flex-end;padding:0}
  .pe-sheet{border-radius:14px 14px 0 0;max-height:92vh}
}
.pe-sheet-h{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;
  border-bottom:1px solid var(--border)}
.pe-tabs{display:flex;gap:6px;padding:10px 16px 0}
.pe-tab{flex:1;padding:10px;border:1px solid var(--border);border-radius:9px;background:none;
  color:inherit;font:inherit;font-weight:600;cursor:pointer}
.pe-tab.active{background:var(--accent);color:#fff;border-color:var(--accent)}
.pe-pane{padding:14px 16px 20px;overflow-y:auto}
.pe-grp{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);margin:14px 0 6px}
.pe-pickrow{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;
  padding:11px 12px;border:1px solid var(--border);border-radius:9px;background:none;color:inherit;
  font:inherit;text-align:left;cursor:pointer;margin-bottom:6px}
.pe-pickrow:hover{border-color:var(--accent);background:rgba(59,130,246,.10)}
.pe-field{display:flex;flex-direction:column;gap:5px;margin-bottom:12px}
.pe-field label{font-size:13px;color:var(--muted);font-weight:600}
.pe-2col{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.pe-sports{display:flex;flex-wrap:wrap;gap:6px}
.pe-sport{padding:9px 12px;border:1px solid var(--border);border-radius:9px;background:none;
  color:inherit;font:inherit;cursor:pointer}
.pe-sport.on{background:var(--accent);color:#fff;border-color:var(--accent)}
.pe-wide{width:100%}
/* editing an existing item, not adding another — say so plainly */
.pe-sheet.editing{box-shadow:0 0 0 2px var(--accent), 0 20px 60px rgba(2,6,23,.5)}
.pe-sheet.editing .pe-sheet-h{background:rgba(59,130,246,.12)}
.pe-ord .btn.xi[data-ed]{color:var(--accent)}
@media (max-width:620px){
  .pe-2col{grid-template-columns:1fr}
  .pe-move label{width:100%}
}

/* ---- Day navigation, sitting on the date itself ---- */
.bdate-nav{display:flex;align-items:center;gap:4px}
.dnav{display:grid;place-items:center;width:34px;height:34px;flex:none;border-radius:9px;
  color:var(--muted);text-decoration:none;font-size:20px;line-height:1;border:1px solid transparent}
.dnav:hover{color:var(--ink);background:rgba(148,163,184,.14);border-color:var(--border)}
.dpick{position:relative;font-size:15px;cursor:pointer;margin-left:2px}
/* the real input covers the icon so a tap anywhere on it opens the native picker */
.dpick input{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:pointer;
  border:0;padding:0;background:none}
.bdate-nav .bdate{padding:0 2px}
/* a calendar cell is now a link */
a.cal-cell{display:block;text-decoration:none;color:inherit}
a.cal-cell:hover{border-color:var(--accent)}
@media (max-width:620px){
  .dnav{width:40px;height:40px}
}

/* Month cells. iPad reports `hover: none`, so a hover peek is invisible there — the cell has
   to carry the information itself whenever it has room, rather than hiding it behind a gesture
   half the devices cannot make. Labels appear once a cell is wide enough to hold them. */
a.mcal-day{display:block;text-decoration:none;color:inherit}
a.mcal-day:hover{border-color:var(--accent)}
.mcal-day .cminis{flex-direction:row;flex-wrap:wrap;gap:2px}
.mcal-day .cmini{padding:1px 3px;gap:0;border-radius:4px}
.mcal-day .cmini b{display:none}
.mcal-day .cmini i{font-size:11px}
@media (min-width:860px){
  .mcal-day{min-height:76px}
  .mcal-day .cminis{flex-direction:column;gap:2px}
  .mcal-day .cmini{gap:4px;padding:2px 4px;width:100%}
  .mcal-day .cmini b{display:block;font-size:10.5px;font-weight:600;line-height:1.2;
    overflow:hidden;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical}
}

/* ---- Week / month navigation: the same header the day view uses ---- */
.calnav-h{display:flex;align-items:center;gap:4px;margin:0 0 14px;padding-bottom:10px;
  border-bottom:1px solid var(--border)}
.calnav-t{font-size:17px;font-weight:700;letter-spacing:-.01em;padding:0 2px}
.ol-toggle a.ol-btn{text-decoration:none;display:inline-block}
.cal-wk{margin-bottom:18px}
.cal-wk:last-of-type{margin-bottom:0}
@media (max-width:620px){ .calnav-t{font-size:15px} }

/* ---- Hover peek on a week/month cell ----
   Gated to real pointers: on touch the cell is a link and tapping opens the day, so this must
   never appear there (that was the old popover's whole problem). pointer-events:none so it can
   never swallow the click it sits on top of. */
.cday-pop{display:none}
/* any-hover, NOT hover. iPadOS reports `hover: none` / `pointer: coarse` even with a trackpad
   attached, because those describe the PRIMARY input and it still considers that touch —
   so `(hover:hover)` excluded the iPad by definition. `any-hover` asks whether any attached
   input can hover, which is the actual question. Harmless if a touch device answers yes: the
   cell is a link, so a tap navigates before a stuck hover state could matter. */
@media (any-hover:hover){
  .cal-cell,.mcal-day{position:relative}
  .cday-pop{display:block;position:absolute;left:50%;transform:translateX(-50%);
    bottom:calc(100% + 8px);z-index:40;width:max-content;min-width:180px;max-width:280px;
    background:var(--card);border:1px solid var(--border);border-radius:10px;padding:10px 12px;
    box-shadow:0 10px 30px rgba(2,6,23,.4);opacity:0;visibility:hidden;pointer-events:none;
    transition:opacity .12s;text-align:left}
  .cal-cell:hover .cday-pop,.mcal-day:hover .cday-pop{opacity:1;visibility:visible}
  /* edge columns cannot centre without leaving the grid */
  .cday-pop.pk-l{left:0;transform:none}
  .cday-pop.pk-r{left:auto;right:0;transform:none}
  .cday-pop-h{display:block;font-size:12px;color:var(--muted);text-transform:uppercase;
    letter-spacing:.07em;margin-bottom:7px}
  .cday-pop-r{display:flex;gap:8px;align-items:flex-start;padding:3px 0;font-size:13px;
    line-height:1.35;font-weight:600}
  .cday-pop-r i{font-style:normal;font-size:14px;flex:none}
  .cday-pop-r em{display:block;font-style:normal;font-weight:400;font-size:11.5px;
    color:var(--muted);margin-top:1px}
  .cday-pop-r.st-done{opacity:.5}
  .cday-pop-r.st-done>span{text-decoration:line-through}
  .cday-pop-r.st-skipped{opacity:.42}
}
@media print{.cday-pop{display:none!important}}

/* ==========================================================================
   TEXTURE
   A hairline of light on the bottom and right edges of every surface — one
   source, low and to the right. The VALUES live in theme_texture() in lib.php,
   not here: strength and tint are settings, and dark/light has to follow the
   theme's own verdict (the card colour you picked) rather than the OS, or a
   light theme on a dark phone gets invisible highlights.
   ========================================================================== */

.card{
  background-image:linear-gradient(315deg, var(--sheen, transparent), transparent 160px);
  box-shadow:var(--emboss), var(--lift);
}
/* Day rows deliberately take NO texture: they are hairlines inside an already-embossed card,
   and a bevel on each one is what made a list of five things look like five objects. */

.kpi{box-shadow:var(--emboss-lo);
  background-image:linear-gradient(315deg, var(--sheen, transparent), transparent)}
.cal-cell,.mcal-day{box-shadow:var(--emboss-lo)}
.cal-cell.today,.mcal-day.today{box-shadow:var(--emboss), 0 0 0 1px var(--accent) inset}
.cmini{box-shadow:var(--emboss-lo)}
.btn,.ib{box-shadow:var(--emboss-lo)}
.btn:active,.ib:active{box-shadow:inset 0 2px 4px rgba(2,6,23,.3)}
.pe-item,.pe-sheet,.trun{box-shadow:var(--emboss-lo)}
.rd-card{box-shadow:var(--emboss-lo)}
.cday-pop{box-shadow:var(--emboss), 0 14px 40px rgba(2,6,23,.5)}
/* the sticky top bar wants a little weight so content scrolls *under* something */
.topnav{box-shadow:0 1px 0 var(--sheen, transparent), 0 2px 12px rgba(2,6,23,.3)}

@media print{
  .card,.drow,.kpi,.cal-cell,.mcal-day,.cmini,.btn,.topnav{box-shadow:none!important;
    background-image:none!important}
}

/* ---- Dashboard: today's session, a summary that hands off to the Plan ---- */
.tsess-r{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.tsess-i{display:inline-flex;align-items:center;gap:7px;padding:7px 11px;border-radius:9px;
  border:1px solid var(--border);border-left:3px solid var(--c,var(--border));
  background:var(--card);font-size:14px;box-shadow:var(--emboss-lo)}
.tsess-i i{font-style:normal;font-size:16px}
.tsess-i b{font-weight:600}
/* Status reads as a mark, not just a tone — opacity alone is invisible on a phone in sun. */
.tsess-i[class*=" st-"]::after{font-size:12px;opacity:.85}
.tsess-i.st-done{opacity:.55}
.tsess-i.st-done b{text-decoration:line-through}
.tsess-i.st-done::after{content:"✓";color:var(--good)}
.tsess-i.st-partial::after{content:"◐";color:var(--warn)}
.tsess-i.st-skipped{opacity:.45}
.tsess-i.st-skipped b{text-decoration:line-through}
.tsess-i.st-skipped::after{content:"✗";color:var(--bad)}
.tsess-go{margin-left:auto;display:flex;align-items:center;gap:10px}
.tsess-rd{margin-top:11px;padding:9px 12px;border-radius:9px;font-size:13.5px;
  border:1px solid var(--border)}
.tsess-rd.rd-red{background:color-mix(in srgb,var(--bad) 10%,transparent);
  border-color:color-mix(in srgb,var(--bad) 45%,transparent)}
.tsess-rd.rd-amber{background:color-mix(in srgb,var(--warn) 10%,transparent);
  border-color:color-mix(in srgb,var(--warn) 45%,transparent)}
@media (max-width:620px){ .tsess-go{margin-left:0;flex:1 1 100%} }
/* Log calendar: non-ride activities carry their own marker — bike miles tint the cell, so an
   activity-only day would otherwise be indistinguishable from a rest day. */
.calmonth .cm.ca{opacity:.85;font-size:11px}
/* Dashboard week: non-bike sessions, listed rather than summed into the bike KPIs. */
.wkacts-h{display:flex;align-items:center;gap:9px;font-weight:600;margin-bottom:10px}
.wkacts-h .btn{margin-left:auto}
.wkacts-r{display:flex;flex-wrap:wrap;gap:8px}
.wka{display:inline-flex;align-items:center;gap:8px;padding:7px 11px;border-radius:9px;
  border:1px solid var(--border);border-left:3px solid var(--c,var(--border));
  background:var(--card);font-size:14px;box-shadow:var(--emboss-lo)}
.wka i{font-style:normal;font-size:16px}
.wka .hint{font-size:12.5px}
@media (max-width:620px){ .wka{width:100%} }
/* Day editor: the authored-prescription box. Multi-line, so it needs the same chrome as the inputs. */
.pe-field textarea{width:100%;padding:9px 11px;border-radius:8px;border:1px solid var(--border);
  background:var(--card);color:var(--ink);font:inherit;font-size:14px;resize:vertical;line-height:1.5}
/* Performance: sport switcher. The page answers a different question per sport, so the choice
   belongs at the top, not buried in a filter row. */
.sportbar{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0 4px}
/* .sportpill / .ctxchip / .lib-nav a are the .pill primitive — they keep their own names only
   because three pages name them in markup. Everything but the extras comes from .pill. */
.sportpill,.ctxchip,.lib-nav a{display:inline-flex;align-items:center;gap:6px;padding:6px 13px;
  border-radius:var(--r-pill);border:1px solid var(--border);background:var(--card);
  color:var(--ink);text-decoration:none;font-size:14px;box-shadow:var(--emboss-lo)}
.sportpill:hover,.ctxchip:hover,.lib-nav a:hover{border-color:var(--c,var(--accent))}
.sportpill.on,.ctxchip.on{border-color:var(--c,var(--accent));font-weight:600;
  box-shadow:var(--emboss-lo),0 0 0 1px var(--c,var(--accent)) inset}
.sportpill .hint{font-size:12px}
/* Fitness PMC: per-sport inclusion chips, one row under the series legend. */
.clg.pmc-sports{margin-top:2px}
.clg.pmc-sports label{text-transform:capitalize}
/* Plan editor: inline "move this item to another day" bar, revealed under the item row. */
.pe-mvbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:8px 0 2px;
  padding:9px 11px;border-radius:9px;border:1px solid var(--border);background:var(--bg);
  grid-column:1/-1}
.pe-mvbar input[type=date]{padding:6px 9px;border-radius:7px;border:1px solid var(--border);
  background:var(--card);color:var(--ink);font:inherit;font-size:14px}
.pe-mvbar .hint{flex:1 1 auto;min-width:120px}
/* Journal: last-night context chips. Tag only the exceptions — blank is the normal night. */
.ctxchips{display:flex;flex-wrap:wrap;gap:7px}
.ctxchip{font-size:13.5px;cursor:pointer;user-select:none}
.ctxchip input{margin:0;accent-color:var(--accent)}
/* Public-profile widget: Today's fuel — the "meals eaten" and "still needed" views. */
.mealist{display:flex;flex-direction:column;gap:7px}
.mealist{min-width:0}
/* minmax(0,1fr), not 1fr: a plain 1fr track floors at the content's min-content width, so a long
   run of food names pushed the row wider than the tile and the whole widget scrolled sideways. */
.mealrow{display:grid;grid-template-columns:52px minmax(0,1fr) auto;gap:10px;align-items:start;
  padding-bottom:6px;border-bottom:1px solid var(--border);min-width:0}
.mealrow:last-child{border-bottom:0;padding-bottom:0}
.mr-t{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px;color:var(--muted)}
.mr-b{display:flex;flex-direction:column;min-width:0}
.mr-b{min-width:0}
.mr-b>b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Each logged item on its own line, wrapping. overflow-wrap:anywhere so a long unbroken product
   name breaks rather than forcing the grid track wider than the tile. */
.mr-i{display:block;font-size:11.5px;color:var(--muted);line-height:1.35;
  white-space:normal;overflow-wrap:anywhere}
.mr-b .hint{font-size:12px}
@media(max-width:700px){
  .mealrow{grid-template-columns:42px minmax(0,1fr) auto;gap:7px}
  .mr-t{font-size:11.5px}
  .mr-n{font-size:12.5px}
}
.mr-n{text-align:right;font-variant-numeric:tabular-nums;font-size:13.5px;white-space:nowrap}
.mr-n .hint{display:block;font-size:11.5px}
.mealrow.planned{opacity:.72}
.mealrow.planned .mr-n{color:var(--accent)}
.mr-tag{align-self:flex-start;margin:1px 0 2px;padding:1px 6px;border:1px dashed var(--accent);
  border-radius:99px;font-size:10px;font-weight:700;letter-spacing:.04em;color:var(--accent);
  text-transform:uppercase}
/* The share view is a copy of the share graphic's Stats template — title, subtitle, then a 2-up
   grid of four tiles with the value large and the label beneath. Same shapes, same order. */
.fs-sub{font-size:13px;color:var(--muted);margin:2px 0 16px;line-height:1.45;max-width:46ch}
.fs-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px 16px}
.fs-tile{display:flex;flex-direction:column;gap:3px;min-width:0}
.fs-tile b{font-size:26px;font-weight:800;letter-spacing:-.02em;line-height:1.05;color:var(--ink);
  font-variant-numeric:tabular-nums;white-space:nowrap;
  /* nowrap without this lets an over-long value run straight across the next tile */
  overflow:hidden;text-overflow:ellipsis}
.fs-tile span{font-size:12px;color:var(--muted);line-height:1.25}
@media(max-width:420px){ .fs-tile b{font-size:22px} }
/* The share graphic is sized for a full-bleed image; inside a 158px profile tile the same type
   scale overflows and the tile starts scrolling. Scope it down to the tile without touching the
   shareable graphic itself. */
.pf-tile .fs-sub{font-size:12px;margin:1px 0 9px;line-height:1.35;max-width:none}
.pf-tile .fs-grid{gap:9px 12px}
.pf-tile .fs-tile b{font-size:19px}
.pf-tile .fs-tile span{font-size:11px}
@media(max-width:700px){
  .pf-tile .fs-sub{margin-bottom:7px}
  .pf-tile .fs-grid{gap:7px 10px}
  .pf-tile .fs-tile b{font-size:17px}
}

/* ---- Supplements widget ------------------------------------------------------------------
   Name on the left, the three slots on the right. An untaken row is dimmed rather than hidden,
   because the question the widget answers is what is still owed today. */
.sw-list{display:flex;flex-direction:column;gap:5px;min-width:0}
.sw-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center}
.sw-n{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sw-row.todo .sw-n{color:var(--muted)}
.sw-slots{display:flex;gap:4px}
.sw-slot{padding:1px 6px;border:1px solid var(--border);border-radius:99px;font-size:10px;
  font-weight:600;color:var(--muted);letter-spacing:.02em}
.sw-slot.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 16%,transparent);
  color:var(--accent)}

/* ---- REAMS report ---------------------------------------------------------------------------
   A reading is judged against its HEALING range, not its distance from "perfect" — for salts and
   cell debris the healing band sits above perfect by design, so colour comes from state, never
   from which number is bigger. */
.rm-intro{margin:10px 2px 0;line-height:1.5}
.rm-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:12px;margin-top:4px}
.rm-card{border:1px solid var(--border);border-left-width:4px;border-radius:var(--r-md);
  padding:11px 13px;background:var(--inner);min-width:0}
.rm-card.rm-ok  {border-left-color:var(--good)}
.rm-card.rm-low {border-left-color:var(--warn)}
.rm-card.rm-high{border-left-color:var(--bad)}
.rm-lab{font-size:12px;font-weight:700;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}
.rm-val{font-size:26px;font-weight:800;letter-spacing:-.02em;line-height:1.15;
  font-variant-numeric:tabular-nums;color:var(--ink)}
.rm-sub{font-size:11.5px;color:var(--muted);line-height:1.35;margin-top:1px}
.rm-meta{display:flex;justify-content:space-between;gap:8px;margin-top:7px;font-size:11px;
  color:var(--muted);font-variant-numeric:tabular-nums}
.rm-eff{margin-top:8px;height:14px;position:relative;background:rgba(148,163,184,.18);border-radius:99px}
.rm-eff span{position:absolute;inset:0 auto 0 0;background:var(--accent);border-radius:99px}
.rm-eff b{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:10px;font-weight:700;color:var(--ink)}
.rm-tbl{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums;font-size:13px}
.rm-tbl th,.rm-tbl td{padding:6px 9px;border-bottom:1px solid var(--border);text-align:right;white-space:nowrap}
.rm-tbl th:first-child,.rm-tbl td:first-child{text-align:left}
.rm-tbl th{font-size:11.5px;color:var(--muted);font-weight:600}
.rm-tbl td.rm-low {color:var(--warn);font-weight:700}
.rm-tbl td.rm-high{color:var(--bad);font-weight:700}
.rm-form{margin-top:4px}
.rm-fgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:9px;margin-top:9px}
.rm-f{display:flex;flex-direction:column;gap:3px;font-size:12px;font-weight:600;min-width:0}
.rm-f span{color:var(--muted);font-weight:600}
.rm-f.rm-wide{margin-top:9px}
@media(max-width:640px){ .rm-val{font-size:22px} }

/* REAMS trends — the shaded band behind each line is the HEALING range, so the eye reads a
   reading against where it should be rather than against the other readings. */
.rm-trends{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}
.rm-tcard{border:1px solid var(--border);border-radius:var(--r-md);padding:10px 12px;
  background:var(--inner)}
.rm-tlab{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:12px;
  font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.02em}
.rm-tlab b{font-size:16px;letter-spacing:-.01em;font-variant-numeric:tabular-nums;text-transform:none}
.rm-tlab b.rm-ok{color:var(--good)} .rm-tlab b.rm-low{color:var(--warn)} .rm-tlab b.rm-high{color:var(--bad)}
.rm-spark{width:100%;height:74px;display:block;margin:6px 0 2px;overflow:visible}
.rm-trange{font-size:10.5px;color:var(--muted);font-variant-numeric:tabular-nums}
/* ---- One logical session (session.php) -------------------------------------------------------
   A session the watch split into two or three recordings, shown as one. Everything here reuses the
   site's card/table/kpi chrome; the only new ideas are the back arrow, the stitched-session note
   and the pause row — the pause has to LOOK like an interruption, because reading it as ordinary
   whitespace is exactly how a 9-lap run passed for two pointless 5-minute ones. */
.sess-head{display:flex;align-items:flex-start;gap:10px}
.sess-back{color:var(--muted);text-decoration:none;font-size:26px;line-height:1;
  padding:2px 8px 2px 0;margin-top:2px;flex:none}
.sess-back:hover{color:var(--ink)}
.sess-ttl{min-width:0}
.sess-ttl h1{margin:0;font-size:22px;overflow-wrap:anywhere}
.sess-note{margin:10px 0 0;padding:10px 12px;border-radius:var(--r-md);font-size:13px;line-height:1.5;
  background:color-mix(in srgb,var(--accent) 8%,var(--card));
  border:1px solid color-mix(in srgb,var(--accent) 35%,transparent)}
.sess-h2{margin:22px 0 8px;font-size:15px;font-weight:800;letter-spacing:.01em}
.sess-foot{margin:9px 0 0;line-height:1.5;white-space:normal}
/* Column units live in the header as a second line, so the cells stay bare numbers. Case is NOT
   normalised here: "W" is watts and "w" is not. */
.laptbl th small{display:block;font-weight:400;font-size:10px;letter-spacing:.04em;
  color:var(--muted)}
.laptbl td small{font-size:10.5px;font-weight:400}
.laptbl tbody tr:not(.lap-gap):hover{background:var(--hover)}
tr.lap-gap td{background:color-mix(in srgb,var(--warn,#d97706) 11%,var(--card));
  color:var(--muted);font-size:12px;font-weight:600;letter-spacing:.02em;
  border-top:1px dashed color-mix(in srgb,var(--warn,#d97706) 55%,transparent);
  border-bottom:1px dashed color-mix(in srgb,var(--warn,#d97706) 55%,transparent);
  white-space:normal}
/* Phone (390 px): app.js already turns any 5+-column table into one card per row and the site's own
   rule puts the KPI grid on a 6-column track, so nothing here may touch either — an earlier
   .kpis.wide override fought that rule and dropped the KPIs to one per row. Only the title and the
   lap table's own density are this page's business. */
@media (max-width:620px){
  .sess-ttl h1{font-size:19px}
  .sess-head{gap:6px}
  .laptbl{font-size:12px}
  .laptbl th,.laptbl td{padding:6px 7px}
}
/* The dashboard's non-bike chip, when it is a link to a stitched session. */
a.wka{text-decoration:none;color:inherit}
a.wka:hover{background:var(--hover)}
.wka .wkap{font-size:11px;font-weight:700;color:var(--muted);
  border:1px solid var(--border);border-radius:99px;padding:1px 6px}
/* "2 parts" marker on a history row whose session the watch split into several recordings. */
.npill{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.02em;
  padding:1px 6px;border-radius:99px;vertical-align:1px;white-space:nowrap;
  color:var(--warn);background:color-mix(in srgb,var(--warn) 12%,transparent);
  border:1px solid color-mix(in srgb,var(--warn) 40%,transparent)}
