:root {
  --bg: #f2f2f7; --card: #fff; --card2: #fff; --line: #e3e3e8;
  --fg: #000; --fg2: #6c6c70; --fg3: #a1a1a6;
  --accent: #007aff; --good: #30a14e; --warn: #ff9f0a; --bad: #ff453a;
  /* --muted was used in six rules and declared in none, so every label meant
     to recede was inheriting the card's foreground and shouting at full
     strength. --line2 is the previous watch's stretch of a sparkline: visible
     as a line, clearly not the live one. */
  --muted: #8a8a8e; --line2: #c7c7cc;
  --radius: 14px;
  --safe-b: env(safe-area-inset-bottom, 0px);
  color-scheme: light dark;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #000; --card: #1c1c1e; --card2: #2c2c2e; --line: #38383a;
    --fg: #fff; --fg2: #98989f; --fg3: #6c6c70;
    --accent: #0a84ff; --good: #32d74b; --warn: #ffd60a; --bad: #ff453a;
    --muted: #8e8e93; --line2: #48484a;
  }
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg); color: var(--fg);
  font: 15px/1.45 -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  padding-bottom: calc(58px + var(--safe-b));
}
a { color: var(--accent); text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* ---------------------------------------------------------------- layout */
main { max-width: 780px; margin: 0 auto; padding: 0 16px 32px; }
header.top {
  max-width: 780px; margin: 0 auto; padding: 22px 16px 6px;
}
header.top h1 { margin: 0; font-size: 30px; font-weight: 700; letter-spacing: -0.4px; }
header.top .sub { color: var(--fg2); font-size: 14px; margin-top: 2px; }

section { margin-top: 22px; }
h2 {
  margin: 0 0 8px; font-size: 13px; font-weight: 600; letter-spacing: 0.4px;
  text-transform: uppercase; color: var(--fg2); padding-left: 4px;
}

.card {
  background: var(--card); border-radius: var(--radius);
  padding: 14px 16px; margin-bottom: 10px;
}
.grid { display: grid; gap: 10px; grid-template-columns: repeat(2, 1fr); }
.grid > .card { margin-bottom: 0; }
/* Three across even on a phone — he asked for dense once you're in the detail. */
.grid.g3 { grid-template-columns: repeat(3, 1fr); gap: 8px; }
/* Four stats in a three-wide grid leaves the fourth stranded on its own row at
   full width. Two-by-two is the balanced shape for four. */
.grid.g3:has(> :nth-child(4):last-child) { grid-template-columns: repeat(2, 1fr); }
.grid.g3 > .card { padding: 11px 12px; }
.grid.g3 .value { font-size: 21px; letter-spacing: -0.4px; }
.grid.g3 .value .unit { font-size: 11px; margin-left: 1px; }
.grid.g3 .label { font-size: 11px; }

/* ------------------------------------------------------------- stat cards */
.stat { display: flex; flex-direction: column; gap: 2px; }
.stat .label { font-size: 12px; color: var(--fg2); font-weight: 500; }
.stat .value { font-size: 27px; font-weight: 600; letter-spacing: -0.6px; line-height: 1.15; }
.stat .value .unit { font-size: 14px; font-weight: 500; color: var(--fg2); margin-left: 2px; }
.stat .note { font-size: 12px; color: var(--fg2); }
.stat.wide .value { font-size: 34px; }

.z { font-weight: 600; }
.z.up { color: var(--good); } .z.down { color: var(--bad); } .z.flat { color: var(--fg2); }
.chip {
  display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 7px;
  border-radius: 999px; background: var(--card2); color: var(--fg2);
  border: 1px solid var(--line);
}
@media (prefers-color-scheme: dark) { .chip { border-color: transparent; } }
.src { font-size: 11px; color: var(--fg3); }

/* ------------------------------------------------------------- disclosure */
details.more { margin-top: 10px; border-top: 1px solid var(--line); padding-top: 8px; }
details.more > summary {
  list-style: none; cursor: pointer; font-size: 12px; color: var(--accent);
  font-weight: 500;
}
details.more > summary::-webkit-details-marker { display: none; }
details.more > summary::after { content: " ›"; }
details.more[open] > summary::after { content: " ⌄"; }

/* ------------------------------------------------------------------ table */
table.data { width: 100%; border-collapse: collapse; font-size: 12.5px; font-variant-numeric: tabular-nums; }
table.data th {
  text-align: left; font-weight: 600; color: var(--fg2); font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.3px; padding: 6px 8px 6px 0;
  border-bottom: 1px solid var(--line); position: sticky; top: 0; background: var(--card);
}
table.data td { padding: 5px 8px 5px 0; border-bottom: 1px solid var(--line); vertical-align: top; }
table.data tr:last-child td { border-bottom: 0; }
table.data td.num, table.data th.num {
  text-align: right; padding-right: 0; padding-left: 12px; white-space: nowrap;
}
.scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; }

