/* Eve Coach — desktop-first.
 *
 * §7.3's constraints, followed literally:
 *   * STYLE ONLY FROM THE EXISTING VOCABULARY. Every colour, radius and easing
 *     below is a var() from shared/public/tokens.css — ONE file, served at
 *     /shared by every app, dark palette derived 1:1 from the Eve Shell mock
 *     and a light one derived from that. Theming is free here because
 *     nothing in this file names a colour.
 *     NO NEW TOKENS ARE INVENTED — if something here needed a colour that does
 *     not exist, that would be a finding to report, not a licence to add a hex
 *     code. Nothing did.
 *   * The dashboard is NOT restyled. It is served as published, inside an
 *     iframe, and the coach frame goes around it.
 *
 * ⚠️ WHERE THIS DELIBERATELY DEPARTS FROM THE EVE SHELL (§7.3 item 1):
 * the Eve Shell is phone-shaped — a bottom dock, a monogram space-switcher,
 * module tabs. A check-in queue is a dense, scannable, desktop-first table and
 * that pattern does not transfer. So the dock becomes a top bar, and the phone
 * view DROPS the grid rather than shrinking it: a coach on a phone is triaging
 * and replying, not programming. That is a real requirement (ideas §3
 * "computer or mobile"), but it is not the same screen scaled down.
 *
 * The card grammar IS reused rather than reinvented: solid card = live,
 * dashed = degraded/read-only, absent = not available. A stale queue row, an
 * expired proposal and a client with no data are all that same grammar.
 */

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  background: var(--canvas);
  color: var(--ink);
  font: 15px/1.45 -apple-system, "SF Pro Text", "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
}
button { font: inherit; color: inherit; cursor: pointer; }
a { color: var(--acc); }

.dim { color: var(--dim); }
.faint { color: var(--faint); }
[hidden] { display: none !important; }

/* ── login ─────────────────────────────────────────────────────────────── */
.login {
  min-height: 100vh; display: grid; place-items: center; padding: 24px;
  background: var(--bg);
}
.login-card {
  width: min(360px, 100%); background: var(--card); border: 1px solid var(--card-line);
  border-radius: var(--r-card); padding: 28px; display: grid; gap: 14px;
}
.login-card h1 { margin: 0 0 4px; font-size: 20px; font-weight: 600; letter-spacing: -0.01em; }
.login-card label { display: grid; gap: 6px; font-size: 13px; color: var(--dim); }
.login-card input {
  background: var(--field); border: 1px solid var(--chip-line); color: var(--ink);
  border-radius: var(--r-val); padding: 11px 12px; font: inherit; min-height: var(--tap-min);
}
.login-card input:focus { outline: none; border-color: var(--acc-border); }
.mark {
  width: 38px; height: 38px; border-radius: var(--r-chip);
  background: var(--acc-tint); border: 1px solid var(--acc-border);
  color: var(--acc); display: grid; place-items: center;
  font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
}
.err { color: var(--bad); font-size: 13px; margin: 0; }

.btn-primary {
  background: var(--acc-tint); border: 1px solid var(--acc-border-strong); color: var(--acc);
  border-radius: var(--r-btn); padding: 12px 16px; font-weight: 600;
  min-height: var(--tap-min); transition: background .16s var(--ease);
}
.btn-primary:hover { background: var(--acc-tint-2); }
.btn-quiet {
  background: var(--field); border: 1px solid var(--chip-line); color: var(--ink-3);
  border-radius: var(--r-chip); padding: 8px 12px; font-size: 13px;
}
.btn-quiet:hover { border-color: var(--chip-line-2); color: var(--ink); }

/* ── shell ─────────────────────────────────────────────────────────────── */
.top {
  display: flex; align-items: center; gap: 20px;
  padding: 12px 20px; padding-top: calc(12px + env(safe-area-inset-top));
  background: var(--dock-bg); border-bottom: 1px solid var(--card-line);
  position: sticky; top: 0; z-index: 20; backdrop-filter: blur(12px);
}
.tabs { display: flex; gap: 4px; flex: 1; }
.tab {
  background: none; border: 1px solid transparent; color: var(--dock-dim);
  padding: 8px 14px; border-radius: var(--r-pill); font-size: 14px;
}
.tab.is-on { color: var(--acc); background: var(--acc-tint); border-color: var(--acc-border); }
.who { display: flex; align-items: center; gap: 12px; font-size: 13px; }

