/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   TODAY — the horizon's own rules. Contract: docs/ia/today.md.

   ⛔ IT EXTENDS style.css, IT DOES NOT REPLACE IT. Every class the Today hero uses already existed
   and is still declared there; what is here is what today.md CHANGES (the hero's ground and its
   distance type) and what it ADDS (the badge, the three new blocks). A second full declaration of
   `.today-banner` in a second file is how two stylesheets come to disagree about one element.

   ⚠ LOADED AFTER style.css AND ia/shell.css, which is what lets the overrides below win on equal
   specificity. The order is index.html's and it is load-bearing.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── The header hero ─────────────────────────────────────────────────────────────────────────────
   today.md: "Header, chrome gradient: date eyebrow, workout dot and type, distance in mono at 56px,
   the beats and pace line, then a badge if the day was trimmed or pinned."
   ⛔ IT IS THE HEADER'S OWN BLOCK NOW (#449 `5c`), NOT A CARD UNDER ONE. His Q1 answer gave every
   screen its own full-bleed header, and on Today the hero IS that header: the shell paints the
   gradient once, over one box, and the hero draws its type, its distance and its line inside it.
   ✎ THIS BLOCK USED TO DESCRIBE A VISIBLE SEAM — "the header finishes its run in 64px and the hero
   starts its own again" — and to say that making it one continuous field was ia/shell.css's to change
   and a visual decision belonging to a design sitting. Q1 WAS THAT SITTING, and the seam is gone
   because there is one element left. RETRACTED IN PLACE rather than left above its own correction.
   ✎ AND SO IS THE FULL-BLEED WORKAROUND: the `margin: -14px -14px 16px` and the square top corners
   under `@media (max-width: 668px)` existed to make a card inside a padded, centred column span the
   viewport, and they never did — the two negative margins cancelled when the margin box was centred,
   so it sat 14px in on both sides at 440 (`#450`, measured). Nothing has to win an override now.
   ⇒ THE `@media (max-width: 668px)` BLOCK IS DELETED, not neutralised. The base rule below stays,
   because off-DOM the head slot is absent — the test harness lifts #view-root alone — and the hero
   then renders inside the column exactly where it always did, needing its own ground and padding. */
.today-banner {
  background: linear-gradient(135deg, var(--navy) 0%, var(--navy-mid) 100%);
  padding: 14px 18px 18px;
}

/* ⛔ IN THE HEADER IT PAINTS NOTHING AND MEASURES NOTHING. The header is the box with the ground and
   the padding; a second background here would restart the gradient inside the first one, and a second
   padding would inset the hero from a block that is already inset. */
.ia-shead-body > .today-banner {
  background: none;
  padding: 0;
  margin: 0;
  border-radius: 0;
}
/* Race day and a quiet day keep their own ground: purple is the race colour and grey is the absence
   of a session, and both say more than the chrome gradient can. ⛔ ON THE HEADER, because that is the
   box being painted; `_closeHero` puts the class there. */