/* ------------------------------------------------------------------- list */
.row {
  display: flex; align-items: center; gap: 12px; padding: 11px 16px;
  background: var(--card); border-bottom: 1px solid var(--line);
  color: var(--fg);
}
.row:first-child { border-radius: var(--radius) var(--radius) 0 0; }
.row:last-child { border-bottom: 0; border-radius: 0 0 var(--radius) var(--radius); }
.row:only-child { border-radius: var(--radius); }
.row .ico { font-size: 21px; width: 28px; text-align: center; flex: none; }
.row .mid { flex: 1; min-width: 0; }
.row .t1, .row .t2 { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row .t1 { font-weight: 600; font-size: 15px; }
.row .t2 { font-size: 12.5px; color: var(--fg2); }
.row .end { flex: none; text-align: right; font-size: 12.5px; color: var(--fg2); font-variant-numeric: tabular-nums; }
.row .end b { display: block; color: var(--fg); font-size: 15px; font-weight: 600; }

/* ------------------------------------------------------------------ coach */
.coach {
  background: linear-gradient(180deg, var(--card), var(--card));
  border-left: 3px solid var(--accent); border-radius: 6px var(--radius) var(--radius) 6px;
}
.coach .who { font-size: 11px; font-weight: 700; letter-spacing: 1px; color: var(--accent); }
.coach p { margin: 6px 0 0; font-size: 15px; line-height: 1.5; white-space: pre-wrap; }

/* ------------------------------------------------------------------ zones */
.zbar { display: flex; height: 26px; border-radius: 6px; overflow: hidden; margin: 6px 0 4px; }
.zbar div { min-width: 0; }
.zlegend { display: flex; gap: 10px; flex-wrap: wrap; font-size: 11.5px; color: var(--fg2); }
.zlegend i { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 4px; }

/* Sleep stages.
   This was one stacked bar, stages laid end to end deepest-first. It reads as a
   timeline — left to right, in order — and he read it as one, which is a fair
   thing to do with a horizontal bar that starts at bedtime's side of the card.
   It never was one: Apple sends a total per stage and no intervals, so the
   sequence in that bar was alphabetical-by-depth, i.e. invented.
   One track per stage cannot be misread as time. Every track is 0-100% of the
   night, so the four stay comparable, and the tick is his own median share. */
.stages { display: grid; gap: 12px; margin: 14px 0 8px; }
/* Label and numbers on one line, the bar on its own beneath it. Four fixed
   columns plus a flexible track fit a laptop and starved the track on a phone
   — at 390px it came out ~20px wide and deep and REM were the same picture. */
.stage .hd {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; font-size: 12px; margin-bottom: 5px;
}
.stage .nm { color: var(--fg2); font-weight: 500; display: flex; align-items: center; gap: 6px; }
.stage .nm i { width: 8px; height: 8px; border-radius: 2px; flex: none; }
/* Fixed sub-columns so duration, share and usual line up down the four rows.
   Left as flex they wrapped to wherever each string ended, and Awake — which
   has no usual share to show — pulled its own row out of line with the rest. */
.stage .vals {
  display: inline-grid; grid-template-columns: 58px 34px 62px;
  gap: 8px; align-items: baseline;
  font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right;
}
.stage .vals b { font-weight: 600; color: var(--fg); }
.stage .vals .pc { color: var(--fg2); }
.stage .vals em { font-style: normal; font-size: 11px; color: var(--fg3); }
.stage .track {
  position: relative; height: 9px; border-radius: 5px;
  background: color-mix(in srgb, var(--fg) 8%, transparent);
}
.stage .fill { height: 100%; border-radius: 5px; }
/* The tick overhangs the bar top and bottom so it stays legible whether the
   night landed under or over his usual share. */
.stage .med {
  position: absolute; top: -3.5px; width: 2px; height: 16px; margin-left: -1px;
  background: var(--fg); opacity: .5; border-radius: 1px;
}
.stagenote { margin: 2px 0 0; }

/* Autonomic markers. Were accent-blue pills reading "Blood oxygen down far
   above usual" — the label, a hard-coded direction and a magnitude that had
   been through Math.abs, three things saying two. Now: the marker, then one
   phrase that carries both direction and size, tinted only when it is past
   two sigma. */
.markers { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.marker {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 5px 10px; border-radius: 8px; font-size: 12px;
  background: color-mix(in srgb, var(--fg) 6%, transparent); color: var(--fg2);
}
.marker b { font-weight: 600; color: var(--fg); }
.marker.hard { background: color-mix(in srgb, var(--warn) 16%, transparent); }
.marker.hard b { color: var(--warn); }

/* ------------------------------------------------------------------- tabs */
nav.tabs {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 20;
  display: flex; justify-content: space-around;
  padding-bottom: var(--safe-b);
  background: color-mix(in srgb, var(--card) 82%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--line);
}
nav.tabs a {
  flex: 1; text-align: center; padding: 7px 0 6px; color: var(--fg3);
  font-size: 10px; font-weight: 500; letter-spacing: 0.2px;
}
nav.tabs a .g { display: block; font-size: 20px; line-height: 1.25; }
nav.tabs a.on { color: var(--accent); }

/* ------------------------------------------------------------------ misc */
.controls { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.controls button, .controls select {
  background: var(--card); border: 1px solid var(--line); color: var(--fg);
  padding: 6px 11px; border-radius: 999px; font-size: 13px;
}
.controls button.on { background: var(--accent); color: #fff; border-color: var(--accent); }
.controls select { border-radius: 10px; flex-basis: 100%; }
.muted { color: var(--fg2); }
.tiny { font-size: 11.5px; }
.center { text-align: center; }
.spinner { padding: 40px 0; text-align: center; color: var(--fg3); }
.err { color: var(--bad); }
.chart { width: 100%; }
.delta { font-size: 12.5px; font-weight: 600; }

/* ------------------------------------------------------------------ login */
.login { max-width: 320px; margin: 22vh auto; text-align: center; padding: 0 16px; }
.login h1 { font-size: 22px; margin: 0 0 4px; }
.login input {
  width: 100%; padding: 12px 14px; font-size: 16px; margin: 16px 0 10px;
  border-radius: 12px; border: 1px solid var(--line); background: var(--card); color: var(--fg);
}
.login button {
  width: 100%; padding: 12px; border-radius: 12px; background: var(--accent);
  color: #fff; font-weight: 600; font-size: 16px;
}

/* uPlot theming */
.u-legend { font-size: 11.5px; color: var(--fg2); }
.u-legend .u-marker { width: 9px; height: 9px; }
.u-title { font-size: 12px; color: var(--fg2); }

/* --------------------------------------------------------- trends chips */
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip-btn {
  background: var(--card); border: 1px solid var(--line); color: var(--fg);
  padding: 7px 12px; border-radius: 999px; font-size: 13.5px; font-weight: 500;
}
.chip-btn.on { background: var(--accent); color: #fff; border-color: var(--accent); }

details.allmetrics { margin-top: 10px; }
details.allmetrics > summary {
  list-style: none; cursor: pointer; font-size: 12.5px; color: var(--accent); padding-left: 2px;
}
details.allmetrics > summary::-webkit-details-marker { display: none; }
details.allmetrics > summary::after { content: " ›"; }
details.allmetrics[open] > summary::after { content: " ⌄"; }
#msearch {
  width: 100%; margin: 8px 0; padding: 9px 12px; font-size: 16px;
  border-radius: 10px; border: 1px solid var(--line); background: var(--card); color: var(--fg);
}
.mlist { max-height: 320px; overflow-y: auto; border-radius: var(--radius); background: var(--card); }
.mlist button {
  display: flex; gap: 8px; align-items: baseline; width: 100%; text-align: left;
  padding: 9px 14px; border-bottom: 1px solid var(--line); font-size: 13.5px;
}
.mlist button:last-child { border-bottom: 0; }
.mlist button.on { color: var(--accent); }
.mlist button .mono { flex: 1; }

/* ------------------------------------------------------------- load page */
.focus + .focus { margin-top: 12px; }
.focus-h { display: flex; align-items: baseline; gap: 8px; font-size: 13.5px; }
.focus-h span:first-child { font-weight: 600; }
.focus-h b { margin-left: auto; font-variant-numeric: tabular-nums; }
.focus-bar { height: 9px; border-radius: 999px; background: var(--line); overflow: hidden; margin: 5px 0 2px; }
.focus-bar div { height: 100%; border-radius: 999px; }

h2 .more-link { float: right; text-transform: none; letter-spacing: 0; font-weight: 500; }
p.lead { margin: 10px 0 0; font-size: 14px; line-height: 1.45; color: var(--fg2); }
.linkish { color: var(--accent); font-size: 11.5px; margin-left: auto; }

/* ------------------------------------------------------------------ map */
.map-card { padding: 10px; }
.map { position: relative; overflow: hidden; border-radius: 10px; background: var(--card2); }
.map .tiles { position: absolute; inset: 0; }
.map .tiles img { position: absolute; width: 256px; height: 256px; }
.map svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.zlegend i { flex: none; }

/* ---------------------------------------------------------------- gauge */
.gauge { position: relative; }
.gauge-track { display: flex; height: 10px; border-radius: 999px; overflow: hidden; }
.gauge-track div { flex: 1; }
.gauge-dot {
  position: absolute; top: 50%; width: 15px; height: 15px; border-radius: 50%;
  background: var(--fg); border: 2px solid var(--card);
  transform: translate(-50%, -50%); box-shadow: 0 0 0 1px rgba(0,0,0,.25);
}
.gauge-scale { display: flex; justify-content: space-between; margin-top: 4px; }

/* ------------------------------------------------------------- conflicts
   A four-column table of this on a phone wraps the date onto two lines and
   clips the winner off the right edge. One block per conflict instead. */
.conflict {
  background: var(--card); padding: 10px 14px; border-bottom: 1px solid var(--line);
}
.conflict:first-child { border-radius: var(--radius) var(--radius) 0 0; }
.conflict:last-child { border-bottom: 0; border-radius: 0 0 var(--radius) var(--radius); }
.conflict-h { display: flex; align-items: baseline; gap: 8px; font-size: 14px; }
.conflict-h .muted { margin-left: auto; }
.conflict-v { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.conflict-v span {
  font-size: 11.5px; color: var(--fg2); background: var(--card2);
  border-radius: 7px; padding: 3px 8px; font-variant-numeric: tabular-nums;
}
.conflict-v span b { color: var(--fg); font-weight: 600; margin-left: 3px; }
.conflict-v span.won { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
.conflict-v span.won b { color: var(--accent); }

/* --------------------------------------------------------- wider screens
   The tab bar stretched the full 1280 px while the content sat in a 780 px
   column, leaving the tabs stranded at the edges of the window. */
@media (min-width: 840px) {
  nav.tabs {
    left: 50%; right: auto; transform: translateX(-50%);
    width: 560px; border-radius: 16px 16px 0 0; border: 1px solid var(--line);
    border-bottom: 0;
  }
  .grid { grid-template-columns: repeat(3, 1fr); }
  .grid.g3 { grid-template-columns: repeat(4, 1fr); }
}

/* ============================================================ density pass
   First screen was showing three things: a title, a paragraph, and one card.
   Everything below tightens the rhythm so four or five land above the fold,
   without shrinking the numbers themselves — those are the point. */

header.top { padding: 16px 16px 4px; }
header.top h1 { font-size: 27px; }
header.top .sub { font-size: 13px; }

section { margin-top: 18px; }
h2 {
  font-size: 12px; font-weight: 600; letter-spacing: 0.2px;
  text-transform: none; margin-bottom: 6px; opacity: 0.85;
}

.card { padding: 13px 15px; margin-bottom: 8px; }
.grid { gap: 8px; }

/* The note used to be clamped to four lines because it appeared unasked and
   could not be allowed to own the first screen. Now it only exists because he
   pressed a button, so it shows in full — clamping something he explicitly
   asked for would be the wrong instinct entirely. */
.coach { padding: 12px 15px 13px; }
.coach .who { font-size: 10px; letter-spacing: 1.2px; opacity: 0.9; }
.coach p { font-size: 14px; line-height: 1.5; margin-top: 4px; }
.coach p + p { margin-top: 9px; }
.coach .who + p { margin-top: 5px; }

/* Disclosure rows were costing 40px on every card. */
details.more { margin-top: 8px; padding-top: 7px; }
details.more > summary { font-size: 11.5px; opacity: 0.9; }

.stat .label { font-size: 11.5px; }
.stat .note { font-size: 11.5px; line-height: 1.35; }
.zlegend { gap: 8px; font-size: 11px; }
.zbar { height: 22px; margin: 6px 0 5px; }
.row { padding: 10px 15px; }

/* -------------------------------------------------------------- info sheet */
button.info {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 50%; margin-left: 5px;
  border: 1px solid var(--fg3); color: var(--fg3);
  font: 600 10px/1 ui-serif, Georgia, serif; vertical-align: 1px;
}
button.info:hover { border-color: var(--accent); color: var(--accent); }
.stat .label button.info { vertical-align: 0; }

.sheet { position: fixed; inset: 0; z-index: 100; display: flex; align-items: flex-end; }
.sheet-bg { position: absolute; inset: 0; background: rgba(0,0,0,.55); }
@media (prefers-color-scheme: dark) { .sheet-bg { background: rgba(0,0,0,.7); } }
.sheet-card {
  position: relative; width: 100%; max-width: 640px; margin: 0 auto;
  max-height: 86vh; overflow-y: auto;
  background: var(--card); border-radius: 18px 18px 0 0;
  padding: 20px 20px calc(20px + var(--safe-b));
  animation: sheet-up .22s cubic-bezier(.2,.8,.3,1);
}
@keyframes sheet-up { from { transform: translateY(14px); opacity: .6 } to { transform: none; opacity: 1 } }
.sheet-card h3 { margin: 0 0 2px; font-size: 19px; letter-spacing: -0.3px; }
.sheet-card h4 {
  margin: 16px 0 3px; font-size: 11px; font-weight: 600; letter-spacing: 0.4px;
  text-transform: uppercase; color: var(--fg2);
}
.sheet-card p { margin: 0; font-size: 14px; line-height: 1.5; color: var(--fg); }
.sheet-close {
  margin-top: 20px; width: 100%; padding: 11px; border-radius: 12px;
  background: var(--card2); color: var(--accent); font-weight: 600; font-size: 15px;
}
@media (min-width: 840px) {
  .sheet { align-items: center; }
  .sheet-card { border-radius: 18px; }
}

.tier-toggle {
  display: block; width: 100%; text-align: center; padding: 10px;
  font-size: 12px; color: var(--accent); border-top: 1px solid var(--line);
}

/* Source dot in tables — same colour vocabulary as the chart legends, so the
   line you're looking at and the row you're reading are obviously the same
   device. */
.dot {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  margin-right: 6px; vertical-align: baseline;
}

/* --------------------------------------------------------------- HR ruler
   Every zone drawn to scale between 100 bpm and max, so a boundary stops being
   a number in a sentence and becomes a place on a line. The two threshold marks
   sit on separate rows: they are only 25 bpm apart and their labels collide on
   a phone otherwise. */
.hrruler { --h: 34px; }
.hrruler-marks { position: relative; height: 34px; }
.hrmark { position: absolute; top: 0; width: 0; }
.hrmark::after {
  content: ""; position: absolute; left: 0; width: 1px; background: var(--fg); opacity: .5;
  top: calc(var(--row) * 16px + 13px);
  height: calc(34px - (var(--row) * 16px + 13px) + var(--h));
}
.hrmark-l {
  position: absolute; top: calc(var(--row) * 16px); transform: translateX(-96%);
  white-space: nowrap; font-size: 10px; color: var(--fg2);
}
.hrmark-l b { color: var(--fg); }
.hrruler-bar {
  position: relative; height: var(--h); border-radius: 8px; overflow: hidden;
  background: var(--line);
}
.hrseg { position: absolute; top: 0; height: 100%; }
.hrseg-z {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 11px; font-weight: 650; color: #fff; text-shadow: 0 0 3px rgba(0,0,0,.4);
}
.hrruler-ticks { position: relative; height: 16px; margin-top: 5px; }
.hrruler-ticks span {
  position: absolute; transform: translateX(-50%);
  font-size: 10px; color: var(--fg2); font-variant-numeric: tabular-nums;
}
.hrruler-ticks span.start { transform: translateX(0); }
.hrruler-ticks span.end { transform: translateX(-100%); }
.hrlegend { display: flex; flex-wrap: wrap; gap: 5px 12px; margin-top: 10px; font-size: 12px; }
.hrlegend span { display: flex; align-items: center; gap: 5px; color: var(--fg2); }
.hrlegend i { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.hrlegend b { color: var(--fg); }
.hrlegend em { font-style: normal; opacity: .7; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------- log */
.feelrow { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
.feelrow button {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 9px 2px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--card2, transparent); color: var(--fg); font: inherit; cursor: pointer;
}
.feelrow button b { font-size: 15px; }
.feelrow button span { font-size: 10px; color: var(--fg2); text-align: center; line-height: 1.15; }
.feelrow button.on { background: var(--accent); border-color: var(--accent); }
.feelrow button.on b, .feelrow button.on span { color: #fff; }
.sheet-card input[type="date"], .sheet-card textarea {
  width: 100%; margin: 4px 0 12px; padding: 9px 10px; font: inherit;
  color: var(--fg); background: var(--card2, transparent);
  border: 1px solid var(--line); border-radius: 10px; box-sizing: border-box;
}
.sheet-card textarea { resize: vertical; }

/* ------------------------------------------------------- spectrum key
   Drawn from the same function that colours the numbers, so the key can never
   drift away from the data. */
.speckey { margin-top: 10px; }
.speckey-bar { display: flex; height: 6px; border-radius: 3px; overflow: hidden; }
.speckey-bar i { flex: 1; }
.speckey-l {
  display: flex; justify-content: space-between;
  font-size: 10px; color: var(--fg2); margin-top: 3px;
}

/* ------------------------------------------------------------------ plan */
.pgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.pday {
  background: var(--card); border-radius: 14px; padding: 9px 10px 8px;
  border: 1px solid transparent; min-height: 76px;
}
.pday.today { border-color: var(--accent); }
.pday.empty { opacity: .55; }
.pday-h { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 5px; }
.psession {
  display: flex; align-items: center; gap: 7px; width: 100%; margin-bottom: 4px;
  padding: 5px 6px; border: 0; border-radius: 9px; background: var(--card2, rgba(127,127,127,.09));
  color: var(--fg); font: inherit; text-align: left; cursor: pointer;
}
.psession.won  { background: rgba(48,209,88,.14); }
.psession.lost { background: rgba(255,159,10,.14); }
.ps-i { font-size: 15px; flex: none; }
.ps-m { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ps-m b { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-e { flex: none; text-align: right; font-size: 12px; color: var(--fg2); }
.ps-e span { display: block; }
.padd {
  width: 100%; padding: 3px; border: 1px dashed var(--line); border-radius: 8px;
  background: none; color: var(--fg3, var(--fg2)); cursor: pointer; font: inherit; font-size: 13px;
}
.tplrow { display: grid; grid-template-columns: 1fr 1fr 62px 56px 26px; gap: 5px; margin-bottom: 6px; }
.tplrow select, .tplrow input {
  padding: 6px; font: inherit; font-size: 13px; color: var(--fg);
  background: var(--card2, transparent); border: 1px solid var(--line); border-radius: 8px;
  min-width: 0; box-sizing: border-box;
}
.sheet-card.wide { max-width: 34rem; }
.sheet-card input[type="text"], .sheet-card input[type="number"] {
  width: 100%; margin: 4px 0 12px; padding: 9px 10px; font: inherit; color: var(--fg);
  background: var(--card2, transparent); border: 1px solid var(--line);
  border-radius: 10px; box-sizing: border-box;
}
.chk { display: flex; align-items: center; gap: 8px; margin: 4px 0; font-size: 14px; }
.chk input { width: auto; margin: 0; }
.psrow { display: flex; align-items: stretch; gap: 4px; margin-bottom: 4px; }
.psrow .psession { margin-bottom: 0; flex: 1; min-width: 0; }
.psskip {
  flex: none; width: 26px; border: 1px solid var(--line); border-radius: 9px;
  background: none; color: var(--fg3, var(--fg2)); cursor: pointer; font-size: 12px;
}
.psskip.on { background: rgba(255,159,10,.18); color: var(--fg); }
.psession.skip { background: rgba(127,127,127,.10); opacity: .6; }
.psession.skip .ps-m b { text-decoration: line-through; }


/* ------------------------------------------------------------- ask the coach
   The buttons are deliberately plain and equal-weight. Nothing here should read
   as the app's recommendation of which question to ask — that is his call, and
   a highlighted "Today" button would quietly become the automatic note again in
   a different costume. */
.coach-ask { margin-top: 18px; }
.coach-ask h2 { margin-bottom: 8px; }
.ask-row { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 8px; }
button.ask {
  appearance: none; border: 1px solid var(--line); background: var(--card);
  color: var(--fg); border-radius: 999px; padding: 7px 14px;
  font: inherit; font-size: 13px; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
button.ask:active { background: var(--line); }
button.ask.ghost { color: var(--muted); border-style: dashed; }
.ask-note { margin: 0 0 9px; }

.coach.thinking p { opacity: 0.6; }
.coach.thinking { animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1 } 50% { opacity: 0.62 } }

.coach-foot {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 10px; margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--line);
}
.coach-acts { display: flex; gap: 12px; flex-shrink: 0; }
button.link {
  appearance: none; background: none; border: 0; padding: 0;
  font: inherit; font-size: 11.5px; color: var(--accent); cursor: pointer;
}

/* ---------------------------------------------------------------- export */
.sheet-card.wide { max-width: 680px; }
#ex-text {
  width: 100%; box-sizing: border-box; margin: 8px 0 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px;
  line-height: 1.4; background: var(--bg); color: var(--fg);
  border: 1px solid var(--line); border-radius: 8px; padding: 9px; resize: vertical;
}
.row-btns { display: flex; gap: 8px; flex-wrap: wrap; }
.row-btns button {
  appearance: none; border: 1px solid var(--line); background: var(--card);
  color: var(--fg); border-radius: 9px; padding: 9px 16px; font: inherit;
  font-size: 14px; cursor: pointer;
}
.row-btns button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }

/* --------------------------------------------------------------- purpose */
.purpose { padding: 10px 0; border-top: 1px solid var(--line); }
.purpose .p-h { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
.purpose .q { margin: 3px 0 5px; font-size: 13.5px; }
.purpose p { margin: 3px 0; }

/* ------------------------------------------------------ hand-entered fields
   The three things about a swim that no sensor can produce. Kept visually plain:
   a form that looks like admin is a form that stops getting filled in. */
label.fld { display: block; margin: 11px 0; }
label.fld > span {
  display: block; font-size: 12px; color: var(--muted); margin-bottom: 4px;
}
label.fld > input {
  width: 100%; box-sizing: border-box; padding: 10px 11px; font: inherit;
  font-size: 16px;                       /* under 16px iOS zooms the whole page */
  background: var(--bg); color: var(--fg);
  border: 1px solid var(--line); border-radius: 9px;
}
label.fld > input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

/* ------------------------------------------------------------------- map
   Tiles under a heat canvas. The canvas is pointer-transparent so drags land
   on the container and pan both layers together. */
.map.heat {
  position: relative; overflow: hidden; height: 340px;
  border-radius: 12px; background: var(--line);
  touch-action: none;                    /* we handle pan and pinch ourselves */
  cursor: grab; user-select: none;
}
.map.heat.dragging { cursor: grabbing; }
.map.heat .tiles { position: absolute; inset: 0; }
.map.heat .tiles img {
  position: absolute; pointer-events: none;
  /* OSM's own tiles are busy under a heat layer; knocking back the saturation
     and lifting the contrast lets the heat sit on top instead of fighting it. */
  filter: saturate(0.35) contrast(0.92) brightness(1.04);
}
.heat-canvas { position: absolute; inset: 0; pointer-events: none; }

.map-bar {
  display: flex; justify-content: space-between; align-items: center;
  gap: 10px; margin-top: 8px;
}
.map-btns { display: flex; gap: 4px; }
.map-btns button {
  min-width: 34px; padding: 5px 9px; font-size: 12.5px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--card);
  color: var(--accent); cursor: pointer; font: inherit; font-size: 12.5px;
}
.map-btns button:active { background: var(--line); }

@media (prefers-color-scheme: dark) {
  .map.heat .tiles img { filter: saturate(0.3) brightness(0.62) invert(0.9) hue-rotate(180deg); }
}

.footlinks { margin: 12px 0 0; text-align: center; }
.footlinks a { font-size: 12.5px; color: var(--muted); text-decoration: none; }

/* --------------------------------------------------------------- overview
   Two across on a phone. Each card is one metric: where it is, the shape it
   made getting there, and how far it moved. */
.ovgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.ovcard {
  display: block; background: var(--card); border-radius: 12px;
  padding: 12px 13px 10px; text-decoration: none; color: var(--fg);
  -webkit-tap-highlight-color: transparent;
}
.ovcard:active { background: var(--line); }
.ov-h {
  display: flex; justify-content: space-between; align-items: baseline; gap: 6px;
  font-size: 12px; color: var(--muted); margin-bottom: 3px;
}
.ov-stale { font-style: normal; font-size: 10.5px; color: var(--warn); flex-shrink: 0; }
.ov-v { display: block; font-size: 24px; font-weight: 600; letter-spacing: -0.5px; }
.ov-v em { font-style: normal; font-size: 12px; font-weight: 500; color: var(--muted); margin-left: 2px; }
.ovcard .spark { display: block; width: 100%; height: 26px; margin: 6px 0 4px; }
.ov-d {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 12px; color: var(--muted);
}
.ov-d.up { color: var(--good); } .ov-d.down { color: var(--bad); }
.ov-d i { font-style: normal; font-size: 10.5px; color: var(--muted); font-weight: 400; }
.ov-d.up i, .ov-d.down i { color: var(--muted); }
@media (min-width: 620px) { .ovgrid { grid-template-columns: repeat(3, 1fr); } }

/* ------------------------------------------------------- dragging a session */
body.dragging-session { user-select: none; }
body.dragging-session .pday { touch-action: none; }
.psrow[data-drag] { touch-action: pan-y; }
.psrow.lifted { opacity: 0.3; }
.psession.drag-ghost {
  position: fixed; z-index: 60; pointer-events: none;
  transform: translate(-50%, -50%) scale(1.04) rotate(-1.5deg);
  width: 46vw; max-width: 240px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.28);
  border-radius: 10px; opacity: 0.96;
}
.pday.drop-ok {
  outline: 2px solid var(--accent); outline-offset: -1px;
  background: color-mix(in srgb, var(--accent) 9%, var(--card));
}
.pday.drop-no { outline: 2px dashed var(--warn); outline-offset: -1px; }

/* ---------------------------------------------------------------- sync pill
   Small and grey on purpose: it is reassurance, not a status you should have to
   read. It only earns attention while it is actually doing something. */
.syncpill { font-size: 11.5px; color: var(--muted); margin-top: 2px; min-height: 14px; }
.syncpill.working { color: var(--accent); }
.syncpill.working::before {
  content: ""; display: inline-block; width: 6px; height: 6px; margin-right: 5px;
  border-radius: 50%; background: currentColor; animation: pulse 1.2s ease-in-out infinite;
}
.syncpill.quiet { color: var(--warn); }

/* Said once, above the grid, instead of a footnote under twelve cards. */
.seamnote {
  font-size: 12px; line-height: 1.45; color: var(--muted);
  margin: 0 0 10px; padding: 9px 11px;
  background: var(--card); border-radius: 10px;
  border-left: 3px solid var(--line2);
}

/* The manual device check sits with the footer links and reads like one. */
.footlinks { display: flex; gap: 14px; flex-wrap: wrap; align-items: baseline; }
.footlinks button.linkish {
  font-size: 12.5px; color: var(--muted); background: none; border: 0;
  padding: 0; cursor: pointer; font-family: inherit;
}
.footlinks button.linkish:disabled { opacity: 0.6; cursor: default; }

/* The store being behind is not the same fault as a device not syncing, and
   the sync pill can only see the second one. This says the first one plainly,
   at the top, in the colour the app already uses for "read this". */
.card.stale {
  background: color-mix(in srgb, var(--warn) 12%, var(--card));
  border: 1px solid color-mix(in srgb, var(--warn) 34%, transparent);
}
.card.stale .label { color: var(--warn); font-weight: 600; }