/* Day/night — deliberately the same shape as the client app's Appearance
   control in Settings (app.css .seg), so one product has one way of doing
   this. A track with the choices in it reads as a switch at a glance; the
   single cycling pill it replaced read as a status label and was invisible to
   the person who asked for it. */
.theme-seg { display: flex; background: var(--field); border-radius: var(--r-pill); padding: 3px; }
.theme-seg button {
  background: none; border: none; color: var(--dim);
  padding: 5px 12px; border-radius: var(--r-pill); font-size: 12.5px;
}
.theme-seg button:hover { color: var(--ink); }
/* --bg as the text colour on an accent fill: near-black on periwinkle in dark,
   near-white on indigo in light. The one token that is correct both ways. */
.theme-seg button.active { font-weight: 700; color: var(--bg); background: var(--acc); }

/* ⚠️ NARROWER, NOT FEWER. The obvious saving below the drawer breakpoint is to
   hide the two inactive options and show only the current one — which lands
   straight back on the bug this control was rewritten to fix: a lone pill
   reading "Auto" that nobody recognises, and which cannot even be clicked to
   change since the only visible option is the one already chosen. All three
   stay; they just get smaller. */
@media (max-width: 1000px) {
  .theme-seg button { padding: 5px 8px; font-size: 11.5px; }
  .who { gap: 8px; }
}

main { padding: 20px; max-width: 1280px; margin: 0 auto; }

/* ── cards ─────────────────────────────────────────────────────────────── */
.card {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: var(--r-card); padding: 18px; margin-bottom: 12px;
}
/* Dashed = degraded or read-only, straight from the Eve Shell's card grammar. */
.card.is-quiet { border-style: dashed; background: transparent; }
.section-head {
  display: flex; align-items: baseline; justify-content: space-between;
  margin: 0 0 12px; gap: 12px;
}
.section-head h2 { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }

/* ── the queue: a dense table, not a card list ─────────────────────────── */
.queue { width: 100%; border-collapse: collapse; }
.queue th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--faint); font-weight: 600; padding: 0 12px 8px; white-space: nowrap;
}
.queue td { padding: 12px; border-top: 1px solid var(--card-line); vertical-align: top; }
.queue tr.row { cursor: pointer; }
.queue tr.row:hover td { background: var(--field); }
.queue .name { font-weight: 600; }
.queue .when { white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Flag chips reuse the source-chip grammar: a hairline pill that names where a
   number came from. Here it names WHY a row surfaced — §7.3 item 2, the queue
   must show that in the row, without a click. */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--chip-line); background: var(--field);
  border-radius: var(--r-pill); padding: 3px 9px; font-size: 12px; color: var(--dim);
  white-space: nowrap;
}
.chip.warn { border-color: var(--warn-border); color: var(--warn); }
.chip.bad  { border-color: var(--bad-border);  color: var(--bad); }
.chip.good { border-color: var(--good-border); color: var(--good); }
.chip.acc  { border-color: var(--acc-border);  color: var(--acc); }

.empty { color: var(--dim); padding: 28px 12px; text-align: center; }

