/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   RACE — the countdown hub's own styles. Contract: docs/ia/race.md.

   ⛔ ITS OWN FILE FOR THE REASON `ia/today.css` IS ONE: these rules belong to one surface, and the
   shell's stylesheet is chrome every screen renders through. What IS in ia/shell.css and stays
   there is `.ia-door` itself and the centring rule for this surface's header, both written by `5c`
   before this screen existed.

   ⛔ EVERY SIZE IS RELATIVE AND EVERY COLOUR IS A TOKEN (#449 `5b`). Written that way once rather
   than in literals to be converted twice by `5k`.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── The countdown ───────────────────────────────────────────────────────────────────────────────
   race.md's Layout asks for 68px, which is 4.25rem against the 16px root the app already inherits
   from the browser. It is NOT `--fs-hero`: that token is 56px, Today's number, and lifting it to
   68 would move a hero on another screen nobody has asked to move. */
.race-count {
  font-family: var(--font-mono);
  font-size: 4.25rem; font-weight: 800; line-height: 1;
  margin-top: 1rem;
}

/* ── A door with a chevron and a value ───────────────────────────────────────────────────────────
   ⛔ MODIFIERS, NOT A REDEFINITION OF `.ia-door`. Profile's admin door is a plain `.ia-door` with a
   title and a sub, and making the base class a flex row would have laid those two out side by side.
   ⚠ THE WHOLE CARD IS THE TARGET and the chevron is decorative, which is why it is aria-hidden and
   carries no handler of its own. */
.ia-door--nav { display: flex; align-items: center; gap: .875rem; }
.ia-door-body { flex: 1 1 auto; min-width: 0; }
.ia-door-chev { flex: 0 0 auto; color: var(--text-muted); font-size: 1.125rem; line-height: 1; }
.ia-door-value { display: block; margin-top: .5rem; }
.ia-door-num { font-family: var(--font-mono); font-size: 1.5rem; font-weight: 800; }
.ia-door-unit { font-size: var(--fs-meta); color: var(--muted); }
.ia-door-tag {
  margin-left: .375rem;
  font-size: var(--fs-meta); font-weight: 700;
  color: var(--door-accent, var(--muted));
}
/* Inside seven days the race-week door leads, which is race.md's own state table. The accent bar is
   how every other leading card in this app announces itself. */
.ia-door--primary { border-left: 5px solid var(--brand); }
.ia-door--nav[style*="--door-accent"] .ia-door-tag { color: var(--door-accent); }

/* ── The races list: the inline delete confirm ───────────────────────────────────────────────────
   #590. The prototype asks `Delete this race?` INSIDE the card it is about, on a rose panel, with
   `Keep it` and `Delete`; the app asked it over a full-screen scrim.

   ⛔ IT LIVES HERE RATHER THAN BESIDE `.race-card` IN style.css, and that is the split this file was
   made for: `.race-card` is chrome shared with the result list, and this panel belongs to one
   surface. ⚠ `.race-act` and `.race-actions` are NOT redeclared here for the same reason — the
   disabled state below is a MODIFIER on what that file already draws.
   ⛔ THE DISABLED ROW IS WHAT REPLACES THE SCRIM, so it is drawn as well as enforced: a control that
   is unreachable and looks reachable is worse than the modal was. */
.race-confirm {
  /* --red-50 is the pale red chip fill this palette already declares as "the design's own", and it
     is #fef2f2, which is the exact ground the prototype paints this panel. */
  margin-top: .6875rem;
  background: var(--red-50);
  border-radius: var(--r-sm);
  padding: .75rem .8125rem;
}
.race-confirm-q {
  margin: 0;
  font-size: var(--fs-meta); font-weight: 600; line-height: 1.55; color: var(--text);
}
.race-confirm-row { display: flex; gap: .5rem; margin-top: .6875rem; flex-wrap: wrap; }
/* The quiet half is `.race-act` and is not redrawn. This is the filled destructive half, which the
   card has never had: `.race-act--danger` is red TEXT on the row's own grey, and the prototype's
   `Delete` inside the confirm is white on red — the one control on this screen that is the act
   itself rather than a way to reach it. */
/* Every figure here is `.race-act`'s own, in rem rather than the px that file writes them in
   (this file's rule: every size relative, every colour a token). The two buttons sit side by side,
   so a difference in any of them would read as a mistake. */
.race-confirm-go {
  font-family: inherit; font-size: 0.8125rem; font-weight: 700;
  border: 0; border-radius: .5625rem; padding: .5rem .875rem;
  min-height: 2.25rem; cursor: pointer;
  background: var(--red); color: #fff;
}
.race-confirm-go:active { background: var(--red-dk); }
.race-card--confirming .race-actions button:disabled,
.race-card--confirming .race-actions a:disabled { opacity: .45; pointer-events: none; }

/* ── The races list: the recovery card ───────────────────────────────────────────────────────────
   #590. The last card on the drawing's list, and the only place it says how LONG the recovery runs
   and which day of it you are on. `.card` + `.ia-rail--note` supply the ground and the grey bar the
   prototype draws; `.ia-card-eyebrow` supplies the `RECOVERY` label. Only the sentence is declared. */
.race-recovery-body {
  margin: .5rem 0 0;
  font-size: var(--fs-meta); line-height: 1.55; color: var(--text);
}

/* ── The long-run note ───────────────────────────────────────────────────────────────────────────
   A statement, not a door: nothing opens, so it is not a button. */
.race-note {
  margin: .875rem 0 0; padding: .875rem 1rem;
  background: var(--card); border-left: 4px solid var(--accent);
  border-radius: var(--r-sm); box-shadow: var(--shadow-sm);
  font-size: var(--fs-meta); line-height: 1.55; color: var(--text);
}

/* ── The arc from here ───────────────────────────────────────────────────────────────────────────
   One bar per week, bottom-aligned, heights already resolved to a percentage of the peak week by
   the composer so the CSS never has to know a mileage. */
.race-arc { margin-top: .875rem; }
.race-arc-t { font-family: var(--font-display); font-size: var(--fs-title); font-weight: 700; }
.race-arc-bars {
  display: flex; align-items: flex-end; gap: .25rem;
  height: 4.625rem; margin-top: .875rem;
}
.race-arc-bar { flex: 1 1 0; border-radius: .25rem; min-width: .25rem; }
.race-arc-legend {
  display: flex; justify-content: space-between; gap: .5rem;
  margin-top: .5625rem;
  font-size: var(--fs-caption); color: var(--text-muted);
}

/* The upgrade card standing in for the projection door (race.md's TIER_0 state).
   ⛔ THIS RULE IS DELETED AND THE SENTENCE ABOVE IT IS RETRACTED, NOT AMENDED (#703, 2026-09-08).
   It read "a card spaces itself BELOW and a door spaces itself ABOVE, so without this the gap under
   it is double" — which was an accurate description of a convention that has now gone. Doors space
   themselves below like cards, so zeroing this card's bottom margin would produce the OPPOSITE
   defect it was written to prevent: no gap at all under the teaser. ⚠ A compensation whose reason
   has been removed reads exactly like a rule with a reason. */

/* ── The calendar feed screen ────────────────────────────────────────────────────────────────────
   #594. The card's layout was five inline `style=` attributes written when it lived inside the
   settings form; it is a screen of its own now, so it gets rules of its own.
   ⛔ `.cal-switch` OVERRIDES `.cal-toggle` BY CASCADE ORDER, NOT BY SPECIFICITY. `style.css` loads
   first and `ia/race.css` after it, and both selectors are one class, so the later file wins. The
   element keeps BOTH classes deliberately: `.cal-toggle` is the handle three extraction-equivalence
   probes reach this control by. */
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: .75rem; margin-bottom: .625rem; }
.cal-title { margin: 0; }
.cal-desc { font-size: var(--fs-meta); color: var(--muted); margin: 0 0 .875rem; line-height: 1.5; }
/* The design's rail card under the toggle: the sentence that says why the feed is worth having. */
.cal-why { margin: 0; font-size: var(--fs-meta); line-height: 1.55; color: var(--text); }