.ia-header.today-ground-race { background: #7c3aed; }
.ia-header.today-ground-rest { background: #4b5563; }

/* ⚠ THE OFF-DOM PATH KEEPS ITS OWN GROUND. With no head slot the hero renders inside the column and
   these two are what colour it there; in the header the classes above win because the header is the
   painted box. Both are declared because both paths are real. */
.today-banner-race { background: #7c3aed; }
.today-banner-rest { background: #4b5563; }

/* 56px, mono, per the spec. `--font-display` was the old face; the distance is the one number on
   this screen the athlete reads at arm's length, and the mono figures are what make it scan. */
.today-banner-dist {
  font-family: var(--font-mono);
  font-size: var(--fs-hero);
  line-height: .98;
  letter-spacing: -.03em;
  margin: 10px 0 2px;
}
/* ⛔ #449 phase 7 `7a` (G4): THE FIGURE AND ITS UNIT ARE TWO SIZES, WHICH IS THE PROTOTYPE'S OWN
   PROPORTION — 56px/800 for the number, 22px/600 for the unit. The app set both at 56/700, so "mi"
   carried the number's -1.68px tracking and its full size, which is the thing the row names.
   ⚠ THE TRACKING IS RESET ON THE UNIT AND NOT ONLY THE SIZE. Tight negative tracking is what makes a
   long run of monospace figures scan; on a two-letter word it just closes the letters up. */
.today-banner-dist .tb-num  { font-weight: 800; }
.today-banner-dist .tb-unit { font-size: 1.375rem; font-weight: 600; letter-spacing: 0; }

/* ✎ THIS LINE USED TO READ "The unit and the 'on feet' tail stay at reading size, or a 56px 'mi'
   swamps the number it labels", and the UNIT half is RETRACTED, 2026-09-01: reading size was the
   workaround for exactly the defect G4 names, and `.tb-unit` above is the answer to it.
   ⛔ THE "on feet" TAIL IS DELIBERATELY LEFT WHERE IT IS. G4 is about the hero's UNIT; "on feet" and
   "min descending" are clarifying phrases in the same slot, they draw only on an ultra time-based day
   and a downhill day, and neither state is on this seed — so moving them would be an unmeasured
   change to a path no capture in this pass has ever seen. It belongs to the `today` group's row 1. */
.today-banner-dist .tb-onfeet { font-size: 1rem; letter-spacing: 0; }
.today-banner-dist .tb-mono { font-family: var(--font-mono); }

/* The beats-and-pace line. The zone is a BAND, never a fabricated bpm: a target heart rate needs a
   threshold, and §10 forbids printing one the athlete's own data has not produced. */
.tb-beats {
  display: inline-block; margin-left: 8px; padding: 1px 7px;
  border-radius: 6px; background: rgba(255,255,255,.14);
  font-size: var(--fs-meta); font-weight: 700; letter-spacing: .04em;
}

/* ── The header badge ────────────────────────────────────────────────────────────────────────────
   Trimmed or pinned, never both (today.md's Acceptance), so this row holds exactly one child. */
.tb-badges { margin-top: 12px; }
.tb-badge {
  display: inline-block; padding: 3px 9px; border-radius: 999px;
  font-size: var(--fs-meta); font-weight: 700; letter-spacing: .02em;
  background: rgba(255,255,255,.16); color: #fff;
}
.tb-badge-pin { background: rgba(255,255,255,.22); }
.tb-badge-trim { background: rgba(249,115,22,.26); color: #fed7aa; }

/* ── 2 · Sync trouble ────────────────────────────────────────────────────────────────────────────
   Amber, not red: nothing is lost and nothing is required of the athlete, which is what the copy
   says. A red card would ask for an action the sentence explicitly says is not needed. */
.sync-trouble { border-left: 3px solid var(--accent-warm, #f97316); }
.sync-trouble-l { font-size: 0.84375rem; line-height: 1.5; color: var(--ink, #111827); }

/* ── 16 · Standing homework ──────────────────────────────────────────────────────────────────────
   It is a prescription that stands for the whole block rather than a thing to answer, so it reads
   as a quiet note and carries no control. */
.homework-card { border-left: 3px solid var(--navy-mid); }
.homework-l { font-size: 0.84375rem; line-height: 1.5; color: var(--ink, #111827); }

/* ── 17 · The suggestion pill ────────────────────────────────────────────────────────────────────
   Collapsed by default: the cards it holds each carry an Apply and a Dismiss, and today.md's whole
   intent is that Today asks at most one question a day. Opening it is the athlete's choice. */
.sug-pill-wrap { margin: 14px 0 4px; }
.sug-pill {
  width: 100%; min-height: 44px; padding: 11px 14px;
  border: 1px solid var(--line, #e5e7eb); border-radius: 999px;
  background: var(--card, #fff); color: var(--ink, #111827);
  font-size: 0.875rem; font-weight: 700; text-align: left; cursor: pointer;
}
.sug-pill::after { content: '›'; float: right; opacity: .5; font-weight: 400; }
.sug-pill[aria-expanded="true"]::after { content: '⌄'; }
.sug-pill:active { background: var(--surface, #f9fafb); }
.sug-pill-body { margin-top: 10px; }
.sug-pill-body[hidden] { display: none; }

/* ── 15 · The fitness door ───────────────────────────────────────────────────────────────────────
   The `.ia-door` component is the shell's and is used exactly as designed (ia/shell.css), and it
   now carries its own spacing on BOTH sides, so this surface has nothing to add.
   ⛔ THE 14px TOP MARGIN THAT STOOD HERE IS DELETED, NOT MOVED (#703). It was compensating for a
   door that spaced itself only above; with the door spacing itself below, this sheet loads after
   the shell's and would have won, giving this one door 14 above AND 14 below while every other door
   on the screen got 14. ⚠ A compensation outlives the thing it compensates for, silently. */

/* ⛔ THE SLOT IS SHARED AND THE TYPE FOLLOWS ITS CONTENTS, NOT ITS POSITION. today.md sizes the
   distance at 56px, and #319 ruled that the same slot must also carry "Nothing on the plan", "No
   distance set" and "Skipped" — three sentences, not measurements. At 56px monospace the first of
   them wrapped to two lines and filled the hero. Reading size, same weight, same colour. */
.today-banner-dist.tb-dist-phrase {
  font-family: var(--font-display);
  font-size: 1.875rem;
  line-height: 1.1;
  letter-spacing: -.01em;
}

/* ── #533 · The hero's one line ──────────────────────────────────────────────────────────────────
   The prototype closes its hero with ONE 14.5px line at 74% white — the beats and the pace — where
   this app carried a labelled pace line, the whole belt block and a demand row. The belt moved
   behind the session door (`ia/today.js`, `T.banner`); what is left here is the line's own type.
   ⚠ IT WRAPS RATHER THAN TRUNCATES. A run-walker on a quality day reads
   `1:30 run · 0:30 walk · Session avg today 8:56/mi`, which is longer than the artboard's example,
   and cutting a pace off mid-figure would be worse than a second line. */
.today-banner-pace { line-height: 1.45; }

/* ── #533 · The session door ─────────────────────────────────────────────────────────────────────
   The `.ia-door` component is the shell's and is used exactly as designed, and it carries the same
   14px every other door on this screen carries — on its own, now that a door spaces itself below.
   ⛔ THE 14px TOP MARGIN THAT STOOD HERE IS DELETED FOR THE SAME REASON AS THE FITNESS DOOR'S
   (#703): it would have doubled this one door's spacing and nothing would have failed loudly. */

/* ── #534 · The ask door ─────────────────────────────────────────────────────────────────────────
   A mark, the label and a chevron. The disc is the prototype's own: a 26px lilac circle with the
   twinkle inside it, which is what marks this row as the AI surface now that the `AI` pill is gone.
   ⚠ THE TITLE IS THE WHOLE BODY. This door has no sub-line — the label IS the sentence — so the
   body needs no second row and the flex baseline is the title's. */
.today-ask-mark {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%;
  background: var(--brand-50, #f3ecff); color: var(--brand);
  display: flex; align-items: center; justify-content: center;
}
.today-ask-mark .ask-spark { width: 14px; height: 14px; display: block; }
.today-ask-door .ia-door-title { font-weight: 600; }

/* ── #533 · The fitness door's reading ───────────────────────────────────────────────────────────
   An eyebrow over a mono figure with its phrase on the same baseline, which is the artboard's own
   arrangement: 24px/800 for the number, 12.5px/700 for the phrase, the two aligned on the baseline
   so the figure carries the row and the phrase reads as its caption.
   ⛔ THE PHRASE'S COLOUR IS A VERDICT AND IS DECLARED FOR ALL THREE. Green for ahead, the app's own
   caution for behind, and the muted grey where there is nothing to compare against — an ahead-only
   colour would print a green "behind your goal" the first time the athlete slipped. */
.today-fit-eyebrow { display: block; }
/* ⛔ #533 — THE FRESHNESS DOOR'S FORM FIGURE. The door itself is built in `ia/progress.js` (the
   state map is module-private there and a second copy is forbidden in that file's own words), but
   it RENDERS on Today, so its rule lives with Today's other figures. The mono face and weight are
   `.today-fit-num`'s, one screen region over, rather than a size chosen by eye: the two numerals sit
   on the same screen and reading as one family is the point. ⚠ The artboard's 44px conic ring is NOT
   built — its proportion producer is module-private to the same file — and this figure stands in its
   place, which is a real reading either way. */
.today-fresh { align-items: center; }
.today-fresh-form { font-family: var(--font-mono); font-size: 1.125rem; font-weight: 800; letter-spacing: -.02em; color: var(--muted); flex: none; margin-left: auto; padding-left: 10px; }
.today-fit-line { display: flex; align-items: baseline; gap: 9px; margin-top: 7px; flex-wrap: wrap; }
.today-fit-num { font-family: var(--font-mono); font-size: 1.5rem; font-weight: 800; letter-spacing: -.02em; }
.today-fit-delta { font-size: var(--fs-meta); font-weight: 700; }
.today-fit-delta--good { color: var(--success); }
.today-fit-delta--warn { color: var(--accent); }
.today-fit-delta--flat { color: var(--muted); }

/* ── #534 · The closing note ─────────────────────────────────────────────────────────────────────
   ⛔ IT IS A CARD WITH THE APP'S OWN RAIL, NOT A FLAT GREY BLOCK. `.card` supplies the ground,
   `.ia-rail` the bar, and this declares the bar's colour and the sentence.
   ⛔ THE COLOUR IS RULED, 2026-09-06: the deep purple `--navy-mid` that the standing homework card
   already wears, so the two notes that can share this screen are marked the same way. He was shown
   both sides on a summit athlete's run day, where both cards are on screen at once. It is stated on
   this card's own class rather than as a new rail KIND because only this card wants one; a kind
   lands with the second surface to ask for it.
   ✎ TWO CLAIMS THAT USED TO SIT HERE ARE WITHDRAWN, AND BOTH WERE STALE IN THE SAME DIRECTION.
   (1) It said the card wears `.ia-rail--summit` (`--vert`, the climbing family's green) "which is
   the colour the artboard rails this card in". The KIND came off when he ruled and the class is a
   plain `.ia-rail` now, so a reader following that sentence would have gone looking for a modifier
   the builder no longer writes.
   (2) It said "which of the two colours this card should wear is an OPEN question of #534's … the
   question is left open; nothing here decides it". That was true when it was written and stopped
   being true the same day; left standing, it sat two lines above the declaration that decides it and
   contradicted it (§13q: a fact you withdraw takes every sentence resting on it with it).
   ⚠ A comment is a durable home, which is what makes leaving a superseded one expensive.
   ✎ IT OVERRIDES style.css's `.today-notes`, which set a `--surface` ground and a 10px radius for
   the flat block this replaces. Same single-class specificity, and this file loads after it — which
   is the arrangement this stylesheet's header describes and is why the rule is stated here rather
   than edited there. */
.today-notes {
  background: var(--card);
  border-left-color: var(--navy-mid);
  border-radius: var(--r);
  padding: 14px 16px;
  margin: 14px 0 0;
  font-size: 0.84375rem;
  line-height: 1.55;
  color: var(--text);
}

/* ── #617 · The bodyweight swap ──────────────────────────────────────────────────────────────────
   A tinted full-width card BELOW the list, which is where the artboard draws it. Its ground is the
   brand tint the app already uses behind a purple-inked block and its ink is `--brand-dk`, so the
   card reads as an aside about a move rather than as another thing to do.
   ⚠ THE OPEN MOVE IS MARKED. The card is under the whole list, so with five cards on screen nothing
   would say WHICH move it is about beyond its own first clause; the tinted edge on the open card is
   what ties the two together while you scroll between them. */
.str-swap-card {
  margin-top: 10px; padding: 13px 15px; border-radius: var(--r);
  background: var(--brand-50, #f3ecff); color: var(--brand-dk);
  font-size: 0.8125rem; line-height: 1.55;
}
.str-swap-card[hidden] { display: none; }
.str-move--swap { cursor: pointer; }
.str-move--open { border-color: var(--brand-lt); }

/* ── #547 · The load card's limit sentence ───────────────────────────────────────────────────────
   The prototype prints the caveat as body copy directly under the headline and the "easiest fix"
   line under that, so the limit reads at the same weight as the sentence it qualifies rather than
   as fine print. `.load-body` above it and `.load-sub` below it are style.css's; this is the one
   line #547 adds.
   ⚠ IT IS NOT MUTED. A limit set in the caption grey reads as a disclaimer nobody has to take in,
   which is the opposite of why it is printed (§4r: the ratio genuinely cannot see eccentric load). */
.load-limit {
  font-size: 0.78125rem; color: var(--text); line-height: 1.55; margin-top: 7px;
}

/* ✎ #561's `.ses-rw-*` AND `.chg-row--cta` RULES LEFT THIS FILE 2026-09-06 and now sit in
   style.css beside every other `.ses-*` and `.chg-row` rule. They were written here only because
   style.css belonged to another lane that day, and the lane that wrote them said so at the time and
   asked for the move. ⚠ Nothing about them was ever Today's. */