/* ── client pane ───────────────────────────────────────────────────────── */
.pane {
  position: fixed; inset: 0; background: var(--bg); z-index: 40;
  display: flex; flex-direction: column;
}
.pane-head {
  display: flex; align-items: center; gap: 16px;
  padding: 12px 20px; padding-top: calc(12px + env(safe-area-inset-top));
  border-bottom: 1px solid var(--card-line); background: var(--dock-bg);
}
.pane-title { flex: 1; display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.pane-title strong { font-size: 16px; }
.pane-tabs { display: flex; gap: 4px; padding: 10px 20px; border-bottom: 1px solid var(--card-line); }
.ptab {
  background: none; border: 1px solid transparent; color: var(--dock-dim);
  padding: 6px 12px; border-radius: var(--r-pill); font-size: 13px;
}
.ptab.is-on { color: var(--acc); background: var(--acc-tint); border-color: var(--acc-border); }
/* ── the split: data left, conversation right ──────────────────────────────
   ⚠️ THE CHAT IS A COLUMN, NOT A TAB. A coach looking at a client's dashboard
   and wanting to say something about it should not have to leave the number to
   write about it, and recording a voice note ABOUT what is on screen is
   impossible if opening the recorder hides the screen. That was the whole
   reason to split.

   Chat on the RIGHT: the data is what is being read and the conversation is
   what is being written into, and a composer on the trailing edge is the
   convention every messaging tool has settled on. Flipping it is one
   `flex-direction: row-reverse` here if that turns out to be wrong. */
.pane-split { flex: 1; display: flex; min-height: 0; }
.pane-main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.pane-chat {
  /* Wider than the first cut: the composer is the thing a coach spends most of
     their time in, and a 340px column made it a slot rather than a field.
     Still a clamp — a fixed width would either starve the dashboard on a
     laptop or waste half an ultrawide. */
  width: clamp(400px, 34%, 580px);
  border-left: 1px solid var(--card-line);
  background: var(--bg);
  display: flex; flex-direction: column; min-height: 0;
}
.chat-head {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px; border-bottom: 1px solid var(--card-line);
  font-size: 13px; color: var(--ink-3);
}
.chat-head .spacer { flex: 1; }
/* The close button belongs to the drawer; in two-column mode there is nothing
   to close. */
#chat-close, #chat-toggle { display: none; }
.pane-chat > #chat {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 14px 16px; display: flex; flex-direction: column;
}
/* The thread grows; the composer stays put at the bottom of the column. */
.pane-chat .thread { flex: 1; min-height: 0; overflow-y: auto; max-height: none; }
.pane-chat .composer, .pane-chat .rec-bar, .pane-chat .rec-row { flex: 0 0 auto; }
.pane-chat .msg { max-width: 92%; }

.pane-body { flex: 1; overflow: auto; }
.panel { display: none; height: 100%; }
.panel.is-on { display: block; }
/* The dashboard panel stacks a staleness banner above a full-bleed iframe.
   Both at height:100% would make the iframe overflow by the banner's height,
   so the panel is a column and the frame takes what is left. */
.panel[data-panel="dashboard"].is-on { display: flex; flex-direction: column; }
.panel[data-panel="dashboard"] > .banner { flex: 0 0 auto; }
.panel[data-panel="dashboard"] > #dash-frame { flex: 1 1 auto; min-height: 0; }
.panel > div { padding: 20px; max-width: 1100px; margin: 0 auto; }

#dash-frame { width: 100%; height: 100%; border: 0; display: block; background: var(--bg); }

/* The staleness banner. §7.2: a coach must be able to tell "didn't log" from
   "hasn't synced yet" — the first is coachable, the second is noise. */
.banner {
  margin: 0; padding: 10px 20px; font-size: 13px; color: var(--dim);
  background: var(--field); border-bottom: 1px solid var(--card-line);
}

/* ── chat ──────────────────────────────────────────────────────────────── */
.thread { display: grid; gap: 10px; margin-bottom: 16px; }
.msg { max-width: 76%; padding: 10px 14px; border-radius: var(--r-sub); background: var(--card); border: 1px solid var(--card-line); }
.msg.mine { margin-left: auto; background: var(--acc-tint); border-color: var(--acc-border); }
.msg.system { margin: 0 auto; background: none; border-style: dashed; color: var(--dim); font-size: 13px; }
.msg .meta { font-size: 11px; color: var(--faint); margin-top: 5px; }
.msg audio, .msg video { max-width: 100%; margin-top: 6px; border-radius: var(--r-val); }


/* Photos in the thread. Capped so a portrait phone shot does not become a
   scroll of its own, and tappable through to the full image. */
.msg img { max-width: 100%; max-height: 320px; border-radius: var(--r-val); margin-top: 6px; display: block; }

.composer { display: flex; gap: 8px; align-items: flex-end; }
.composer textarea {
  /* ⚠️ min-width: 0 matters. A flex item will not shrink below its content's
     intrinsic width by default, so a textarea beside several buttons ends up a
     slot rather than a field — which is exactly what the media buttons did to
     it while they lived in this row. */
  flex: 1 1 auto; min-width: 0;
  background: var(--field); border: 1px solid var(--chip-line); color: var(--ink);
  border-radius: var(--r-val); padding: 11px 12px; font: inherit; resize: vertical; min-height: 46px;
}
.composer .btn-primary { flex: 0 0 auto; }
.composer textarea:focus { outline: none; border-color: var(--acc-border); }