/* A track and a knob, with no text in it. The state travels as `aria-checked` on `role="switch"`,
   which is what the word in the old pill was doing for a screen reader. */
.cal-switch {
  position: relative; flex: 0 0 auto;
  width: 3.125rem; height: 1.75rem; min-width: 0; min-height: 0;
  padding: 0; border-radius: 999px;
  background: var(--surface-2);
  transition: background .2s;
}
.cal-switch-knob {
  position: absolute; top: .1875rem; left: .1875rem;
  width: 1.375rem; height: 1.375rem; border-radius: 50%;
  background: var(--card); box-shadow: var(--shadow-sm);
  transition: transform .2s;
}
/* ⛔ THE ON MARKER IS THE APP'S OWN `cal-toggle-on`, NOT A NEW NAME. Minting `cal-switch-on` beside
   it would leave `style.css`'s pill rule styling a class nobody emits, which is exactly what the
   dead-CSS detector exists to catch. Both declarations below are one class, and this file loads
   after `style.css`, so the switch's filled track wins over the pill's green by cascade order. */
.cal-switch.cal-toggle-on { background: var(--brand); }
.cal-toggle-on .cal-switch-knob { transform: translateX(1.375rem); }

/* ── The race editor, a SCREEN ───────────────────────────────────────────────────────────────────
   #449 phase 7 `7d` part two, conformance row 31. The prototype draws a full screen whose every
   field is a white card with an uppercase eyebrow label; the app drew a bottom sheet with a scrim,
   stacked label-over-input rows and sticky Cancel / Save.

   ⛔ THE CARD, THE EYEBROW AND THE RAIL ARE ALL COMPONENTS THIS PHASE ALREADY BUILT — `.card`,
   `.ia-card-eyebrow` (G3) and `.ia-rail` (G5). What is declared here is only what is this screen's
   own: the chip row, the note's sentence, and the foot.
   ⛔ AND THE FIELD BOX ITSELF IS NOT HERE. `.race-ed input/select` shares ONE declaration with the
   modal it used to be, in style.css, because they are the same field. */