/* Accept-cards inline in the stream. Five states is a lot (§7.3 item 3), so
   they are distinguished by border colour and one word rather than by five
   different components. */
.propcard { border: 1px solid var(--acc-border); border-radius: var(--r-sub); padding: 12px 14px; background: var(--acc-tint); }
.propcard.state-accepted   { border-color: var(--good-border); background: var(--good-tint); }
.propcard.state-declined   { border-color: var(--bad-border);  background: transparent; }
.propcard.state-superseded,
.propcard.state-expired    { border-style: dashed; background: transparent; color: var(--dim); }
.propcard h4 { margin: 0 0 6px; font-size: 13px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--dim); }
.kv { display: grid; grid-template-columns: auto auto; gap: 2px 14px; font-variant-numeric: tabular-nums; font-size: 14px; }
.kv .was { color: var(--faint); text-decoration: line-through; }


/* ── recording (C9: text, voice, video) ────────────────────────────────── */
.rec-bar[hidden] { display: none; }   /* an element with display:flex ignores the
                                          hidden attribute, which only sets
                                          display:none at the weakest possible
                                          specificity — so say it explicitly */
.rec-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  border: 1px solid var(--bad-border); border-radius: var(--r-sub);
  padding: 10px 12px; margin-bottom: 10px; background: var(--field);
}
.rec-bar .spacer { flex: 1; }
.rec-dot {
  width: 10px; height: 10px; border-radius: var(--r-pill);
  background: var(--bad); animation: rec-pulse 1.2s var(--ease) infinite;
}
@keyframes rec-pulse { 0%,100% { opacity: 1 } 50% { opacity: 0.25 } }
@media (prefers-reduced-motion: reduce) { .rec-dot { animation: none } }
.rec-time { font-variant-numeric: tabular-nums; color: var(--ink-2); }
.rec-preview {
  width: 160px; border-radius: var(--r-val); background: #000;
  transform: scaleX(-1);   /* a selfie preview that is not mirrored feels wrong */
}
.rec-row { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.rec-btn { white-space: nowrap; }

/* ── forms, grids ──────────────────────────────────────────────────────── */
.form { display: grid; gap: 12px; max-width: 460px; }
.form label { display: grid; gap: 5px; font-size: 13px; color: var(--dim); }
.form input, .form select, .form textarea {
  background: var(--field); border: 1px solid var(--chip-line); color: var(--ink);
  border-radius: var(--r-val); padding: 10px 12px; font: inherit;
}
.form input:focus, .form select:focus, .form textarea:focus { outline: none; border-color: var(--acc-border); }
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* The prescription grid (§7.3 item 4): "It is a grid, not a form." Slot rows
   across a day, rep range + RPE per slot. Modelled on the program sheet in
   docs/reference/excersise.jpg, which is the closest prior art in the repo. */
.slots { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.slots th { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--faint); text-align: left; padding: 0 8px 6px; font-weight: 600; }
.slots td { padding: 5px 8px; border-top: 1px solid var(--sub-line); }
.slots input, .slots select {
  width: 100%; background: var(--val); border: 1px solid var(--chip-line);
  color: var(--ink); border-radius: var(--r-chip); padding: 7px 8px; font: inherit;
}
.slots .idx { color: var(--faint); width: 30px; }

/* The prescription grid, per exercise. Modelled on the program sheet in
   docs/reference/excersise.jpg: the exercise names the block, the sets are
   rows beneath it, and every number is tabular so columns line up when a coach
   scans down a day. */
.ex-block {
  border: 1px solid var(--sub-line); border-radius: var(--r-sub);
  padding: 12px 14px; margin-bottom: 10px;
}
.ex-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
/* Unsaved edits are VISIBLE, not something you discover at Send. Reuses the
   card grammar: a dashed edge means "not committed yet", the same thing it
   means on a degraded module card. */
.ex-block.is-dirty { border-style: dashed; border-color: var(--acc-border); }
.ex-block.is-dirty .save-slots { color: var(--acc); border-color: var(--acc-border); }
.ex-head .spacer { flex: 1; }
.slots .reps { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.slots .reps input { width: 62px; }
.slots .dash { color: var(--faint); }
.slots td input, .slots td select { max-width: 130px; }
/* The load column is deliberately last and quiet: C10 prescribes rep ranges
   and RPE, and a load is the exception rather than the habit. */
.slots td:nth-child(5) input { color: var(--dim); }

.assign-select {
  background: var(--field); border: 1px solid var(--chip-line); color: var(--ink);
  border-radius: var(--r-val); padding: 10px 12px; font: inherit; min-width: 220px;
}
.assign-select:focus { outline: none; border-color: var(--acc-border); }

/* ── sheets ────────────────────────────────────────────────────────────── */
.sheet-scrim {
  position: fixed; inset: 0; background: var(--scrim); z-index: 60;
  display: grid; place-items: center; padding: 24px;
  backdrop-filter: blur(3px);
}
.sheet {
  background: var(--sheet); border: 1px solid var(--card-line);
  border-radius: var(--r-sheet); padding: 22px;
  width: min(460px, 100%); max-height: 80vh; overflow: auto;
}
.sheet h3 { margin: 0 0 4px; font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }
.sheet .form { margin-top: 12px; max-width: none; }
.row-btns { display: flex; gap: 8px; align-items: center; margin-top: 4px; }

.pick-search {
  width: 100%; margin: 12px 0 8px;
  background: var(--field); border: 1px solid var(--chip-line); color: var(--ink);
  border-radius: var(--r-val); padding: 11px 12px; font: inherit;
}
.pick-search:focus { outline: none; border-color: var(--acc-border); }
.pick-list { max-height: 44vh; overflow: auto; margin-bottom: 12px; }
.pick-group-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--faint); margin: 12px 0 4px;
}
.pick-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; text-align: left; background: none; border: 0;
  border-bottom: 1px solid var(--sub-line); padding: 10px 4px;
  min-height: var(--tap-min);
}
.pick-row:hover { background: var(--field); }

/* ── no room for two columns ───────────────────────────────────────────────
   Below 1000px the conversation becomes a slide-over drawer rather than a
   squeezed column. It is still ALWAYS RENDERED — same DOM, same poller, same
   code path — only its presentation changes, so nothing about the chat has a
   second implementation for narrow screens. */
@media (max-width: 1000px) {
  .pane-chat {
    position: fixed; top: 0; right: 0; bottom: 0; width: min(480px, 100%);
    z-index: 50; transform: translateX(100%);
    transition: transform .22s var(--ease);
    box-shadow: -18px 0 40px var(--shadow-drawer);
    padding-top: env(safe-area-inset-top);
  }
  .pane-chat.is-open { transform: translateX(0); }
  #chat-close, #chat-toggle { display: inline-flex; }
  /* An unread mark on the toggle, so a message arriving behind the drawer is
     not silent. */
  #chat-toggle.has-news::after {
    content: ''; display: inline-block; width: 7px; height: 7px;
    border-radius: var(--r-pill); background: var(--good); margin-left: 6px;
  }
}

/* ── mobile: triage and reply, not programming (§7.3 item 1) ───────────── */
@media (max-width: 720px) {
  main { padding: 12px; }
  .top { gap: 10px; padding: 10px 12px; }
  .tabs { overflow-x: auto; }
  .who span { display: none; }

  /* The queue table becomes stacked rows — the same data, a different shape. */
  .queue thead { display: none; }
  .queue tr.row { display: block; border: 1px solid var(--card-line); border-radius: var(--r-sub); margin-bottom: 10px; padding: 4px; }
  .queue td { display: block; border: 0; padding: 5px 10px; }
  .queue td[data-col="when"] { color: var(--dim); font-size: 13px; }

  /* Programming is dropped on a phone rather than squeezed: a prescription
     grid at 375px is a worse tool than no tool (§7.3 item 1 — a coach on a
     phone is triaging and replying, not programming). The grid scrolls
     horizontally rather than reflowing, so the columns stay aligned and the
     screen stays honest about being the wrong one for the job. */
  .tab[data-view="templates"] { opacity: 0.45; }
  .ex-block { overflow-x: auto; }
  .slots { min-width: 520px; }
}

/* ══ the new coach surfaces ═══════════════════════════════════════════════
   Every colour below is a var() from shared/public/tokens.css, so all of this
   themes for free — the day/night switch was built two commits before these
   screens existed and nothing here had to know about it. */

/* ── queue: tasks sit in the same table as check-ins ───────────────────── */
.task-title { font-size: 13.5px; color: var(--ink-2); }
.btn-quiet.tiny { padding: 4px 9px; font-size: 12px; min-height: 0; }