.race-ed .ed-f > label { display: block; }
/* The card's own padding already sets the gutter, so a field box fills it. */
.race-ed .ed-f input,
.race-ed .ed-f select { width: 100%; }

/* ✎ `.ed-chips`, `.ed-chip` AND ITS THREE MODIFIERS ARE PROMOTED, 2026-09-03 (#449 phase 7 `7h`
   part two), to `.ia-chip` in ia/shell.css. This block was the SECOND hand-drawing of one shape and
   said so in writing: "a THIRD promotes it to a named component". The Type picker on Change this day
   is that third, so the rule fired rather than being remembered. `More…` wears `.ia-chip--quiet`
   now, which is named for how it looks rather than for it. Not one declaration of this block was
   dropped; the two the copies disagreed on are resolved in the component, with the measurement. */

/* The railed notes. `.card` supplies the ground and `.ia-rail` the bar; this declares the sentence. */
.race-ed .ed-note {
  font-size: var(--fs-meta); line-height: 1.55; color: var(--text);
}

/* ⛔ THE FOOT IS A COLUMN, NOT THE SHEET'S SIDE-BY-SIDE ROW. Cancel is gone with the sheet, so the
   row held one primary action and, when editing, one destructive one — and a destructive control the
   same size and beside the primary is the last shape that pair should take. */
.ed-actions { display: flex; flex-direction: column; gap: .25rem; margin-top: .25rem; }
.ed-actions .danger-btn { width: 100%; }

/* ── RACE WEEK, the screen (#592) ────────────────────────────────────────────────────────────────
   The hub used to be one collapsed card behind an `Open ▾`, and the design has no such tap: its
   opened state IS the screen. What is declared here is only what that screen needs and no component
   already carries — the dated row, the promise card's two text sizes, and the print sheet.

   ⛔ THE CARD, THE RAIL AND THE EYEBROW ARE ALL COMPONENTS THIS PHASE ALREADY BUILT — `.card`,
   `.ia-rail--prompt` / `.ia-rail--caution` (G5) and `.ia-card-eyebrow` (G3). The prototype rails its
   four promise cards in `--wt-race`, which is this app's `--brand`, and its note in `--warn`, which
   is `--accent`; both are the rail kinds those two colours already name, so nothing new is minted.
   ⛔ AND EVERY SIZE IS A TOKEN, which is the rule this file opened with. `--fs-meta` is 13.6px and
   `--fs-caption` 12.8px after `5k`; the prototype's 13.5 and 12.5 sit inside that pair, and a
   third size for half a pixel would be a 415th declaration nobody can defend. */