/* ── the task list ────────────────────────────────────────────────────── */
.task-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 0; border-top: 1px solid var(--card-line);
}
.task-row:first-of-type { border-top: none; }
.task-row.is-done { opacity: 0.6; }
/* A 22px circle with a 44px hit area — the tap target rule survives the fact
   that the thing you can see is small. */
.task-check {
  position: relative; width: 22px; height: 22px; flex-shrink: 0;
  border-radius: 999px; border: 1.5px solid var(--chip-line-2); background: none;
}
.task-check::after {
  content: ''; position: absolute; inset: -11px;    /* → 44px */
}
.task-check:hover { border-color: var(--good); background: var(--good-tint); }

/* ── road map ─────────────────────────────────────────────────────────── */
/* A vertical spine with a dot per phase. The timeline is the point: a client
   should be able to see that the plan ENDS, which is the graduation idea made
   visual rather than written down in a paragraph nobody reads. */
.rmap { list-style: none; margin: 0; padding: 0 0 0 26px; position: relative; }
.rmap::before {
  content: ''; position: absolute; left: 7px; top: 10px; bottom: 10px;
  width: 2px; background: var(--card-line);
}
.rmap-phase { position: relative; margin-bottom: 12px; }
.rmap-dot {
  position: absolute; left: -26px; top: 20px; width: 16px; height: 16px;
  border-radius: 999px; background: var(--card);
  border: 2px solid var(--chip-line-2);
}
.rmap-phase.is-active  .rmap-dot { border-color: var(--acc); background: var(--acc); }
.rmap-phase.is-done    .rmap-dot { border-color: var(--good); background: var(--good); }
.rmap-phase.is-skipped .rmap-dot { border-color: var(--faint); }
.rmap-body {
  background: var(--card); border: 1px solid var(--card-line);
  border-radius: var(--r-card); padding: 14px 16px;
}
.rmap-phase.is-active .rmap-body { border-color: var(--acc-border); }
.rmap-phase.is-done .rmap-body, .rmap-phase.is-skipped .rmap-body { opacity: 0.72; }
.row-check { display: flex; align-items: center; gap: 10px; font-size: 13.5px; }
.row-check input { width: auto; }

/* ── recovery ─────────────────────────────────────────────────────────── */
.rc-chart {
  width: 100%; height: 92px; margin-top: 12px; overflow: visible;
  /* preserveAspectRatio="none" stretches the viewBox, which would also stretch
     stroke width — vector-effect keeps the line 1px whatever the box does. */
}
.rc-chart path, .rc-chart line, .rc-chart circle { vector-effect: non-scaling-stroke; }
.rc-band { fill: var(--acc-tint); stroke: none; }
.rc-line { fill: none; stroke: var(--acc); stroke-width: 1.6px; }
.rc-dot.bad  { fill: var(--bad); }
.rc-dot.warn { fill: var(--warn); }
.rc-dot.good { fill: var(--good); }
/* Markers are hairlines, deliberately quiet: they are context for the line,
   not a second series competing with it. */
.rc-mark { stroke: var(--chip-line-2); stroke-width: 1px; stroke-dasharray: 2 3; }
.rc-mark.programme { stroke: var(--acc-border); }
.rc-devs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }

/* ── the body heat map ────────────────────────────────────────────────── */
.bm-wrap { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
.bodymap { flex: 1 1 340px; max-width: 460px; height: auto; }
.bm-figure rect, .bm-figure ellipse { fill: var(--field); }
.bm-m { stroke: var(--card); stroke-width: 1.5; transition: fill .2s var(--ease); }
.bm-m:hover { stroke: var(--acc); stroke-width: 2; }
.bm-label { fill: var(--dim); font-size: 11px; font-weight: 600; }
.bm-list { flex: 1 1 220px; min-width: 200px; }
.bm-row {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 6px 0; border-bottom: 1px solid var(--card-line); font-size: 13.5px;
}
.bm-cold { margin-top: 12px; font-size: 12.5px; color: var(--dim); line-height: 1.6; }
.bm-unmapped {
  margin-top: 14px; padding: 10px 12px; border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--warn) 10%, transparent);
  border: 1px solid var(--warn-border);
}
.bm-unmapped .micro { color: var(--warn); font-weight: 700; }
.bm-basis { margin-top: 12px; line-height: 1.6; }