/* The dated row: a day or a clock in the mono face, then the sentence it belongs to. Worn by the
   week by the clock, by race morning and by the printed run-walk sheet, so the three cannot drift
   into three different row shapes. ⚠ The label column is empty on a row we cannot honestly date
   (bib pickup), and the grid keeps its width so the sentences still line up. */
/* ⛔ A ROW IS ITS OWN ELEMENT RATHER THAN TWO CELLS OF ONE GRID, WHICH IS THE UNDATED ROW'S DOING.
   A two-column grid puts the hairline on every CELL, so a row with no label needs `nth-child`
   arithmetic that stops being true the first time one row has one child and the next has two. A
   flex row carries its own rule and its own `:first-child` reset, and a sentence with no label
   simply fills the width. */
.rw-rows { margin-top: .6875rem; }
.rw-row { display: flex; gap: .8125rem; padding: .6875rem 0; border-top: 1px solid var(--border); }
.rw-row:first-child { border-top: none; padding-top: 0; }
/* ⛔ IT SIZES TO ITS CONTENT WITH A FLOOR, NOT TO A FIXED 3.25rem. The design's column holds `4:30`
   and this app's clock is `fmtClock`, which prints `4:30 am` — measured at 440, that wrapped onto two
   lines inside a 52px cell and the row read as broken. The floor keeps a card's rows aligned, since
   the labels inside one card are all weekdays or all clocks. */
.rw-when {
  flex: 0 0 auto; min-width: 3.25rem; white-space: nowrap;
  font-family: var(--font-mono); font-size: var(--fs-caption); font-weight: 700;
  color: var(--muted); line-height: 1.45;
}
.rw-what { flex: 1 1 auto; min-width: 0; font-size: var(--fs-meta); color: var(--text); line-height: 1.45; }

/* The sentence under a card's title: the run-walk card's own line, and each promise card's. */
.rw-note {
  font-size: var(--fs-caption); color: var(--muted); line-height: 1.5; margin-top: .25rem;
}
/* The promise card's heading. It is a card TITLE rather than a section title, so it takes the
   display face at the same size `.hub-sec-t` uses one card over. */
.rw-promise-t {
  font-family: var(--font-display); font-weight: 700; font-size: var(--fs-meta); color: var(--navy);
}
/* The amber rail's sentence is body text, not a caption: it is the one thing the locked screen
   actually says to the athlete. */
.rw-rail-t { font-size: var(--fs-meta); color: var(--text); line-height: 1.55; }

/* ── The printed run-walk card ───────────────────────────────────────────────────────────────────
   ⛔ THE SHEET IS OFF SCREEN AND ON PAPER, WHICH IS BOTH HALVES OF ONE REQUIREMENT. The artboard's
   card is a heading, a sentence and a button; race-week.md's acceptance is that the button "prints
   one page at the athlete's goal pace with the beats applied". A visible splits table would be a
   block the design has no place for, and a button that printed the whole app would not be the card.
   ⚠ THE FLAG IS ON `body` AND IS CLEARED ON `afterprint`, so a cancelled dialog cannot leave the
   screen printing-shaped. Nothing here applies without it. */
.rw-sheet { display: none; }
@media print {
  body[data-rw-print] #ia-header,
  body[data-rw-print] #ia-bar,
  body[data-rw-print] #ia-ribbon,
  body[data-rw-print] #view-root > *:not(.rw-printable) { display: none !important; }
  body[data-rw-print] .rw-sheet { display: block; }
  body[data-rw-print] .rw-print { display: none; }
  body[data-rw-print] .rw-printable { box-shadow: none; border: none; }
}
/* ⛔ THE BUTTON IS `.ia-chip`, THE COMPONENT `7h` PROMOTED, NOT A FOURTH HAND-DRAWING OF IT. The
   prototype's `Print the card` is a grey filled button at 13px bold with a 9px radius, which is what
   that component already is; minting a `.rw-print` ground beside it would be the exact repeat the
   promotion exists to stop. `.rw-print` names it ONLY so the print sheet can hide it, and it
   declares nothing outside `@media print` above. */
.rw-print { margin-top: .75rem; }
