/* FondoLab design system: "race bib". See docs/design-system.md.
   Order: fonts, tokens, base, layout, components, pages, print. */

/* ---------- Fonts: Barlow, self-hosted (SIL OFL, see fonts/OFL.txt) ---------- */
@font-face { font-family: "Barlow"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/barlow-400.woff2") format("woff2"); }
@font-face { font-family: "Barlow"; font-style: italic; font-weight: 400; font-display: swap; src: url("fonts/barlow-400-italic.woff2") format("woff2"); }
@font-face { font-family: "Barlow"; font-style: normal; font-weight: 500; font-display: swap; src: url("fonts/barlow-500.woff2") format("woff2"); }
@font-face { font-family: "Barlow"; font-style: normal; font-weight: 600; font-display: swap; src: url("fonts/barlow-600.woff2") format("woff2"); }
@font-face { font-family: "Barlow Condensed"; font-style: normal; font-weight: 700; font-display: swap; src: url("fonts/barlow-condensed-700.woff2") format("woff2"); }
@font-face { font-family: "Barlow Condensed"; font-style: normal; font-weight: 800; font-display: swap; src: url("fonts/barlow-condensed-800.woff2") format("woff2"); }

/* ---------- Tokens ---------- */
:root {
  color-scheme: light dark;

  --bg: #ffffff;
  --surface: #f4f4f2;
  --ink: #111111;
  --ink-2: #525252;
  --line: #e5e5e5;
  --line-strong: #a3a3a3;
  --rule: #111111;
  --accent: #ea580c;
  --accent-ink: #111111;
  --link: #c2410c;
  --ok: #15803d;
  --warn: #b45309;
  --bad: #b91c1c;

  /* The black bands (header, hero, footer) and the white race bib look the
     same in both themes. */
  --band: #111111;
  --band-ink: #ffffff;
  --band-ink-2: #a3a3a3;
  --band-accent: #fb923c;
  --bib: #ffffff;
  --bib-ink: #111111;
  --bib-ink-2: #525252;

  --font: "Barlow", system-ui, -apple-system, "Segoe UI", sans-serif;
  --display: "Barlow Condensed", "Arial Narrow", "Roboto Condensed", system-ui, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --text-xs: 0.8125rem;
  --text-sm: 0.9375rem;
  --text-md: 1.0625rem;
  --text-lg: 1.1875rem;
  --text-xl: 1.5rem;
  --text-2xl: 2.25rem;
  --text-3xl: 3.5rem;

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 5rem;

  --radius: 2px;
  --radius-lg: 4px;
  --measure: 46rem;
  --wide: 76rem;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #161616;
    --surface: #1f1f1f;
    --ink: #f5f5f5;
    --ink-2: #a3a3a3;
    --line: #2e2e2e;
    --line-strong: #5c5c5c;
    --rule: #f5f5f5;
    --accent: #f97316;
    --link: #fb923c;
    --ok: #4ade80;
    --warn: #fbbf24;
    --bad: #f87171;
    --band: #000000;
  }
}

/* ---------- Base ---------- */
* { box-sizing: border-box; }
/* Room for the scrollbar on every page, so short and long pages centre
   alike and the header does not shift between them. */
html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
body {
  margin: 0;
  font: var(--text-md)/1.6 var(--font);
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
main { flex: 1 0 auto; width: 100%; }
h1, h2 {
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  line-height: 0.95;
  letter-spacing: 0;
  margin: var(--space-7) 0 var(--space-4);
}
h1 { font-size: clamp(2.5rem, 1.6rem + 3.5vw, 4.25rem); margin-top: var(--space-6); }
h2 { font-size: clamp(1.875rem, 1.4rem + 1.8vw, 2.75rem); }
h3 { font-size: var(--text-lg); font-weight: 600; line-height: 1.25; margin: var(--space-5) 0 var(--space-2); }
p, ul, ol { margin: 0 0 var(--space-4); }
a { color: var(--link); text-underline-offset: 0.15em; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
small { font-size: var(--text-sm); }
strong { font-weight: 600; }
table, dd, .num { font-variant-numeric: tabular-nums; }
section { margin-top: var(--space-7); }
[data-island]:empty { min-height: 2.5rem; }
/* A full-bleed band inside a narrow column, without a horizontal scrollbar. */
.band {
  background: var(--band);
  color: var(--band-ink);
  box-shadow: 0 0 0 100vmax var(--band);
  clip-path: inset(0 -100vmax);
}
.band a:not(.button) { color: var(--band-accent); }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- Layout ---------- */
main { max-width: var(--measure); margin: 0 auto; padding: var(--space-4) var(--space-4) 0; }
main.wide { max-width: var(--wide); }
.bar { max-width: var(--wide); margin: 0 auto; padding: var(--space-3) var(--space-4); }

/* The header stays on screen: a black band with a few fixed sections, then
   the current section's pages. Its height is --header-h, so whatever else
   sticks to the top sits below it. On short screens (a phone on its side,
   a keyboard open) it scrolls away instead. */
:root {
  --band-h: 3.5rem;
  --subnav-h: 2.75rem;
  --header-h: calc(var(--band-h) + 4px);
}
:root:has(.subnav, .thing-bar) { --header-h: calc(var(--band-h) + 4px + var(--subnav-h)); }
html { scroll-padding-top: var(--header-h); }
.site-header { position: sticky; top: 0; z-index: 20; }
.site-band { background: var(--band); color: var(--band-ink); border-bottom: 4px solid var(--accent); }
.site-band .bar {
  display: flex;
  align-items: stretch;
  gap: var(--space-4);
  height: var(--band-h);
  padding-top: 0;
  padding-bottom: 0;
  padding-right: var(--space-2);
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--display);
  font-size: 1.625rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--band-ink);
  text-decoration: none;
}
.brand svg { width: 30px; height: 30px; flex: none; }
.brand .mark-bg { fill: var(--accent); }
.brand .mark-peak { fill: #111111; }
.sections, .site-utils, .subnav .bar {
  display: flex;
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.sections { flex: 1; gap: var(--space-5); font-size: 1.125rem; }
.sections a, .site-utils a, .subnav a {
  display: flex;
  align-items: center;
  white-space: nowrap;
  text-decoration: none;
  border-top: 3px solid transparent;
  border-bottom: 3px solid transparent;
}
.sections a { color: var(--band-ink); }
.sections a:hover { border-bottom-color: var(--band-ink-2); }
.sections a[aria-current] { color: var(--band-accent); border-bottom-color: var(--accent); }
.site-utils { align-items: stretch; gap: var(--space-5); font-size: 1rem; }
.site-utils a { color: var(--band-ink); }
.site-utils a:hover { color: var(--band-accent); }
.site-utils a[aria-current] { border-bottom-color: var(--accent); }
.util-account svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
/* The current section's pages, on the page's own ground. */
.subnav, .thing-bar { background: var(--bg); border-bottom: 1px solid var(--line); }
.subnav .bar {
  gap: var(--space-5);
  height: var(--subnav-h);
  padding-top: 0;
  padding-bottom: 0;
  font-size: 1rem;
  overflow-x: auto;
  scrollbar-width: none;
}
.subnav a { color: var(--ink-2); }
.subnav a:hover { color: var(--ink); }
.subnav a[aria-current] { color: var(--ink); border-bottom-color: var(--accent); }
/* Phones: the mark alone, the account as an icon; admin moves to the footer. */
@media (max-width: 47.99rem) {
  .brand-name, .util-account span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .site-utils .util-admin { display: none; }
  .util-account { width: 44px; justify-content: center; }
}
@media (min-width: 48rem) {
  :root { --band-h: 4rem; --subnav-h: 2.875rem; }
  .site-band .bar { gap: var(--space-7); padding-right: var(--space-4); }
  .sections { font-size: 1.1875rem; gap: var(--space-6); }
  .subnav .bar { font-size: 1.0625rem; gap: var(--space-6); }
  .util-account svg { display: none; }
}
/* Phones: four sections, the language and the account icon share one row. */
@media (max-width: 29.99rem) {
  .site-band .bar { gap: var(--space-3); }
  .sections { gap: var(--space-3); font-size: 1rem; letter-spacing: 0.03em; }
  .site-utils { gap: var(--space-2); }
  .util-account { width: 32px; }
}
@media (max-width: 22rem) {
  .sections { gap: var(--space-2); font-size: 0.9375rem; letter-spacing: 0.02em; }
}
@media (max-height: 30rem) {
  .site-header { position: static; }
  :root, :root:has(.subnav, .thing-bar) { --header-h: 0px; }
}
/* The language switch is a form, so choosing saves the choice; it looks
   like the links beside it. */
.lang-switch { display: contents; }
.lang-switch button {
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: var(--band-ink-2);
}
.lang-switch button:hover { background: none; color: var(--band-ink); }

/* The footer is the finish line: a chequered strip, then the black band. */
.site-footer { margin-top: var(--space-8); background: var(--band); color: var(--band-ink-2); }
.site-footer::before {
  content: "";
  display: block;
  height: 16px;
  background: repeating-conic-gradient(#111111 0 25%, #ffffff 0 50%) 0 0 / 16px 16px;
}
.site-footer .bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3) var(--space-6);
  padding-top: var(--space-6);
  padding-bottom: var(--space-6);
}
.tagline {
  margin: 0;
  font-family: var(--display);
  font-size: 1.75rem;
  font-weight: 800;
  text-transform: uppercase;
  color: var(--band-ink);
}
.site-footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  font-family: var(--display);
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.site-footer nav a { color: var(--band-ink); text-decoration: none; }
.site-footer nav a:hover { color: var(--band-accent); }

/* ---------- Components ---------- */
.eyebrow {
  font-family: var(--display);
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--link);
  margin: var(--space-6) 0 var(--space-2);
}
.eyebrow + h1 { margin-top: 0; }
.band .eyebrow { color: var(--band-accent); }
.lead { font-size: var(--text-lg); color: var(--ink-2); max-width: 36rem; }
.hint { color: var(--ink-2); }
.error { color: var(--bad); margin: 0; }
.ref { font-family: var(--mono); letter-spacing: 0.1em; }

/* Buttons: square, condensed, upper case, like a race-number font. */
button, .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 2.75rem;
  padding: 0.35rem 1.1rem;
  font-family: var(--display);
  font-size: 1.1875rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  line-height: 1.1;
  text-transform: uppercase;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
}
button:hover, .button:hover { background: var(--ink); color: var(--bg); }
button.primary, .button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
button.primary:hover, .button.primary:hover { background: var(--ink); border-color: var(--ink); color: var(--bg); }
/* Strava's own orange, as its brand guidelines ask of a "Connect with Strava" button. */
.button.strava { background: #fc5200; border-color: #fc5200; color: #fff; }
.button.strava:hover { background: var(--ink); border-color: var(--ink); color: var(--bg); }
button.quiet, .button.quiet { border-color: var(--line-strong); color: var(--ink-2); }
button.quiet:hover, .button.quiet:hover { border-color: var(--ink); background: transparent; color: var(--ink); }
button.danger, .button.danger { border-color: var(--bad); color: var(--bad); }
button.danger:hover, .button.danger:hover { background: var(--bad); color: var(--bg); }
.band .button:not(.primary) { border-color: var(--band-ink); color: var(--band-ink); }
.band .button:hover { background: var(--band-ink); border-color: var(--band-ink); color: var(--band); }
.actions { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }

/* Forms */
input[type="email"], input[type="text"], input[type="number"], input[type="date"], input[type="time"], input:not([type]), select {
  font: inherit;
  min-height: 2.75rem;
  padding: 0.4rem 0.6rem;
  border: 2px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* iOS gives native date and time inputs a minimum width of their own, wider
   than a phone's half column, so they spill over the field beside them. */
input[type="date"], input[type="time"] { -webkit-appearance: none; appearance: none; min-width: 0; }
::-webkit-date-and-time-value { text-align: left; }
input:hover, select:hover { border-color: var(--ink-2); }
input:focus-visible, select:focus-visible { outline-offset: 0; border-color: var(--ink); }
/* Selects. The native one gets our border and a chevron of our own; that
   is all there is without JavaScript, and on touch screens, where the
   phone's own picker suits a thumb. With a mouse, site.js wraps it in
   .select: a button showing the choice and a list in the site's type, the
   hidden select still holding the value. */
:root { --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 9'%3E%3Cpath d='M1.5 1.5 7 7l5.5-5.5' fill='none' stroke='%23525252' stroke-width='2.5'/%3E%3C/svg%3E"); }
@media (prefers-color-scheme: dark) {
  :root { --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 9'%3E%3Cpath d='M1.5 1.5 7 7l5.5-5.5' fill='none' stroke='%23a3a3a3' stroke-width='2.5'/%3E%3C/svg%3E"); }
}
select, .select { width: 100%; max-width: 100%; }
select {
  appearance: none;
  padding-right: 2.5rem;
  background-image: var(--chevron);
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 0.875rem auto;
  text-overflow: ellipsis;
  cursor: pointer;
}
.select { position: relative; display: inline-block; vertical-align: middle; }
.select.is-on > select { display: none; }
.select-button {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  min-height: 2.75rem;
  padding: 0.4rem 0.75rem 0.4rem 0.6rem;
  font: inherit;
  letter-spacing: normal;
  text-transform: none;
  text-align: left;
  border: 2px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.select-button:hover { background: var(--bg); color: var(--ink); border-color: var(--ink-2); }
.select-button:focus-visible, .select-button[aria-expanded="true"] { outline-offset: 0; border-color: var(--ink); }
.select-button:disabled { cursor: default; opacity: 0.5; }
.select-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.select-button::after {
  content: "";
  flex: none;
  width: 0.875rem;
  height: 0.5625rem;
  background: var(--chevron) no-repeat center / contain;
  transition: transform 0.15s;
}
.select-button[aria-expanded="true"]::after { transform: rotate(180deg); }
/* The list hangs from the button with the header's orange stripe on top,
   or on the bottom when there is only room above. */
.select-list {
  position: absolute;
  z-index: 30;
  top: calc(100% + 2px);
  left: 0;
  min-width: 100%;
  width: max-content;
  max-width: min(24rem, calc(100vw - 2rem));
  max-height: 18rem;
  overflow-y: auto;
  margin: 0;
  padding: var(--space-1) 0;
  list-style: none;
  background: var(--bg);
  color: var(--ink);
  border: 2px solid var(--ink);
  border-top: 4px solid var(--accent);
  border-radius: var(--radius);
  font-weight: 500;
}
.select-list[hidden] { display: none; }
.select.up .select-list { top: auto; bottom: calc(100% + 2px); border-top: 2px solid var(--ink); border-bottom: 4px solid var(--accent); }
.select.end .select-list { left: auto; right: 0; }
.select-list [role="option"] {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: 2.5rem;
  padding: 0.3rem 0.75rem 0.3rem 0.6rem;
  border-left: 4px solid transparent;
  cursor: pointer;
}
.select-list [aria-selected="true"] { border-left-color: var(--accent); font-weight: 600; }
/* The chosen one carries a tick. */
.select-list [aria-selected="true"]::after {
  content: "";
  flex: none;
  width: 0.75rem;
  height: 0.4rem;
  margin-bottom: 0.2rem;
  border: solid var(--accent);
  border-width: 0 0 2.5px 2.5px;
  transform: rotate(-45deg);
}
.select-list .is-active { background: var(--ink); color: var(--bg); }
.select-list [aria-disabled="true"] { color: var(--ink-2); cursor: default; }
.select-list [aria-disabled="true"].is-active { background: var(--surface); color: var(--ink-2); }
input[type="radio"], input[type="checkbox"] { accent-color: var(--accent); width: 1.1rem; height: 1.1rem; }
form.stack { display: grid; gap: var(--space-2); max-width: 26rem; }
form.stack label { font-weight: 600; font-size: var(--text-sm); }
form.stack button { justify-self: start; margin-top: var(--space-2); }
form.inline { display: inline-block; margin: 0 var(--space-2) var(--space-2) 0; }

/* The confirm dialog (hx-confirm): a black head band with the header's
   orange stripe and a cycling eyebrow, the question as a heading, and the
   action beside Cancel. */
dialog.confirm {
  width: min(30rem, calc(100% - 2rem));
  max-height: calc(100% - 2rem);
  padding: 0;
  border: 3px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--bg);
  color: var(--ink);
}
dialog.confirm::backdrop { background: rgb(0 0 0 / 0.6); }
.confirm-head {
  margin: 0;
  padding: var(--space-3) var(--space-5);
  background: var(--band);
  color: var(--band-accent);
  border-bottom: 4px solid var(--accent);
}
.confirm-body { padding: var(--space-5); }
.confirm-body h2 { margin: 0 0 var(--space-3); font-size: var(--text-2xl); overflow-wrap: anywhere; }
.confirm-body .actions { margin: var(--space-5) 0 0; }
.confirm [hidden] { display: none; }
.choices { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-5); }
.choices label { display: inline-flex; gap: 0.4rem; align-items: center; }

/* Stat tiles: the strip along the bottom of a plate. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  margin: var(--space-4) 0;
  border-top: 3px solid var(--rule);
}
.stats > div { padding: var(--space-3) var(--space-4) var(--space-3) 0; border-bottom: 1px solid var(--line); }
.stats dt, .feed-board dt, .plate dt {
  font-family: var(--display);
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.stats dd, .feed-board dd, .plate dd {
  margin: 0;
  font-family: var(--display);
  font-size: 2.25rem;
  font-weight: 800;
  line-height: 1.05;
}
dl { margin: 0; }

/* A plate: one headline figure with a head line, its unit and a strip of
   three figures. The layout is shared; each page dresses it as its own
   race-day object (.bib, .echelon, .stem-card) by setting the --plate
   colours and a decoration. */
.plate {
  --plate: var(--bg);
  --plate-ink: var(--ink);
  --plate-ink-2: var(--ink-2);
  --plate-accent: var(--link);
  --plate-line: var(--line);
  position: relative;
  margin: 0;
  padding: var(--space-5) clamp(var(--space-4), 7cqi, var(--space-6)) var(--space-4);
  width: 100%;
  max-width: 27rem;
  background: var(--plate);
  color: var(--plate-ink);
  /* Everything on a plate is sized to its width, so it fits a phone. */
  container-type: inline-size;
}
.plate dt { color: var(--plate-ink-2); }
.plate-head {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  margin: 0 var(--space-3);
  font-family: var(--display);
  font-size: clamp(0.8125rem, 4cqi, 1rem);
  font-weight: 700;
  letter-spacing: 0.1em;
  white-space: nowrap;
  text-transform: uppercase;
  color: var(--plate-ink-2);
}
.plate-number {
  margin: 0;
  text-align: center;
  font-family: var(--display);
  font-size: clamp(4.5rem, 40cqi, 10.5rem);
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.plate-unit {
  margin: 0 0 var(--space-4);
  text-align: center;
  font-family: var(--display);
  font-size: clamp(1rem, 5.5cqi, 1.375rem);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--plate-accent);
}
.plate dl { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 3px solid var(--plate-ink); text-align: center; }
.plate dl > div { min-width: 0; padding: var(--space-3) var(--space-1) 0; }
.plate dt { font-size: clamp(0.75rem, 3.6cqi, 0.9375rem); letter-spacing: 0.06em; }
.plate dl > div + div { border-left: 1px solid var(--plate-line); }
/* The three figures share the plate's width, so they shrink with it. */
.plate dd { font-size: clamp(1rem, 6.6cqi, 1.875rem); white-space: nowrap; }

/* A board: a plate as wide as the plan's column (a race's weather and
   pacing tabs), like the feed-zone board. Once there is room the headline
   figure and its picture stand beside the figures, which take two rows. */
.plate.board { max-width: none; }
.plate-hero { min-width: 0; }
@container (min-width: 34rem) {
  .board .plate-body {
    display: grid;
    grid-template-columns: minmax(0, 4fr) minmax(0, 5fr);
    gap: var(--space-5);
    align-items: center;
    margin-top: var(--space-2);
  }
  .board .plate-number { font-size: clamp(4.5rem, 17cqi, 8rem); }
  .board .plate-unit { font-size: clamp(1rem, 2.8cqi, 1.375rem); }
  .board dl {
    grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
    align-self: stretch;
    align-content: center;
    border-top: 0;
    border-left: 3px solid var(--plate-ink);
    padding-left: var(--space-4);
    text-align: left;
  }
  .board dl > div { padding: var(--space-3) var(--space-2) var(--space-3) 0; border-bottom: 1px solid var(--plate-line); }
  .board dl > div + div { border-left: 0; }
  .board dt { font-size: clamp(0.75rem, 1.9cqi, 0.9375rem); }
  .board dd { font-size: clamp(1.375rem, 4.4cqi, 2.25rem); }
}

/* The race bib (home): white paper, a safety pin in each corner. */
.bib {
  --plate: var(--bib);
  --plate-ink: var(--bib-ink);
  --plate-ink-2: var(--bib-ink-2);
  --plate-accent: #c2410c;
  --plate-line: #d4d4d4;
  background:
    radial-gradient(circle, var(--bib-ink) 5px, transparent 6px) left 10px top 10px / 12px 12px no-repeat,
    radial-gradient(circle, var(--bib-ink) 5px, transparent 6px) right 10px top 10px / 12px 12px no-repeat,
    radial-gradient(circle, var(--bib-ink) 5px, transparent 6px) left 10px bottom 10px / 12px 12px no-repeat,
    radial-gradient(circle, var(--bib-ink) 5px, transparent 6px) right 10px bottom 10px / 12px 12px no-repeat,
    var(--bib);
  border: 2px solid var(--bib-ink);
  border-radius: 6px;
}

/* The rider licence (rider profile, "Team presentation"): the card a rider
   shows at sign-on. A black band with an orange stripe on top, the rider's
   photo in team kit, the drag area as its big figure, the other numbers as
   licence fields and a machine-readable strip along the bottom. It stays a
   white card in both themes, like the bib. */
.licence {
  margin: 0 0 var(--space-3);
  width: 100%;
  overflow: hidden;
  background: var(--bib);
  color: var(--bib-ink);
  border: 2px solid var(--bib-ink);
  border-radius: 6px;
  /* Everything on the card is sized to its width, so it fits a phone. */
  container-type: inline-size;
}
.licence-head {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  margin: 0;
  padding: var(--space-2) clamp(var(--space-3), 5cqi, var(--space-5));
  background: var(--band);
  color: var(--band-ink);
  border-bottom: 4px solid var(--accent);
  font-family: var(--display);
  font-size: clamp(0.875rem, 4.2cqi, 1.125rem);
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.licence-head span + span { color: var(--band-accent); }
.licence-body {
  display: grid;
  grid-template-columns: 30% minmax(0, 1fr);
  grid-template-areas: "photo hero" "photo fields";
  gap: var(--space-3) clamp(var(--space-3), 5cqi, var(--space-5));
  padding: clamp(var(--space-3), 5cqi, var(--space-5));
  /* The fine lines of security print. */
  background: repeating-linear-gradient(-30deg, transparent 0 6px, rgb(234 88 12 / 0.08) 6px 7px);
}
.licence-photo {
  grid-area: photo;
  align-self: start;
  display: block;
  width: 100%;
  height: auto;
  background: var(--accent);
  border: 2px solid var(--bib-ink);
}
.licence-photo .kit, .licence-photo .helmet { fill: #111111; }
.licence-photo .sash, .licence-photo .lens { fill: #ffffff; }
.licence-photo .helmet { stroke: var(--accent); stroke-width: 1.5; }
.licence-photo .vent { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; }
.licence-hero { grid-area: hero; display: grid; margin: 0; font-family: var(--display); line-height: 1; }
.licence-label, .licence-fields dt {
  font-family: var(--display);
  font-size: clamp(0.6875rem, 3.4cqi, 0.875rem);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bib-ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.licence-number { font-size: clamp(3rem, 20cqi, 6.25rem); font-weight: 800; line-height: 0.95; font-variant-numeric: tabular-nums; }
.licence-unit { font-size: clamp(0.875rem, 4.4cqi, 1.25rem); font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: #c2410c; }
.licence-fields {
  grid-area: fields;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2) var(--space-3);
  padding-top: var(--space-2);
  border-top: 3px solid var(--bib-ink);
}
.licence-fields > div { min-width: 0; }
.licence-fields dd { margin: 0; font-family: var(--display); font-size: clamp(1.125rem, 6cqi, 1.625rem); font-weight: 800; line-height: 1.05; white-space: nowrap; }
.licence-mrz {
  margin: 0;
  padding: var(--space-2) clamp(var(--space-3), 5cqi, var(--space-5));
  border-top: 1px solid #d4d4d4;
  background: #f4f4f2;
  font-family: var(--mono);
  font-size: min(3.6cqi, 1.125rem);
  letter-spacing: 0.06em;
  line-height: 1.4;
  color: var(--bib-ink-2);
  white-space: nowrap;
  overflow: hidden;
}
.licence-mrz span { display: block; }
/* As wide as the plan's column, like a board: once there is room the photo,
   the drag area and the fields stand side by side. */
@container (min-width: 46rem) {
  .licence-body {
    grid-template-columns: minmax(0, 2fr) minmax(0, 4fr) minmax(0, 4fr);
    grid-template-areas: "photo hero fields";
    align-items: center;
  }
  .licence-number { font-size: clamp(3rem, 12cqi, 6.25rem); }
  .licence-label, .licence-fields dt { font-size: clamp(0.6875rem, 1.9cqi, 0.9375rem); }
  .licence-unit { font-size: clamp(0.875rem, 2.4cqi, 1.25rem); }
  .licence-fields {
    align-self: stretch;
    align-content: center;
    padding: 0 0 0 var(--space-4);
    border-top: 0;
    border-left: 3px solid var(--bib-ink);
  }
  .licence-fields dd { font-size: clamp(1.125rem, 3.6cqi, 1.875rem); }
}

/* The echelon (race weather): riders staggered across the road in a
   crosswind, drawn under the headline figure (.echelon-riders). */
.echelon {
  border: 3px solid var(--rule);
  border-radius: var(--radius);
}
.echelon-riders { display: block; width: 100%; height: auto; margin: 0 0 var(--space-3); }
.echelon-riders .road { stroke: var(--line-strong); stroke-width: 1.5; stroke-dasharray: 6 5; }
.echelon-riders .wind { stroke: var(--ink-2); stroke-width: 2; stroke-linecap: round; fill: none; }
.echelon-riders .rider { fill: var(--ink); }
.echelon-riders .rider.front { fill: var(--accent); }

/* The stem card (race pacing, "Team orders"): the race profile and the
   plan taped to the stem, two strips of black tape across its edges, the
   course's silhouette under the headline figure (.stem-profile). */
.stem-card {
  --plate: var(--bib);
  --plate-ink: var(--bib-ink);
  --plate-ink-2: var(--bib-ink-2);
  --plate-accent: #c2410c;
  --plate-line: #d4d4d4;
  border: 2px solid var(--bib-ink);
  border-radius: var(--radius);
}
.stem-card::before, .stem-card::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 5.5rem;
  height: 1.3rem;
  background: color-mix(in srgb, #111 85%, transparent);
}
.stem-card::before { top: -0.7rem; transform: translateX(-50%) rotate(-3deg); }
.stem-card::after { bottom: -0.7rem; transform: translateX(-50%) rotate(2deg); }
.stem-profile { display: block; width: 100%; height: 2.5rem; margin: 0 0 var(--space-3); }
.stem-profile path { fill: var(--accent); }

/* The feed-zone board (fuel planner, "Feed zone"): a plan's totals on the
   roadside sign that marks the feed zone, a white board on two posts with
   an orange head and a chevron edge. It stays white in both themes. */
.feed-board {
  position: relative;
  margin: var(--space-4) 0 var(--space-6);
  background: #ffffff;
  color: #111111;
  border: 3px solid #111111;
  container-type: inline-size;
}
.feed-board::before, .feed-board::after {
  content: "";
  position: absolute;
  top: 100%;
  width: 0.625rem;
  height: calc(var(--space-6) - 3px);
  margin-top: 3px;
  background: var(--line-strong);
}
.feed-board::before { left: 18%; }
.feed-board::after { right: 18%; }
.feed-board-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0 var(--space-4);
  margin: 0;
  padding: var(--space-1) var(--space-4);
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--display);
  font-size: 1.125rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border-bottom: 3px solid #111111;
}
.feed-board-head span + span { font-weight: 700; }
.feed-board dl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  padding: var(--space-2) var(--space-4);
}
.feed-board dl > div { padding: var(--space-2) var(--space-3) var(--space-2) 0; }
.feed-board dt { color: #525252; }
.feed-board dd { white-space: nowrap; font-size: clamp(1.5rem, 4.6cqi, 2.25rem); }
.feed-board dl::after {
  content: "";
  grid-column: 1 / -1;
  height: 0.75rem;
  margin: var(--space-2) calc(-1 * var(--space-4)) calc(-1 * var(--space-2));
  border-top: 2px solid #111111;
  background: repeating-linear-gradient(-45deg, #111111 0 0.5rem, var(--accent) 0.5rem 1rem);
}

/* The fluid deficit: a gauge from 0 to 4 % of body weight with the safe,
   watch and too-high zones, and a marker where the plan lands. */
/* A plan's second summary block, under its plate: a boxed gauge or share
   bar with a heading line. The fluid deficit adds status colours. */
.deficit, .panel {
  margin: var(--space-4) 0;
  padding: var(--space-3) var(--space-4);
  border: 2px solid var(--line-strong);
  border-left-width: 0.5rem;
  background: var(--surface);
}
.deficit.ok { border-color: var(--ok); }
.deficit.warn { border-color: var(--warn); }
.deficit.bad { border-color: var(--bad); }
.deficit p, .panel p { margin: 0; }
.panel { border-left-color: var(--rule); }
.panel-head strong { font-family: var(--display); font-size: 1.125rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; }
.deficit-head, .panel-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-3); }

/* Ghost (*Neutralised start*): a race tab's body while its weather is
   fetched (partial race-ghost). Grey shapes where the plan will be, pulsing
   gently, under a status line; htmx swaps the real body in. */
.ghost-status { margin: 0 0 var(--space-4); color: var(--ink-2); }
.ghost-status .eyebrow { margin: 0 var(--space-2) 0 0; }
.ghost-line, .ghost-block {
  display: block;
  background: var(--line);
  animation: ghost-pulse 1.6s ease-in-out infinite;
}
.ghost-line { width: 70%; height: 0.9rem; margin: var(--space-3) 0; }
.ghost-line.short { width: 40%; }
.ghost-line.wide { width: 100%; }
.ghost-line.tall { width: 50%; height: 2.5rem; }
.ghost-block { height: 14rem; margin: var(--space-4) 0; }
.ghost-plate { height: 11rem; border: 3px solid var(--line-strong); background: var(--surface); }
.ghost-panel { height: 5rem; border-left: 0.5rem solid var(--line-strong); }
.ghost .card::before { color: var(--line); }
@keyframes ghost-pulse { 50% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) {
  .ghost-line, .ghost-block { animation: none; }
}
.deficit-label {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.deficit.ok .deficit-label { color: var(--ok); }
.deficit.warn .deficit-label { color: var(--warn); }
.deficit.bad .deficit-label { color: var(--bad); }
.deficit-gauge { display: block; width: 100%; height: 0.875rem; margin: var(--space-3) 0 var(--space-1); }
.deficit-gauge .zone-ok { fill: var(--ok); opacity: 0.6; }
.deficit-gauge .zone-warn { fill: var(--warn); opacity: 0.6; }
.deficit-gauge .zone-bad { fill: var(--bad); opacity: 0.6; }
.deficit-gauge .marker { fill: var(--ink); }
/* Ticks at 0, 2, 3 and 4 %: the zones are 2 : 1 : 1 wide. */
.deficit-scale {
  position: relative;
  height: 1.25em;
  margin-bottom: var(--space-3) !important;
  font-family: var(--display);
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--ink-2);
}
.deficit-scale span { position: absolute; top: 0; }
.deficit-scale span:nth-child(2) { left: 50%; transform: translateX(-50%); }
.deficit-scale span:nth-child(3) { left: 75%; transform: translateX(-50%); }
.deficit-scale span:nth-child(4) { right: 0; }

/* Line icons in the plan's cues, drawn in the text colour. */
.icon {
  width: 1.1em;
  height: 1.1em;
  vertical-align: -0.2em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.plan-table .cue { color: var(--ink); }
.plan-table .cue .icon { color: var(--link); }
/* A cell's warning: in the warning colour behind a small triangle. */
.plan .flag { color: var(--warn); font-weight: 600; }
.plan .flag::before {
  content: "";
  display: inline-block;
  width: 0.7em;
  height: 0.6em;
  margin-right: 0.3em;
  background: currentColor;
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}

/* Notices */
.notice {
  border: 2px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface);
  padding: var(--space-2) var(--space-4);
  margin: var(--space-3) 0;
}
.notice p { margin: var(--space-1) 0; }
.notice ul { margin: var(--space-1) 0; padding-left: 1.2rem; }
.notice.ok { border-color: var(--ok); }
.notice.warn { border-color: var(--warn); }
.notice.bad { border-color: var(--bad); }
/* Where to ask for an invitation: the one way forward on its page */
.notice.ask { border: 3px solid var(--accent); }
.notice.ask h2 { margin: var(--space-2) 0 var(--space-1); }

/* Badges */
.badge {
  display: inline-block;
  font-family: var(--display);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: var(--ink);
  color: var(--bg);
  border-radius: var(--radius);
  padding: 0.05rem 0.45rem;
  vertical-align: 0.2em;
}

/* Cards: numbered like stages, joined into one block. Flex rather than grid
   so a short last row stretches to fill instead of leaving a gap of rule. */
.cards {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  margin: var(--space-4) 0;
  border: 3px solid var(--rule);
  background: var(--rule);
  counter-reset: stage;
}
.card {
  display: block;
  flex: 1 1 16rem;
  padding: var(--space-5);
  background: var(--bg);
  color: var(--ink);
  text-decoration: none;
  counter-increment: stage;
}
.card::before {
  content: counter(stage, decimal-leading-zero);
  display: block;
  font-family: var(--display);
  font-size: 4rem;
  font-weight: 800;
  line-height: 1;
  color: var(--line-strong);
}
.card h3 {
  margin: var(--space-3) 0 var(--space-2);
  font-family: var(--display);
  font-size: 1.875rem;
  font-weight: 800;
  line-height: 1;
  text-transform: uppercase;
}
.card p { margin: 0; color: var(--ink-2); }
a.card { background: var(--band); color: var(--band-ink); }
a.card::before { color: var(--band-accent); }
a.card h3::after { content: " →"; }
a.card p { color: var(--band-ink-2); }
a.card:hover h3 { color: var(--band-accent); }

/* Tables */
.table-scroll { overflow-x: auto; }
.data-table, .plan-table, .method-table, .feeds, .prose table {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--text-sm);
}
.data-table th, .data-table td,
.plan-table th, .plan-table td,
.method-table th, .method-table td,
.prose th, .prose td {
  text-align: left;
  vertical-align: top;
  padding: var(--space-2) var(--space-3) var(--space-2) 0;
  border-bottom: 1px solid var(--line);
}
.data-table thead th, .plan-table thead th, .method-table thead th, .prose thead th, .feeds th {
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  border-bottom: 3px solid var(--rule);
}

/* Long-form text */
.prose { font-size: 1.125rem; }
.prose h2 { margin-top: var(--space-7); }
.prose table { margin: var(--space-4) 0; }
sup.cite { font-size: 0.72em; line-height: 0; font-family: var(--mono); }
sup.cite a { text-decoration: none; }

/* Lists of articles: big condensed titles between heavy rules. */
.article-list { list-style: none; padding: 0; border-top: 3px solid var(--rule); }
.article-list li { padding: var(--space-4) 0; border-bottom: 2px solid var(--rule); }
.article-list a {
  font-family: var(--display);
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1.05;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
}
.article-list a:hover { color: var(--link); }
.article-list .hint { display: block; margin-top: var(--space-1); }
.article-list .level { display: flex; margin-bottom: var(--space-1); }

/* An article's level: four steps climbing like a gradient, filled in the
   accent up to the level (Cauberg 1 … l'Angliru 4). */
.level {
  display: inline-flex;
  align-items: flex-end;
  gap: var(--space-2);
  font-family: var(--display);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink);
}
.level-steps { display: inline-flex; align-items: flex-end; gap: 2px; }
.level-steps i { width: 5px; border: 1.5px solid var(--ink); }
.level-steps i:nth-child(1) { height: 5px; }
.level-steps i:nth-child(2) { height: 8px; }
.level-steps i:nth-child(3) { height: 11px; }
.level-steps i:nth-child(4) { height: 14px; }
.level-1 i:nth-child(-n+1),
.level-2 i:nth-child(-n+2),
.level-3 i:nth-child(-n+3),
.level-4 i:nth-child(-n+4) { background: var(--accent); }
.kb-meta .level { margin-right: var(--space-3); }
.kb-levels { margin: var(--space-4) 0 var(--space-5); }
.kb-levels .hint { margin: 0 0 var(--space-2); }

@media (max-width: 36rem) {
  .plate { padding-left: var(--space-5); padding-right: var(--space-5); }
}

/* The head unit (calculators, "Neutral service"): the bike computer on the
   stem, a grey LCD screen in a black bezel with its two buttons on top. It
   stays a screen in both themes, like the bib stays paper. */
.head-unit {
  --plate: #dfe3d3;
  --plate-ink: #111111;
  --plate-ink-2: #4b4f45;
  --plate-accent: #c2410c;
  --plate-line: #b9bdae;
  border: 0.6rem solid #1a1a1a;
  border-radius: 14px;
  margin-top: 0.6rem;
  /* On a dark page the black bezel needs an edge to show. */
  outline: 1px solid var(--line-strong);
}
.head-unit::before, .head-unit::after {
  content: "";
  position: absolute;
  top: calc(-0.6rem - 0.45rem);
  width: 2.4rem;
  height: 0.45rem;
  background: #1a1a1a;
  border-radius: 3px 3px 0 0;
}
.head-unit::before { left: 1.4rem; }
.head-unit::after { right: 1.4rem; }
.head-unit-rec::before {
  content: "";
  display: inline-block;
  width: 0.55em;
  height: 0.55em;
  margin-right: 0.35em;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: 0.08em;
}

/* ---------- Pages ---------- */

/* Home */
main.home { padding-top: 0; }
.hero {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-7);
  padding: var(--space-7) 0 var(--space-8);
}
.hero-text { flex: 1 1 30rem; min-width: 0; }
.hero .eyebrow { margin-top: 0; }
.hero h1 { font-size: clamp(3.75rem, 2rem + 6vw, 7rem); line-height: 0.88; margin: 0 0 var(--space-5); }
.hero h1 span { display: block; }
.hero h1 span:last-child { color: var(--band-accent); }
.hero .lead { color: #d4d4d4; font-size: 1.25rem; }
.hero .actions { margin-top: var(--space-6); }
.hero .bib { flex: 1 1 20rem; transform: rotate(-2deg); }
.pockets {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2) var(--space-6);
  margin: 0;
  padding: var(--space-4) 0;
  font-family: var(--display);
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  background: var(--accent);
  color: var(--accent-ink);
  box-shadow: 0 0 0 100vmax var(--accent);
  clip-path: inset(0 -100vmax);
}
.pockets a { color: var(--accent-ink); }
.principles { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: var(--space-6); margin: var(--space-4) 0 0; padding: 0; list-style: none; }
.principles h3 { margin: 0 0 var(--space-2); font-family: var(--display); font-size: 1.5rem; font-weight: 800; line-height: 1; text-transform: uppercase; }
.principles p { margin: 0; color: var(--ink-2); }

/* Fueling planner and rider profile */
.planner { display: grid; gap: var(--space-5); }
.planner-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: end; gap: var(--space-4); }
.planner-head h1 { margin: 0 0 var(--space-2); }
.planner-head .lead { margin: 0; }
.planner-body { display: grid; gap: var(--space-6); }
/* Grid items and fieldsets grow to fit their widest content by default,
   which pushes the page past a phone's width; let them shrink instead. */
.planner-body > *, .planner-form fieldset { min-width: 0; }
/* Both columns start on the same line: a column, and whatever opens it
   when the column is a plain wrapper, drops its top margin. */
.planner-body > *, .planner-body > * > :first-child { margin-top: 0; }
.planner-form fieldset, .planner-form > section {
  border: 0;
  border-top: 3px solid var(--rule);
  margin: 0 0 var(--space-5);
  padding: var(--space-2) 0 0;
}
.planner-form legend, .planner-form .stage-title {
  margin: 0;
  font-family: var(--display);
  font-size: 1.375rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: var(--space-2) var(--space-2) 0 0;
}
/* The fueling planner's sections are numbered like stages: 01, 02, 03. */
.planner-form.stages { counter-reset: stage; }
/* A sidebar section that is not a form (race weather) draws its heading
   on the rule, as a fieldset's legend sits on its border. */
.planner-form > section { border-top: 0; }
.planner-form .stage-title { display: flex; align-items: center; padding-right: 0; }
.planner-form .stage-title::after { content: ""; flex: 1; margin-left: var(--space-2); border-top: 3px solid var(--rule); }
.planner-form.stages :is(legend, .stage-title)::before {
  counter-increment: stage;
  content: counter(stage, decimal-leading-zero);
  margin-right: var(--space-2);
  color: var(--link);
}
/* A group of choices inside a stage (sweat test effort) is not a stage. */
.planner-form.stages fieldset fieldset > :is(legend, .stage-title)::before { content: none; counter-increment: none; }
.planner-form label { display: block; margin: var(--space-2) 0; font-size: var(--text-sm); font-weight: 600; }
.planner-form label small { color: var(--ink-2); font-weight: 400; }
.planner-form .choices label, .planner-form label.check { font-weight: 400; font-size: var(--text-md); }
.planner-form .hint { font-size: var(--text-sm); margin: var(--space-2) 0; }
.planner-form input:not([type="radio"]):not([type="checkbox"]) { display: block; width: 100%; max-width: 12rem; margin-top: var(--space-1); }
.planner-form :is(select, .select) { display: block; max-width: 12rem; margin-top: var(--space-1); }
/* "Where from" notes are sentences, not numbers. */
.planner-form input[name$="_from"]:not([type="radio"]):not([type="checkbox"]) { max-width: none; }
.planner-form label.check { display: flex; gap: var(--space-2); align-items: baseline; }
.planner-form label.check small { display: block; }
/* Labels sit on the bottom of their row, so inputs line up when a label's
   hint wraps. */
.sizes { display: grid; grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr)); gap: 0 var(--space-3); align-items: end; }
.sizes > * { min-width: 0; }
.feeds { margin-bottom: var(--space-3); }
.feeds th { text-align: left; padding-bottom: var(--space-1); }
.feeds td { padding: var(--space-1) var(--space-2) var(--space-1) 0; }
.feeds input:not([type="radio"]):not([type="checkbox"]) { max-width: none; margin: 0; }
/* A value the form shows but another page owns: the fueling planner's
   body weight, which the rider profile keeps. */
.readout { margin: var(--space-2) 0; font-size: var(--text-sm); font-weight: 600; }
.readout strong { margin-left: var(--space-2); font-family: var(--display); font-size: 1.375rem; font-weight: 800; }
.readout small { display: block; color: var(--ink-2); font-weight: 400; }
.readout small .source-tag { display: inline; }

/* Rider profile: one block per bike, between hairlines. */
.bike { padding: var(--space-2) 0 var(--space-3); border-bottom: 1px solid var(--line); margin-bottom: var(--space-3); }
.bike h3 { font-size: var(--text-md); margin: var(--space-4) 0 var(--space-1); }
/* Fixed columns, so fields line up from row to row. */
.sizes.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sizes.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.planner-form .sizes.cols-2 :is(input, select, .select), .planner-form .sizes.cols-3 :is(input, select, .select) { width: 100%; max-width: none; }
.units-toggle { display: inline-flex; }
.units-toggle button { border-color: var(--ink); color: var(--ink); min-height: 2.5rem; font-size: 1.0625rem; }
.units-toggle button:last-child { border-left: 0; }
.units-toggle button[aria-pressed="true"] { background: var(--ink); color: var(--bg); }
.plan { margin-top: 0; }
.plan > h2 { margin-top: 0; }
.pack { margin: var(--space-3) 0; }
.plan-table small { color: var(--ink-2); }
.plan-table th a { color: inherit; }
.plan-table td:first-child strong { font-family: var(--display); font-size: 1.25rem; font-weight: 800; text-transform: uppercase; white-space: nowrap; }
.plan-table .finish td { border-bottom: 0; }
/* The finish row gets a chequered flag. */
.plan-table .finish td:first-child strong::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-right: 0.4rem;
  vertical-align: -1px;
  border: 1px solid var(--ink);
  background: repeating-conic-gradient(var(--ink) 0 25%, var(--bg) 0 50%) 0 0 / 7px 7px;
}
.plan-table td.carbs, .plan-table td.fluid, .plan-table td.sodium, .plan-table td.caffeine { white-space: nowrap; }
.print-only { display: none; }
@media (min-width: 60rem) {
  .planner-body { grid-template-columns: minmax(20rem, 26rem) 1fr; align-items: start; }
  .planner-body .plan { position: sticky; top: calc(var(--header-h) + var(--space-4)); max-height: calc(100vh - var(--header-h) - 2rem); overflow-y: auto; }
  /* A race's tabs (weather, pacing, fueling) and the rider's: a narrower column of inputs
     on mid-size screens, more air and a heavy rule between it and the plan
     the wider the screen. The plan scrolls with the page; on fueling its
     summary (totals and deficit) stays in view. */
  .race-body {
    grid-template-columns: minmax(18rem, 22rem) 1fr;
    column-gap: clamp(var(--space-5), 5vw - 1.5rem, var(--space-7));
  }
  .race-body .plan {
    position: static;
    max-height: none;
    overflow: visible;
    padding-left: clamp(var(--space-5), 5vw - 1.5rem, var(--space-7));
    border-left: 3px solid var(--rule);
  }
  /* The rider profile's form and setup share the width, with more air
     between them the wider the screen. */
  .profile-planner .planner-body {
    grid-template-columns: minmax(20rem, 5fr) minmax(24rem, 6fr);
    column-gap: clamp(var(--space-6), 8vw - 2rem, var(--space-8));
  }
}

@media (min-width: 70rem) {
  .race-body { grid-template-columns: minmax(20rem, 26rem) 1fr; }
}
@media screen and (min-width: 60rem) and (min-height: 48rem) {
  .fueling-body .plan-summary {
    position: sticky;
    top: var(--header-h);
    z-index: 1;
    padding-top: var(--space-2);
    background: var(--bg);
    border-bottom: 1px solid var(--line);
  }
  .fueling-body .plan-summary .deficit { margin-bottom: var(--space-3); }
}

/* The plan stop by stop (fueling, "Feed zone"): the stops on the route's
   rail, each with its musette, the bag handed up at the feed: what to grab
   as icons (bottles, gels, bars) and words, and the amounts for the leg
   after it as big figures. Between two stops the leg: how long, when, how
   hot. The start carries what to start with, the finish is chequered. */
.stops-title { margin: var(--space-6) 0 0; }
.stops { margin-top: var(--space-4); }
.stop-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0 var(--space-3);
  min-height: var(--mark);
  padding-top: 0.2rem;
}
.stop-at { font-family: var(--display); font-size: 1.5rem; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; }
.stop-card {
  container-type: inline-size;
  display: grid;
  gap: var(--space-3) var(--space-5);
  margin-top: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border: 2px solid var(--line);
  border-top: 3px solid var(--rule);
}
.stop-card p { margin: 0; }
.stop-label {
  margin-bottom: var(--space-1) !important;
  font-family: var(--display);
  font-size: var(--text-sm);
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--link);
}
.take-items { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.take-items li { display: flex; align-items: center; gap: var(--space-3); font-weight: 600; line-height: 1.3; }
.take-icons { display: inline-flex; align-items: flex-end; gap: 3px; min-width: 2rem; color: var(--link); }
.take-icons .icon { width: 1.5rem; height: 1.5rem; vertical-align: 0; }
.take-icons .take-icon { width: 0.875rem; height: 1.75rem; stroke: var(--ink); stroke-width: 1.2; }
.take-icon .cap { fill: var(--ink); }
.take-icon .body { fill: var(--accent); }
.take-icon .body.empty { fill: none; stroke: var(--ink-2); stroke-dasharray: 2 1.5; }
.take-icon.half .body:not(.empty) { stroke: none; }
.stop-adds { margin-top: var(--space-2) !important; font-size: var(--text-sm); color: var(--ink-2); }
.stop-figs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr));
  gap: var(--space-2) var(--space-4);
  margin: 0;
  padding-top: var(--space-3);
  border-top: 1px solid var(--line-strong);
}
.stop-figs dt { font-family: var(--display); font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); }
.stop-figs dt a { color: inherit; text-decoration-style: dotted; }
.stop-figs dd { margin: 0; font-family: var(--display); font-size: 1.625rem; font-weight: 800; line-height: 1.1; white-space: nowrap; font-variant-numeric: tabular-nums; }
.stop-figs dd.sub, .stop-figs dd.flag { font-family: var(--font); font-size: var(--text-xs); font-weight: 400; line-height: 1.4; color: var(--ink-2); white-space: normal; }
.stop-figs dd.flag { color: var(--warn); font-weight: 600; }
.stop-figs .nil dd { color: var(--line-strong); }
@container (min-width: 36rem) {
  .stop-card > .stop-take { grid-column: 1; }
  .stop-card { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
  .stop-figs { padding: 0 0 0 var(--space-4); border-top: 0; border-left: 1px solid var(--line-strong); align-content: start; }
  .stop-cues { grid-column: 1 / -1; }
}
.stop-cues { list-style: none; margin: 0; padding: var(--space-2) 0 0; border-top: 1px solid var(--line); font-size: var(--text-sm); display: grid; gap: var(--space-1); }
.stop-cues .icon { color: var(--link); }
.stop-leg { padding-block: var(--space-4); }
.stop-leg .route-leg-figs a { color: inherit; }
.stops .finish .hint { margin: var(--space-1) 0 0; font-size: var(--text-sm); }

/* Phones: each stop of the plan becomes a card, the stop's name on top,
   its amounts in a grid of labelled figures, then what to take and when. */
@media screen and (max-width: 48rem) {
  .plan-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .plan-table, .plan-table tbody { display: block; }
  .plan-table tr {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr));
    gap: var(--space-2) var(--space-3);
    padding: var(--space-3) 0 var(--space-4);
    border-top: 3px solid var(--rule);
  }
  .plan-table td, .plan-table tr td { padding: 0; border: 0; }
  .plan-table td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-family: var(--display);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-2);
  }
  .plan-table td.place, .plan-table td.take, .plan-table td.covers { grid-column: 1 / -1; }
  .plan-table td.place { order: -1; }
  .plan-table td.place br { display: none; }
  .plan-table td.place small { margin-left: var(--space-2); }
  .plan-table td.leg { order: 1; }
  .plan-table td.take { order: 2; }
  .plan-table td.covers { order: 3; }
  .plan-table td.fluid, .plan-table td.carbs, .plan-table td.sodium, .plan-table td.caffeine {
    font-family: var(--display);
    font-size: 1.375rem;
    font-weight: 800;
    line-height: 1.1;
    white-space: normal;
  }
  .plan-table td small { font-family: var(--font); font-weight: 400; font-size: var(--text-xs); }
  .plan-table td.nil { display: none; }
  .plan-table .finish { padding-bottom: 0; }
}

/* Race weather. Wind colours: red headwind, amber crosswind, green
   tailwind, grey calm; each class sets --rel for lines, bars and keys. */
.rel-head { --rel: var(--bad); }
.rel-cross { --rel: var(--warn); }
.rel-tail { --rel: var(--ok); }
.rel-calm { --rel: var(--line-strong); }
.rel-unknown { --rel: var(--line); }
.planner-body .plan.forecast { position: static; max-height: none; overflow: visible; }
.forecast h3 { margin: var(--space-6) 0 var(--space-2); font-family: var(--display); font-size: 1.5rem; font-weight: 800; text-transform: uppercase; border-top: 3px solid var(--rule); padding-top: var(--space-2); }
.forecast .plate { margin: var(--space-3) 0; }
.wind-share { margin: var(--space-4) 0; }
.wind-share figcaption { font-family: var(--display); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); margin-bottom: var(--space-2); }
.wind-share svg { display: block; width: 100%; height: 14px; }
.wind-share .fill { fill: var(--rel); }
/* Share bars in a panel: one labelled row per bar (pacing's distance and
   time by terrain, weather's wind), the legend under them. */
.panel .wind-share { margin: var(--space-3) 0 0; }
.share-row { display: grid; grid-template-columns: 5.5rem minmax(0, 1fr); gap: var(--space-3); align-items: center; margin: var(--space-2) 0; }
.share-row span { font-family: var(--display); font-size: var(--text-sm); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); }
.share-row svg { display: block; width: 100%; height: 14px; }
.share-row .fill, .start-list .fill { fill: var(--rel); }
/* Start times compared (race weather): each start with its wind as a
   small share bar, yours and the one with least headwind marked. */
.start-list { list-style: none; margin: var(--space-3) 0; padding: 0; }
.start-list li { display: grid; grid-template-columns: 3.25rem minmax(0, 1fr); gap: 0 var(--space-3); align-items: center; padding: var(--space-2) 0; border-bottom: 1px solid var(--line); }
.start-list strong { font-family: var(--display); font-size: 1.25rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.start-list li.current strong { color: var(--link); }
.start-list svg { display: block; width: 100%; height: 10px; }
.start-list small { grid-column: 2; color: var(--ink-2); font-size: var(--text-xs); }
.start-list .badge { margin-left: var(--space-1); }
.legend { list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-5); padding: 0; margin: var(--space-2) 0 0; font-size: var(--text-sm); }
.key { display: inline-block; width: 0.8rem; height: 0.8rem; margin-right: 0.35rem; vertical-align: -0.05em; background: var(--rel); border-radius: var(--radius); }
.wx-map, .wx-profile { margin: 0; }
.wx-map > svg { display: block; width: 100%; height: auto; background: var(--surface); border: 3px solid var(--rule); }
.wx-map .casing { fill: none; stroke: var(--bg); stroke-width: 9; stroke-linejoin: round; stroke-linecap: round; }
.wx-map .road { fill: none; stroke: var(--rel); stroke-width: 5; stroke-linejoin: round; stroke-linecap: round; }
.wx-map .arrow path { fill: var(--ink); stroke: var(--bg); stroke-width: 1.5; }
.wx-map .mark circle { fill: var(--bg); stroke: var(--ink); stroke-width: 1.5; }
.wx-map .mark text { font-family: var(--display); font-weight: 700; font-size: 13px; fill: var(--ink); paint-order: stroke; stroke: var(--surface); stroke-width: 3px; }
.wx-map .start { fill: var(--accent); stroke: var(--ink); stroke-width: 2; }
.wx-map .finish { fill: url(#chequer); stroke: var(--ink); stroke-width: 1.5; }
.wx-map .chq-a { fill: #fff; }
.wx-map .chq-b { fill: #111; }
.wx-map figcaption, .wx-profile figcaption { margin-top: var(--space-2); font-size: var(--text-sm); }
.wx-profile svg { display: block; width: 100%; min-width: 34rem; height: auto; }
.wx-profile .elev { fill: color-mix(in srgb, var(--ink) 12%, transparent); }
.wx-profile .temp { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linejoin: round; }
.wx-profile .temp-dot { fill: var(--accent); }
.wx-profile .wx-bar { fill: var(--rel); }
.wx-profile .wx-bar.rain { fill: var(--ink-2); }
.wx-profile .dark { fill: color-mix(in srgb, var(--ink) 9%, transparent); }
.wx-profile .grid { stroke: var(--line); stroke-width: 1; }
.wx-profile .axis { stroke: var(--rule); stroke-width: 2; }
.wx-profile .tick { fill: var(--ink-2); font-family: var(--mono); font-size: 11px; }
.wx-profile .temp-tick { fill: var(--link); }
.wx-profile .label { fill: var(--ink-2); font-family: var(--display); font-weight: 700; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; }
.checkpoints td, .checkpoints th, .starts td, .starts th { white-space: nowrap; }
.checkpoints small, .starts small { color: var(--ink-2); }
.checkpoints tr.dark th, .checkpoints tr.dark td { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.wind-arrow { width: 1.1rem; height: 1.1rem; vertical-align: -0.2em; margin-right: 0.2rem; }
.wind-arrow path { fill: var(--ink); }
.starts tr.current th, .starts tr.current td { font-weight: 700; }
.badge.best { background: var(--accent); color: var(--accent-ink); }
.course-list { list-style: none; padding: 0; margin: var(--space-2) 0 0; }
.course-list li { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--space-2); padding: var(--space-2) 0; border-bottom: 1px solid var(--line); }
.course-list a { font-weight: 600; }
.course-list a[aria-current="true"] { color: var(--ink); font-family: var(--display); font-size: 1.25rem; font-weight: 800; text-transform: uppercase; text-decoration: none; }
.course-list small { display: block; color: var(--ink-2); }
.planner-form input[type="file"] { max-width: 100%; }

/* Race pacing: power bars under the profile, orange on climbs. */
.pacing .plate { margin: var(--space-5) 0; }
.pacing-chart .power-bar { fill: var(--ink-2); }
.pacing-chart .power-bar.climb { fill: var(--accent); }
.pacing-chart .power-bar.descent { fill: var(--line-strong); }
.pacing-chart .target { stroke: var(--ink); stroke-width: 1.5; stroke-dasharray: 5 4; }
.pacing-sections td { white-space: nowrap; }
.pacing-sections tr.climb td:first-child strong { color: var(--link); }
/* Terrain colours, as the power bars: orange climbs, grey flats, light
   descents; each sets --rel for the time split's bars and keys. */
.terrain-climb { --rel: var(--accent); }
.terrain-flat { --rel: var(--ink-2); }
.terrain-descent { --rel: var(--line-strong); }
.credit { margin-top: var(--space-5); }

/* Race catalog: the course's profile with each feed station flagged, as
   the roadbook marks the ravitos. */
.race-profile { margin: var(--space-5) 0; }
.race-profile svg { display: block; width: 100%; min-width: 34rem; height: auto; }
.race-profile .elev { fill: color-mix(in srgb, var(--ink) 14%, transparent); stroke: var(--ink); stroke-width: 1.5; stroke-linejoin: round; }
.race-profile .axis { stroke: var(--rule); stroke-width: 2; }
.race-profile .tick { fill: var(--ink-2); font-family: var(--mono); font-size: 11px; }
.race-profile .feed-mark line { stroke: var(--accent); stroke-width: 2; }
.race-profile .feed-mark rect { fill: var(--accent); }
.race-profile .feed-mark text { fill: var(--accent-ink); font-family: var(--display); font-weight: 800; font-size: 11px; }
.race-profile figcaption { margin-top: var(--space-2); font-size: var(--text-sm); }
.race-profile .climb-band { fill: color-mix(in srgb, var(--accent) 30%, transparent); }
.race-profile .climb-n { fill: var(--ink); font-family: var(--display); font-weight: 800; font-size: 11px; }

/* The route map over tiles (route-map island). It hides the drawing it
   stands for once it is up; print keeps the drawing. The race bib's frame,
   chunky tools in the display face, the road drawn as on the drawing. */
.wx-map.has-live-map > svg { display: none; }
.live-map { position: relative; border: 3px solid var(--rule); background: var(--surface); }
.live-map-canvas { height: clamp(320px, 62vh, 560px); background: var(--surface); font: inherit; }
.live-map.is-expanded { position: fixed; inset: 0; z-index: 1000; border: 0; }
.live-map:fullscreen { border: 0; }
.live-map.is-expanded .live-map-canvas, .live-map:fullscreen .live-map-canvas { height: 100%; }
.live-map:fullscreen { width: 100%; height: 100%; }
html.lm-lock, html.lm-lock body { overflow: hidden; }
@media (prefers-color-scheme: dark) {
  .live-map[data-layer="map"] .leaflet-tile-pane { filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.88) saturate(0.6); }
}

.live-map-tools { position: absolute; top: var(--space-2); right: var(--space-2); z-index: 1000; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); max-width: calc(100% - 4rem); pointer-events: none; }
.live-map-tools > * { pointer-events: auto; }
.lm-layers, .lm-buttons { display: flex; border: 2px solid var(--rule); background: var(--bg); box-shadow: 2px 2px 0 var(--rule); }
.live-map-tools button { display: inline-flex; align-items: center; gap: 0.35rem; min-height: 2.25rem; margin: 0; padding: 0 0.65rem; border: 0; border-radius: 0; background: var(--bg); color: var(--ink); font-family: var(--display); font-weight: 700; font-size: 0.95rem; letter-spacing: 0.06em; text-transform: uppercase; cursor: pointer; }
.live-map-tools button + button { border-left: 2px solid var(--rule); }
.live-map-tools button:hover { background: var(--surface); }
.live-map-tools button[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); }
.live-map-tools button:focus-visible { outline: 3px solid var(--link); outline-offset: -3px; }
.live-map-tools svg { fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
@media (max-width: 40rem) {
  .lm-flow-toggle span { display: none; }
  .live-map-tools button { padding: 0 0.5rem; font-size: 0.85rem; }
}
.live-map-hint { position: absolute; inset: 0; z-index: 900; display: grid; place-items: center; padding: var(--space-4); background: color-mix(in srgb, #000 45%, transparent); color: #fff; font-family: var(--display); font-weight: 700; font-size: 1.25rem; letter-spacing: 0.04em; text-align: center; pointer-events: none; animation: lm-fade 0.2s ease-out; }
@keyframes lm-fade { from { opacity: 0; } }

/* Leaflet's own controls, in the bib's frame. */
.live-map .leaflet-container { font-family: inherit; background: var(--surface); }
.live-map .leaflet-container .leaflet-bar { border: 2px solid var(--rule); border-radius: 0; box-shadow: 2px 2px 0 var(--rule); }
.live-map .leaflet-container .leaflet-bar a { width: 2.25rem; height: 2.25rem; line-height: 2.1rem; border-radius: 0; background: var(--bg); color: var(--ink); border-bottom: 2px solid var(--rule); font-family: var(--display); font-weight: 800; }
.live-map .leaflet-container .leaflet-bar a:last-child { border-bottom: 0; }
.live-map .leaflet-container .leaflet-bar a:hover { background: var(--surface); }
.live-map .leaflet-container .leaflet-bar a.leaflet-disabled { color: var(--ink-2); background: var(--bg); }
.live-map .leaflet-container .leaflet-control-attribution { background: color-mix(in srgb, var(--bg) 80%, transparent); color: var(--ink-2); font-size: 0.7rem; }
.live-map .leaflet-container .leaflet-control-attribution a { color: var(--link); }
.live-map .leaflet-popup-content-wrapper { border: 2px solid var(--rule); border-radius: 0; background: var(--bg); color: var(--ink); box-shadow: 3px 3px 0 var(--rule); }
.live-map .leaflet-popup-tip { background: var(--rule); box-shadow: none; }
.live-map .leaflet-popup-content { margin: 0.6rem 1.75rem 0.6rem 0.75rem; }
.live-map .leaflet-container a.leaflet-popup-close-button { color: var(--ink-2); }
.live-map .lm-popup { margin: 0; font-size: var(--text-sm); line-height: 1.35; }

/* The road, as on the drawing. */
.lm-casing { fill: none; stroke: var(--bg); stroke-width: 10; stroke-linejoin: round; stroke-linecap: round; stroke-opacity: 0.9; }
.lm-road { fill: none; stroke: var(--rel, var(--ink-2)); stroke-width: 5; stroke-linejoin: round; stroke-linecap: round; stroke-opacity: 1; }
.lm-road.base { --rel: var(--ink-2); stroke-width: 4; }
.lm-road.descent { --rel: var(--ink); stroke-width: 4; stroke-dasharray: 2 7; }
.lm-road.climb { --rel: var(--accent); stroke-width: 6; }
.lm-lit { fill: none; stroke: var(--rel); stroke-width: 12; stroke-opacity: 0.45; stroke-linecap: round; stroke-linejoin: round; animation: lm-fade 0.25s ease-out; }

.lm-mark { display: block; }
.lm-mark i { position: absolute; inset: 0; border: 1.5px solid var(--ink); border-radius: 50%; background: var(--bg); }
.lm-mark b { position: absolute; left: 10px; bottom: 6px; font-family: var(--display); font-weight: 700; font-size: 13px; color: var(--ink); white-space: nowrap; text-shadow: 0 0 2px var(--bg), 0 0 2px var(--bg), 0 0 3px var(--bg); }
.lm-pin text { font-family: var(--display); font-weight: 800; font-size: 11px; fill: var(--ink); }
.lm-pin.feed circle { fill: var(--accent); stroke: var(--ink); stroke-width: 1.5; }
.lm-pin.feed text { fill: var(--accent-ink); }
.lm-pin.top rect { fill: var(--bg); stroke: var(--ink); stroke-width: 2; }
.lm-pin.warn path { fill: var(--warn); stroke: var(--ink); stroke-width: 1.5; stroke-linejoin: round; }
.lm-end.start circle { fill: var(--accent); stroke: var(--ink); stroke-width: 2; }
.lm-end.finish rect { fill: #111; }
.lm-end.finish rect.flag { fill: #fff; }
.lm-end.finish rect.edge { fill: none; stroke: var(--ink); stroke-width: 1.5; }
.lm-pin, .lm-end, .lm-wind { cursor: pointer; }

/* The wind: an arrow that grows with it, its dashed tail out to the gusts. */
.lm-wind svg { overflow: visible; filter: drop-shadow(0 1px 1.5px color-mix(in srgb, #000 35%, transparent)); transition: transform 0.15s ease-out; }
.lm-wind:hover svg, .lm-wind:focus-visible svg { transform: scale(1.12); }
.lm-wind path { fill: var(--ink); stroke: var(--bg); stroke-width: 1.5; stroke-linejoin: round; }
.lm-wind .gust { stroke: var(--ink); stroke-opacity: 0.55; stroke-dasharray: 1 4; stroke-linecap: round; }
.live-map[data-layer="satellite"] .lm-wind path { fill: #fff; stroke: #111; }
.live-map[data-layer="satellite"] .lm-wind .gust { stroke: #fff; stroke-opacity: 0.8; }

/* The moving wind's canvas, between the tiles and the road. */
.leaflet-pane.leaflet-flow-pane { z-index: 350; pointer-events: none; }
.lm-flow { position: absolute; left: 0; top: 0; transition: opacity 0.3s; }
.lm-flow.is-moving { opacity: 0; transition: none; }

@media print {
  .wx-map.has-live-map > svg { display: block; }
  .live-map { display: none; }
}

/* Course tab: the form, and the roadbook beside it on the race tabs' layout. */
.sheet h2 { margin-top: 0; }
.sheet h3 { margin: var(--space-5) 0 var(--space-2); }
.sheet .race-profile { margin: var(--space-4) 0 0; }
.sheet .race-profile svg { min-width: 0; }
.sheet-map .road.base { fill: none; stroke: var(--ink-2); stroke-width: 3; stroke-linejoin: round; stroke-linecap: round; }
.sheet-map .road.descent { stroke: var(--ink); stroke-width: 4; stroke-dasharray: 2 6; }
.sheet-map .road.climb { stroke: var(--accent); stroke-width: 6; }
.sheet-map .pin text { font-family: var(--display); font-weight: 800; font-size: 11px; }
.sheet-map .pin.feed circle { fill: var(--accent); stroke: var(--ink); stroke-width: 1.5; }
.sheet-map .pin.feed text { fill: var(--accent-ink); }
.sheet-map .pin.top rect { fill: var(--bg); stroke: var(--ink); stroke-width: 2; }
.sheet-map .pin.top text { fill: var(--ink); }
.sheet-map .pin.warn path { fill: var(--warn); stroke: var(--ink); stroke-width: 1.5; stroke-linejoin: round; }
.sheet-map .pin.warn text { fill: var(--ink); }
.sheet-legend .key-climb { --rel: var(--accent); }
.sheet-legend .key-descent { --rel: var(--ink); }
.sheet-legend .key-feed { --rel: var(--accent); border-radius: 50%; }
.sheet-legend .key-warn { --rel: var(--warn); }
.sheet-climbs th, .sheet-climbs td { white-space: nowrap; }
.sheet-climbs tr.hard td, .sheet-climbs tr.hard th { font-weight: 700; }
.hazards { list-style: none; padding: 0; margin: 0; }
.hazard { padding: var(--space-2) 0 var(--space-2) var(--space-3); border-left: 4px solid var(--line-strong); margin-bottom: var(--space-2); }
.hazard.hairpin { border-left-color: var(--warn); }
.hazard-at { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink-2); margin-right: var(--space-2); }

/* The route (race catalog, course tab): the course cut at its feeds, as a
   roadbook lists the ravitos. Stops sit on a dashed rail, the road; between
   two stops the stretch with its distance, climbing and a bar for its
   length against the longest. Feeds are numbered orange flags, the start a
   black block, the finish chequered. The fueling plan's stops (.stops) and
   the feed editor ride the same rail. */
.route, .stops {
  --mark: 2.25rem;
  position: relative;
  list-style: none;
  margin: var(--space-4) 0 var(--space-5);
  padding: 0;
}
.route { max-width: 40rem; }
.route::before, .stops::before {
  content: "";
  position: absolute;
  top: calc(var(--mark) / 2);
  bottom: calc(var(--mark) / 2);
  left: calc(var(--mark) / 2 - 1.5px);
  border-left: 3px dashed var(--line-strong);
}
.route > li, .stops > li { position: relative; padding-left: calc(var(--mark) + var(--space-4)); }
.route-mark {
  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  place-items: center;
  width: var(--mark);
  height: var(--mark);
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--display);
  font-size: 1.25rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  border-radius: var(--radius);
}
.start > .route-mark { background: var(--rule); }
.start > .route-mark::after { content: ""; width: 0.5rem; height: 0.5rem; background: var(--bg); }
.finish > .route-mark {
  border: 2px solid var(--rule);
  background: repeating-conic-gradient(var(--rule) 0 25%, var(--bg) 0 50%) 0 0 / 0.5rem 0.5rem;
}
.route-stop {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0 var(--space-3);
  min-height: var(--mark);
  padding-top: 0.2rem;
}
.route-name {
  font-family: var(--display);
  font-size: 1.375rem;
  font-weight: 800;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.route-at {
  font-family: var(--display);
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.route-leg { padding-block: var(--space-3) var(--space-4); }
.route-leg-figs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-3);
  font-size: var(--text-sm);
  color: var(--ink-2);
}
.route-leg-figs strong { font-family: var(--display); font-size: 1.125rem; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.route-climb { white-space: nowrap; font-variant-numeric: tabular-nums; }
.route-climb .icon { color: var(--ink-2); }
.route-leg-bar { display: block; width: 100%; max-width: 24rem; height: 0.375rem; margin-top: var(--space-2); }
.route-leg-bar rect { fill: var(--line); }
.route-leg-bar .fill { fill: var(--line-strong); }
.route-leg.longest .fill { fill: var(--accent); }
.route-leg .badge { font-size: var(--text-xs); background: var(--accent); color: var(--accent-ink); vertical-align: 0; }

/* The feed editor (course tab, race form): the route with a name and a
   distance field at each feed, on the profile, where a click drops a flag
   and a flag drags along the road. The textarea is the editor without
   JavaScript. */
.planner-form textarea { display: block; width: 100%; margin-top: var(--space-1); padding: 0.4rem 0.6rem; font: inherit; border: 2px solid var(--line-strong); border-radius: var(--radius); background: var(--bg); color: var(--ink); }
.feed-editor .fe-profile { margin: var(--space-3) 0 var(--space-2); }
.fe-profile svg { cursor: copy; touch-action: pan-x pan-y; user-select: none; -webkit-user-select: none; }
.fe-profile svg.dragging, .fe-profile svg.dragging * { cursor: grabbing; }
.fe-hit, .race-profile .fe-flag .fe-grab { fill: transparent; }
.fe-ghost line { stroke: var(--ink-2); stroke-width: 1.5; stroke-dasharray: 3 3; }
.fe-ghost circle { fill: var(--accent); }
.fe-ghost text { fill: var(--ink); font-family: var(--display); font-weight: 700; font-size: 13px; }
.fe-flag { cursor: grab; touch-action: none; outline: none; }
.fe-flag circle { fill: var(--accent); stroke: var(--bg); stroke-width: 1.5; }
.fe-flag.active line, .fe-flag.held line { stroke-width: 3; }
.fe-flag:focus-visible rect:not(.fe-grab), .fe-flag.active rect:not(.fe-grab) { stroke: var(--ink); stroke-width: 2; }
.feed-editor .route { max-width: none; margin-top: var(--space-3); }
.fe-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 7.5rem auto;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  padding-top: 0;
}
.planner-form .feed-editor .fe-row input:not([type="radio"]):not([type="checkbox"]) { display: block; width: 100%; max-width: none; margin: 0; }
.planner-form .feed-editor .fe-name { font-family: var(--display); font-size: 1.25rem; font-weight: 700; letter-spacing: 0.02em; }
.feed-editor .fe-name::placeholder { font-family: var(--font); font-size: var(--text-md); font-weight: 400; letter-spacing: 0; }
.fe-km { position: relative; display: block; }
.planner-form .feed-editor .fe-km input { padding-right: 2.4rem; text-align: right; font-family: var(--display); font-size: 1.125rem; font-weight: 700; }
.fe-km span { position: absolute; right: 0.6rem; top: 50%; transform: translateY(-50%); color: var(--ink-2); font-size: var(--text-sm); pointer-events: none; }
.fe-remove { width: 2.75rem; padding: 0; }
.fe-row .route-mark { top: 0.25rem; }
.fe-row.active .route-mark { outline: 3px solid var(--rule); outline-offset: 2px; }
.feed-editor input[aria-invalid] { border-color: var(--bad); }
.fe-problem { grid-column: 1 / -1; color: var(--bad); font-weight: 600; }
.fe-empty { margin: var(--space-3) 0 0; padding: var(--space-2) var(--space-4); border: 2px dashed var(--line-strong); color: var(--ink-2); }
.fe-actions { margin-top: 0; }
.fe-undo { color: var(--ink-2); font-size: var(--text-sm); }
button.link { display: inline; min-height: 0; padding: 0; border: 0; font: inherit; letter-spacing: 0; text-transform: none; color: var(--link); text-decoration: underline; }
button.link:hover { background: none; color: var(--ink); }
.race-profile.fe-profile svg { min-width: 20rem; }
@media (max-width: 30rem) {
  .fe-row { grid-template-columns: 8.5rem minmax(0, 1fr) auto; }
  .planner-form .feed-editor .fe-name { grid-column: 1 / -1; }
  .fe-remove { grid-column: 3; }
}
.race-table th a { font-weight: 600; }
.row-actions { white-space: nowrap; }
.row-actions form { display: inline-block; margin-right: var(--space-2); }

/* Method page */
.method-table tr:target { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.method-table tbody th { font-weight: 600; }
.refs a { margin-left: 0.2rem; text-decoration: none; font-family: var(--mono); font-size: var(--text-xs); }
.references { padding-left: 1.4rem; }
.references li { margin-bottom: var(--space-4); }
.references li:target, .kb-references li:target { outline: 3px solid var(--accent); outline-offset: 0.3rem; }
.references p { margin: var(--space-1) 0; }

/* Knowledge base */
.kb-crumbs { margin-top: var(--space-6); }
.kb-crumbs a { color: inherit; }
/* "Feed zone ahead": the call to a tool at the end of an article. */
.kb-cta {
  background: var(--band);
  color: var(--band-ink);
  border-top: 6px solid var(--accent);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5) var(--space-5);
  margin: var(--space-7) 0;
}
.kb-cta .eyebrow { margin: 0 0 var(--space-1); color: var(--band-accent); }
.kb-cta p { margin: var(--space-2) 0; font-size: var(--text-lg); }
.kb-references ol { padding-left: 1.4rem; font-size: var(--text-sm); }
.kb-references li { margin-bottom: var(--space-2); }

/* Admin */
.admin-filters { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); align-items: center; margin: var(--space-4) 0; font-size: var(--text-sm); }
.segmented { display: inline-flex; flex-wrap: wrap; }
.segmented a {
  padding: 0.3rem 0.8rem;
  border: 2px solid var(--ink);
  margin-left: -2px;
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
}
.segmented a:first-child { margin-left: 0; }
.segmented a[aria-current="true"] { background: var(--ink); color: var(--bg); }
.toggle { color: var(--ink-2); }
.toggle::before { content: "☐ "; }
.toggle[aria-checked="true"]::before { content: "☑ "; }
.badge.filter { text-decoration: none; text-transform: none; font-family: var(--font); font-size: var(--text-xs); letter-spacing: 0; padding: 0.1rem 0.45rem; }
.chart { margin: var(--space-3) 0 0; }
.chart .table-scroll svg { display: block; width: 100%; min-width: 34rem; height: auto; }
.chart .bar { fill: var(--accent); }
.chart .hit { fill: transparent; }
.chart .day:hover .hit { fill: color-mix(in srgb, var(--ink) 6%, transparent); }
.chart .grid { stroke: var(--line); stroke-width: 1; }
.chart .axis { stroke: var(--rule); stroke-width: 2; }
.chart .tick { fill: var(--ink-2); font-family: var(--mono); font-size: 11px; }
.chart figcaption { margin-top: var(--space-2); font-size: var(--text-sm); }
.admin-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr)); gap: 0 var(--space-6); }
.admin-grid > section { min-width: 0; }
.breakdown td:first-child { word-break: break-all; }
.share { display: block; width: 100%; height: 4px; margin-top: 0.3rem; }
.share rect { fill: var(--accent); }
.data-table .num, .data-table th.num { text-align: right; }
.data-table td.num + td, .data-table th.num + th { padding-left: var(--space-3); }
.requests { font-size: var(--text-xs); }
.requests td { white-space: nowrap; }
.requests td.referrer { white-space: normal; word-break: break-all; min-width: 10rem; }
.method { font-family: var(--mono); color: var(--ink-2); }

/* Calculators: the form beside the head unit, the working under them. */
.calculator .eyebrow a { color: inherit; text-decoration: none; }
.calculator .eyebrow a:hover { text-decoration: underline; }
.calc-result .plate { margin: var(--space-4) 0 var(--space-5); }
.calc-result .plate dl { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }
.verdict { font-size: var(--text-lg); font-weight: 500; }
.calc-result h3, .calc-how h3 { margin: var(--space-6) 0 var(--space-2); font-family: var(--display); font-size: 1.5rem; font-weight: 800; text-transform: uppercase; border-top: 3px solid var(--rule); padding-top: var(--space-2); }
.calc-table caption { text-align: left; font-size: var(--text-sm); color: var(--ink-2); padding-bottom: var(--space-2); }
.calc-table td, .calc-table th { white-space: nowrap; }
.calc-table tr.current th, .calc-table tr.current td { font-weight: 700; background: color-mix(in srgb, var(--accent) 12%, transparent); }
.moves dd { font-size: 1.75rem; }
.watt-split { margin: var(--space-5) 0; }
.watt-split figcaption { font-family: var(--display); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); margin-bottom: var(--space-2); }
.watt-split svg { display: block; width: 100%; height: 18px; }
.watt-split rect, .watt-split .key { fill: var(--part); background: var(--part); }
.part-aero { --part: var(--accent); }
.part-rolling { --part: var(--ink); }
.part-gravity { --part: var(--ink-2); }
.part-drivetrain { --part: var(--line-strong); }
.part-food { --part: var(--ink); }
.part-muscle { --part: var(--accent); }
.part-liver { --part: var(--line-strong); }
.part-short { --part: var(--bad); }
.calc-more { margin-top: var(--space-4); }
.calc-more summary { cursor: pointer; font-family: var(--display); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
.planner-form .field-hint { display: block; margin-top: var(--space-1); font-weight: 400; }
.working { padding-left: 1.4rem; }
.working li { margin-bottom: var(--space-2); font-variant-numeric: tabular-nums; }

/* ---------- Print: the fueling plan on one page ---------- */
@media print {
  @page { size: A4; margin: 12mm; }
  :root { --ink: #000; --ink-2: #333; --line: #bbb; --line-strong: #888; --rule: #000; --surface: #fff; --bg: #fff; }
  body { font-size: 10pt; line-height: 1.35; color: #000; background: #fff; display: block; min-height: 0; }
  .plan > p, .pack { margin: 0.3rem 0; }
  .feed-board dt { font-size: 7pt; }
  .site-header, .site-footer, .planner-head, .rider-head, .planner-form, .plan > h2 { display: none; }
  main, main.wide { max-width: none; padding: 0; }
  .planner-body { display: block; }
  .planner-body .plan { position: static; max-height: none; overflow: visible; }
  .print-only { display: block; }
  .print-head p { margin: 0 0 0.4rem; }
  .table-scroll { overflow: visible; }
  .plan-table { font-size: 9pt; }
  .plan-table th, .plan-table td { padding: 0.25rem 0.4rem 0.25rem 0; }
  .plan-table small { font-size: 8pt; }
  .plan-table td:first-child strong { font-size: 10pt; }
  .plan-table td:not(:last-child) small { white-space: nowrap; }
  .plan .places, .plan > .hint:last-child { display: none; }
  .plan > .notice.warn { font-size: 8.5pt; }
  .plan-table tr { break-inside: avoid; }
  .stops-title, .stops-title + .hint, .stops::before, .route-mark, .stop-cues { display: none; }
  .stops { margin: 0.3rem 0; }
  .stops > li { padding-left: 0; break-inside: avoid; }
  .stop-head { min-height: 0; padding: 0; }
  .route-name, .stop-at { font-size: 11pt; }
  .stop-card { grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); gap: 0 0.8rem; margin-top: 0.1rem; padding: 0.2rem 0.5rem; background: #fff; border-width: 1px; }
  .stop-label, .take-icons { display: none; }
  .take-items { gap: 0; }
  .stop-adds { margin: 0 !important; font-size: 8pt; }
  .stop-figs { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0 0.4rem; padding: 0; border: 0; }
  .stop-figs dt { font-size: 6.5pt; }
  .stop-figs dd { font-size: 11pt; }
  .stop-leg { padding-block: 0.15rem; font-size: 8.5pt; }
  .feed-board { margin: 0.4rem 0; border-width: 1.5px; }
  .feed-board::before, .feed-board::after, .feed-board dl::after, .feed-board-head { display: none; }
  .feed-board dl { padding: 0.2rem 0.8rem; }
  .feed-board dl > div { padding: 0.1rem 0.6rem 0.1rem 0; }
  .feed-board dd { font-size: 14pt; }
  .deficit { margin: 0.4rem 0; padding: 0.2rem 0.6rem; background: #fff; border-left-width: 2px; }
  .deficit-gauge, .deficit-scale { display: none; }
  .race-body .plan { border: 0; padding: 0; }
  .notice { margin: 0.4rem 0; padding: 0.2rem 0.6rem; }
  section { margin-top: 0; }
  a { color: #000; }
}

/* ---------- Where a number came from ---------- */
/* A source tag sits under or after a number: tested (a dated test, solid
   green), entered (by the rider, outlined) or estimated (from research,
   dashed). The number stays the hero; the tag says how far to trust it. */
.source-tag {
  display: inline-block;
  margin-top: 0.15rem;
  padding: 0 0.4rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--ink-2);
  white-space: normal;
}
.source-tag a { color: inherit; }
.source-tag.tested { border-color: var(--ok); color: var(--ink); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.source-tag.estimated { border-style: dashed; }
.sourced { display: grid; gap: var(--space-2); margin: var(--space-4) 0; }
.sourced > div { display: grid; grid-template-columns: 5.5rem 1fr; gap: var(--space-3); align-items: baseline; }
.sourced dt { font-family: var(--display); font-weight: 700; text-transform: uppercase; }
.sourced dd { margin: 0; font-variant-numeric: tabular-nums; }

/* The bidon (sweat tests, "Bidon"): a white board with an orange head
   band, what the rider sweats out in an hour. Fluid and sodium stand side
   by side, each its figure over a pour of pips (drops of fluid, grains of
   salt) and a key saying what one is, above a strip of three figures. It
   stays white in both themes, like the bib. */
.bidon, .engine {
  --plate: var(--bib);
  --plate-ink: var(--bib-ink);
  --plate-ink-2: var(--bib-ink-2);
  --plate-accent: #c2410c;
  --plate-line: #d4d4d4;
  margin: var(--space-4) 0;
  padding: 0;
  border: 3px solid var(--bib-ink);
}
.bidon { max-width: none; }
.bidon .plate-head, .engine .plate-head {
  margin: 0;
  padding: var(--space-2) var(--space-5);
  font-weight: 800;
}
.engine .plate-head {
  background: var(--band);
  color: var(--band-ink);
  border-bottom: 4px solid var(--accent);
  letter-spacing: 0.12em;
}
.engine .plate-head span + span { color: var(--band-accent); }
.bidon .plate-head {
  flex-wrap: wrap;
  background: var(--accent);
  color: var(--accent-ink);
  border-bottom: 3px solid var(--bib-ink);
  font-size: clamp(0.875rem, 3.4cqi, 1.1875rem);
  letter-spacing: 0.08em;
}
.bidon .plate-head span + span { font-weight: 700; }
.bidon-loss { min-width: 0; padding: var(--space-4) var(--space-5); }
.bidon-loss + .bidon-loss { border-top: 3px solid var(--bib-ink); }
.bidon-what {
  margin: 0;
  font-family: var(--display);
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--plate-ink-2);
}
.bidon .plate-number { margin: 0 0 var(--space-3); text-align: left; font-size: clamp(3.5rem, 22cqi, 6rem); line-height: 0.9; }
.bidon .plate-number span { font-size: 0.375em; color: var(--plate-accent); }
.bidon-pips { display: block; width: 100%; max-width: 20rem; height: auto; }
.bidon-pips path, .bidon-pips rect { stroke: var(--bib-ink); stroke-width: 2.5; }
.bidon-pips.drops path { fill: var(--accent); }
.bidon-pips.grains rect { fill: #ffffff; }
.bidon-pips.grains path { fill: none; stroke-width: 1.5; }
.bidon-pips.drops .empty, .bidon-pips.grains .empty rect { fill: none; stroke: #a3a3a3; stroke-width: 2; stroke-dasharray: 4 3; }
.bidon-key { margin: var(--space-2) 0 0; font-size: 0.9375rem; color: var(--plate-ink-2); }
.bidon dl > div { padding-bottom: var(--space-3); }
.bidon dd small { font-size: 0.6em; }
.engine-strip {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0 var(--space-4);
  margin: 0;
  padding: var(--space-2) var(--space-5);
  background: var(--accent);
  color: var(--accent-ink);
  border-top: 3px solid var(--bib-ink);
  font-family: var(--display);
  font-size: clamp(1rem, 3.4cqi, 1.25rem);
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
@container (min-width: 34rem) {
  .bidon-losses { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bidon-loss + .bidon-loss { border-top: 0; border-left: 3px solid var(--bib-ink); }
  .bidon .plate-number { font-size: clamp(3.5rem, 12.6cqi, 6rem); }
}

/* The sweat tests' chart: rate against temperature. */
.sweat-chart svg { width: 100%; height: auto; }
.sweat-chart .grid { stroke: var(--line); }
.sweat-chart .tick { fill: var(--ink-2); font-size: 12px; }
.sweat-chart .curve { fill: none; stroke: var(--accent); stroke-width: 3; }
.sweat-chart .point { fill: var(--ink); }
.sweat-chart .excluded { fill: none; stroke: var(--ink-2); stroke-width: 2; }
.protocol ol { padding-left: 1.2rem; }

/* Ride tests: the road's elevation against the virtual elevation. */
.ride-chart svg { width: 100%; height: auto; }
.ride-chart .grid { stroke: var(--line); }
.ride-chart .tick { fill: var(--ink-2); font-size: 12px; }
.ride-chart .road { fill: none; stroke: var(--ink-2); stroke-width: 2; }
.ride-chart .ve { fill: none; stroke: var(--accent); stroke-width: 2; }

/* The engine (fitness tests, "Prologue"): the bidon's white board with the
   threshold as its figure, and under it where the rider's energy comes
   from at each power, fat below and carbohydrate above, FatMax and the
   threshold dashed. The strip says what the threshold burns. */
.engine .plate-body { padding: var(--space-4) var(--space-5) var(--space-2); }
.engine-fuel { padding: var(--space-2) var(--space-5) var(--space-4); }
.engine-fuel-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0 var(--space-3);
  margin: 0 0 var(--space-1);
  font-family: var(--display);
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--plate-ink-2);
}
.engine-fuel svg { display: block; width: 100%; height: auto; }
.engine-fuel .carb, .engine .key.carb { fill: var(--accent); --rel: var(--accent); }
.engine-fuel .fat, .engine .key.fat { fill: #111111; --rel: #111111; }
.engine-fuel .mark-gap { stroke: #ffffff; stroke-width: 4; }
.engine-fuel .mark { stroke: #111111; stroke-width: 2; stroke-dasharray: 5 4; }
.engine-fuel .mark-label { fill: #111111; font-family: var(--display); font-size: 18px; font-weight: 800; letter-spacing: 1px; text-transform: uppercase; }
.engine-fuel .tick { fill: #525252; font-family: var(--display); font-size: 17px; font-weight: 700; }
.engine .legend { color: var(--plate-ink); }

/* ---------- Roadbook ---------- */
/* A race's tools as numbered stage cards (.cards), in the order their
   numbers flow. Each card has its status, its live number and where it
   comes from; stages not built yet are dimmed with "next stage". */
.cards.roadbook .card { display: flex; flex-direction: column; gap: var(--space-1); flex-basis: 14rem; }
.cards.roadbook .card::before { font-size: 3rem; }
.cards.roadbook .card h3 { margin-top: 0; }
.stage-status { order: -1; margin: 0 0 var(--space-2); }
.stage-value { font-family: var(--display); font-size: var(--text-2xl); font-weight: 800; line-height: 1; color: var(--ink) !important; }
.stage-value small { font-size: var(--text-md); font-weight: 600; color: var(--ink-2); }
.stage-uses { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.06em; }
.stage-link { margin-top: auto !important; padding-top: var(--space-2); font-weight: 600; }
.card.stage.coming { background: var(--surface); }
.card.stage.coming h3, .card.stage.coming::before { color: var(--line-strong); }
.badge.status-done { background: var(--ok); color: #fff; }
.badge.status-estimated { background: var(--bg); color: var(--ink); outline: 1px dashed var(--ink); }
.badge.status-ready { background: var(--accent); color: var(--accent-ink); }
.badge.status-waiting, .badge.status-coming { background: var(--line); color: var(--ink-2); }
/* A race's priority, A to C, as a square plate. */
.priority { display: inline-block; min-width: 1.6em; padding: 0 0.3em; border: 2px solid var(--ink); border-radius: var(--radius); font-family: var(--display); font-weight: 800; text-align: center; line-height: 1.3; vertical-align: 0.1em; }
h1 .priority { font-size: 0.6em; vertical-align: 0.3em; }
.priority-A { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.priority-C { border-style: dashed; color: var(--ink-2); }
.race-table tr.focus th { font-weight: 800; }
.roadbook-form { max-width: 40rem; }
.roadbook-form:has(.feed-editor) { max-width: var(--measure); }

/* A race's head on the page: its name and day, on every tab. The tabs are
   not here but in the header (.thing-bar), so nothing above them moves. */
.race-head h1 { margin-bottom: var(--space-1); }
.race-head .lead { margin-bottom: var(--space-5); }
.race-head.example .eyebrow { margin-top: var(--space-6); margin-bottom: var(--space-3); }

/* A race's (or the rider's) row in the header, in the subnav's place: the
   thing's name, then its tabs, which look like the subnav and scroll
   sideways on a phone (race-roadbook.md §2b, navigation.md §3). The name
   stays in view however far down the page goes. */
.thing-bar .bar {
  display: flex;
  align-items: stretch;
  gap: var(--space-4);
  height: var(--subnav-h);
  padding-top: 0;
  padding-bottom: 0;
}
.thing-name {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: none;
  max-width: var(--name-w, 40%);
  padding-right: var(--space-4);
  border-right: 1px solid var(--line);
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.0625rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.thing-title { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.thing-label { color: var(--ink-2); font-weight: 700; font-size: 0.8125rem; letter-spacing: 0.06em; }
/* The priority is the race's bib number: a small plate before its name. */
.thing-name .priority { flex: none; font-size: 0.8125rem; line-height: 1.4; }
.race-tabs { position: relative; flex: 1; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.race-tabs::-webkit-scrollbar { display: none; }
.race-tabs ul { display: flex; gap: var(--space-5); height: 100%; list-style: none; margin: 0; padding: 0; }
.race-tabs a {
  display: flex;
  align-items: center;
  height: 100%;
  font-family: var(--display);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  text-decoration: none;
  color: var(--ink-2);
  border-top: 3px solid transparent;
  border-bottom: 3px solid transparent;
}
.race-tabs a:hover { color: var(--ink); }
.race-tabs a[aria-current] { color: var(--ink); border-bottom-color: var(--accent); }
/* The sticker is an action, not a view of the race: a small orange-ruled
   button at the end of the tabs, filled once it is the page shown. */
.race-tabs li.tab-print { display: flex; align-items: center; margin-left: auto; }
.race-tabs .tab-print a { gap: 0.4em; height: auto; padding: 0.15em 0.6em; border: 2px solid var(--accent); border-radius: var(--radius); color: var(--ink); }
.race-tabs .tab-print a:hover, .race-tabs .tab-print a[aria-current] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.race-tabs .tab-print svg { flex: none; width: 1.1em; height: 1.1em; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }
@media (min-width: 48rem) {
  .thing-name { font-size: 1.1875rem; }
  .race-tabs ul { gap: var(--space-6); }
  .race-tabs a { font-size: 1.0625rem; }
}
@media (max-width: 29.99rem) {
  .thing-bar .bar { gap: var(--space-3); }
  .thing-bar { --name-w: 50%; }
  .thing-name { padding-right: var(--space-3); font-size: 0.9375rem; }
  .thing-label { display: none; }
  .race-tabs ul { gap: var(--space-4); }
  .race-tabs a { font-size: 0.9375rem; letter-spacing: 0.04em; }
}

/* The race's name opens the switch to the rider's other races; the menu
   drops over the page from the header. */
.race-switch { position: relative; display: flex; flex: none; max-width: var(--name-w, 40%); }
.race-switch .thing-name { max-width: none; width: 100%; cursor: pointer; list-style: none; }
.race-switch .thing-name::-webkit-details-marker { display: none; }
.race-switch .thing-name::after {
  content: "";
  flex: none;
  width: 0.5em;
  height: 0.5em;
  margin-left: var(--space-1);
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-25%) rotate(45deg);
}
.race-switch[open] .thing-name::after { transform: translateY(25%) rotate(-135deg); }
.race-switch-menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 30;
  min-width: 16rem;
  max-width: calc(100vw - 2 * var(--space-4));
  max-height: 60vh;
  overflow-y: auto;
  padding: var(--space-3) var(--space-4);
  background: var(--bg);
  border: 1px solid var(--line);
  border-top: 3px solid var(--rule);
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.15);
}
.race-switch-menu .eyebrow { margin: 0 0 var(--space-1); }
.race-switch-menu ul { list-style: none; padding: 0; margin: 0 0 var(--space-2); }
.race-switch-menu li { padding: var(--space-1) 0; }
.race-switch-menu p:last-child { margin: 0; padding-top: var(--space-2); border-top: 1px solid var(--line); font-weight: 600; }

/* Error pages (404, 500): the bib of a rider who did not finish */
.error-page {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: var(--space-6);
  align-items: center;
  padding-bottom: var(--space-6);
}
.error-bib { justify-self: center; padding-bottom: var(--space-5); transform: rotate(-3deg); }

/* Home: the promise, one line per thing a race plan gives (navigation.md §4.1) */
.hero .promise { list-style: none; padding: 0; margin: var(--space-5) 0 0; display: grid; gap: var(--space-2); }
.hero .promise li { position: relative; padding-left: var(--space-5); font-weight: 600; }
.hero .promise li::before { content: ""; position: absolute; left: 0; top: 0.6em; width: var(--space-4); height: 3px; background: var(--band-accent); }

/* Today: race radio, the one next step (navigation.md §4.3) */
.race-radio { padding: var(--space-7) 0; }
.race-radio .eyebrow { margin-top: 0; }
.race-radio h1 { margin: 0 0 var(--space-3); }
.race-radio .lead { color: #d4d4d4; max-width: var(--measure); }
.race-radio .actions { margin-top: var(--space-5); }
.card .eyebrow { margin: 0 0 var(--space-1); }

/* The setup guide's three questions */
.setup { max-width: var(--measure); }
.setup-steps { display: grid; gap: var(--space-4); padding-left: var(--space-5); margin: var(--space-5) 0; }
.setup-steps label { display: block; font-weight: 600; }
.setup-steps label small { font-weight: 400; }
.setup-steps :is(input, select, .select) { display: block; margin-top: var(--space-1); }
.setup-steps :is(select, .select) { max-width: 26rem; }
.setup-steps .hint { display: block; margin-top: var(--space-1); }
.band .setup-steps .hint { color: var(--band-ink-2); }

/* Training zones */
.zones-form { display: flex; flex-wrap: wrap; align-items: end; gap: var(--space-3); }
.zones-form label { display: block; }
.zones-form input { display: block; width: 8rem; margin-top: var(--space-1); }
.zones-table .num { white-space: nowrap; }
@media (max-width: 29.99rem) {
  .zones-table th:nth-child(3), .zones-table td:nth-child(3) { display: none; }
}

/* Training plan (training.md §11). The season is drawn as a Grand Tour's
   stage overview: a bar per week, its height the week's load, coloured by
   phase from flat (prep, base) to mountain (specialty), with flags for
   races. Phases go from grey to orange as the race comes closer. */
.promise { list-style: none; padding: 0; margin: var(--space-5) 0; display: grid; gap: var(--space-2); }
.promise li { position: relative; padding-left: var(--space-5); font-weight: 600; }
.promise li::before { content: ""; position: absolute; left: 0; top: 0.6em; width: var(--space-4); height: 3px; background: var(--accent); }
.season { margin: var(--space-4) 0; }
.season svg { display: block; width: 100%; height: 10rem; border-bottom: 3px solid var(--rule); }
.season rect, .season-legend .swatch { fill: var(--line-strong); background: var(--line-strong); }
.season .phase-prep, .season-legend .phase-prep { fill: var(--line); background: var(--line); }
.season .phase-base, .season-legend .phase-base { fill: var(--ink-2); background: var(--ink-2); }
.season .phase-build, .season-legend .phase-build { fill: var(--ink); background: var(--ink); }
.season .phase-specialty, .season-legend .phase-specialty { fill: var(--accent); background: var(--accent); }
.season .phase-taper, .season-legend .phase-taper { fill: var(--link); background: var(--link); }
.season .recovery, .season-legend .recovery { fill: var(--surface); background: var(--surface); stroke: var(--line-strong); stroke-width: 1; }
.season-legend .recovery { border: 1px solid var(--line-strong); }
.season .past { opacity: 0.45; }
.season .now { stroke: var(--accent); stroke-width: 2; }
.season .flag { fill: var(--ink); }
.season .flag.goal { fill: var(--accent); }
/* Planned fitness over the bars, haloed so it reads on black and orange. */
.season .fitness, .season .fitness-halo { fill: none; stroke-linejoin: round; stroke-linecap: round; }
.season .fitness { stroke: var(--ink); stroke-width: 2; }
.season .fitness-halo { stroke: var(--surface); stroke-width: 5; }
.season-legend .swatch.fitness { height: 3px; width: 1.2em; vertical-align: 0.2em; background: var(--ink); }
.season .fitness.ridden { stroke: var(--link); stroke-width: 2.5; }
.season-legend .swatch.fitness.ridden { background: var(--link); }
.strava-block { white-space: pre-wrap; font-family: var(--font); background: var(--surface); padding: var(--space-3); border-radius: var(--radius-lg); }
.strava-lines { list-style: none; padding: 0; }
.season-legend { list-style: none; padding: 0; margin: var(--space-2) 0 0; display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); font-size: var(--text-sm); color: var(--ink-2); }
.season-legend .swatch { display: inline-block; width: 0.9em; height: 0.9em; margin-right: 0.35em; vertical-align: -0.1em; }
.plan-weeks tr.past { color: var(--ink-2); }
.plan-weeks tr.focus th { font-weight: 800; }
.plan-weeks .num { white-space: nowrap; }
.race-flag { white-space: nowrap; font-weight: 600; }
.plan-days { display: grid; grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr)); gap: var(--space-2) var(--space-3); margin-top: var(--space-2); }
.plan-days label { font-weight: 600; }
.plan-days select { margin-top: var(--space-1); }
.setup fieldset { border: 0; padding: 0; margin: 0; }
.setup legend { font-weight: 600; padding: 0; margin-bottom: var(--space-2); }
.setup-steps .choices label { display: inline-flex; font-weight: 600; }
.setup-steps .choices input { display: inline-block; margin-top: 0; }

/* The week's head: its dates, with the weeks either side at hand. */
.week-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: var(--space-4); margin-top: var(--space-6); }
.week-head h1 { margin: 0; }
.week-step { display: flex; gap: var(--space-2); margin: 0; }
.week-step .button { min-width: 2.75rem; }
/* The days ahead and their weather, for a rider without the plan: a row
   per day under a heavy rule. */
.week-days { list-style: none; padding: 0; margin: var(--space-5) 0; border-top: 3px solid var(--rule); }
.week-day { display: grid; grid-template-columns: 8rem 1fr; gap: var(--space-1) var(--space-5); padding: var(--space-3) 0 var(--space-3) var(--space-3); border-bottom: 1px solid var(--line); }
.week-day p { margin: 0; }
.week-day .hint { font-size: var(--text-sm); }
.week-day.today { background: var(--surface); }
.week-date { font-family: var(--display); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
/* The day's best start under its date, the time to be on the start line. */
.week-start { margin: var(--space-1) 0 0; font-variant-numeric: tabular-nums; }
.week-start small { display: block; color: var(--ink-2); letter-spacing: 0.06em; text-transform: uppercase; }
.week-start strong { font-family: var(--display); font-size: 1.25rem; color: var(--accent); }
/* Each day's weather where the rider rides, with the sky as the stage's
   weather symbol, as on a Tour stage card. */
.week-wx { margin-top: var(--space-1) !important; font-variant-numeric: tabular-nums; }
.wx-sky { width: 1.25em; height: 1.25em; vertical-align: -0.25em; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; color: var(--accent); }
.wx-sky .fill { fill: var(--surface); }
.wx-label { font-weight: 600; }
@media (max-width: 29.99rem) {
  .week-day { grid-template-columns: 1fr; }
  /* Today first on a phone, then the days after it. */
  .week-days { display: flex; flex-direction: column; }
  .week-day.today { order: -1; }
}

/* The week planner (Directeur sportif). First the ardoise, the moto's
   chalkboard: the riding time by Sunday night, and a bar for each total
   with what was ridden (white), what is still planned (orange) and the
   plan's week (a dashed mark). */
.ardoise { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); gap: var(--space-5) var(--space-6); margin: var(--space-5) 0 var(--space-2); padding: var(--space-5); background: var(--band); color: var(--band-ink); border: 10px solid #2b2b2b; outline: 2px solid var(--band); }
.ardoise p, .ardoise dl { margin: 0; }
.ardoise-main { display: flex; flex-direction: column; gap: var(--space-3); }
.ardoise-head { font-family: var(--display); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--band-accent); }
.ardoise-figure { font-family: var(--display); text-transform: uppercase; line-height: 0.85; }
.ardoise-figure strong { font-size: clamp(4rem, 9vw, 6.5rem); font-weight: 800; font-variant-numeric: tabular-nums; }
.ardoise-figure small { font-size: var(--text-xl); font-weight: 700; color: var(--band-ink-2); }
.ardoise-line { color: var(--band-ink-2); }
.ardoise-load { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); padding-top: var(--space-3); border-top: 2px dashed #5c5c5c; }
.ardoise-load dt { font-family: var(--display); font-weight: 700; font-size: var(--text-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--band-ink-2); }
.ardoise-load dd { margin: 0; font-family: var(--display); font-weight: 800; font-size: var(--text-2xl); line-height: 1; font-variant-numeric: tabular-nums; }
.ardoise-load dd.form { color: var(--band-accent); }
.ardoise-load dd.was { font-family: var(--font); font-weight: 400; font-size: var(--text-xs); color: var(--band-ink-2); }
.ardoise-rows { display: flex; flex-direction: column; justify-content: center; gap: var(--space-3); }
.ardoise-row { display: grid; grid-template-columns: 7rem minmax(0, 1fr) 11rem; gap: var(--space-3); align-items: center; }
.ardoise-label { font-family: var(--display); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--band-ink-2); }
.ardoise-bar { position: relative; display: flex; height: 1.25rem; background: #2b2b2b; }
.ardoise-bar .done { background: var(--band-ink); }
.ardoise-bar .come { background: repeating-linear-gradient(135deg, var(--accent) 0 6px, var(--link) 6px 9px); }
.ardoise-bar .plan { position: absolute; top: -5px; bottom: -5px; border-left: 2px dashed var(--band-ink); }
.ardoise-fig { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ardoise-fig strong { font-family: var(--display); font-size: var(--text-xl); font-weight: 800; }
.ardoise-fig small { color: var(--band-ink-2); }
.ardoise-key { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); font-size: var(--text-xs); color: var(--band-ink-2); }
.ardoise-key span::before { content: ""; display: inline-block; width: 0.75rem; height: 0.75rem; margin-right: 0.35em; vertical-align: -0.05em; }
.ardoise-key .key-done::before { background: var(--band-ink); }
.ardoise-key .key-come::before { background: var(--accent); }
.ardoise-key .key-plan::before { width: 0; border-left: 2px dashed var(--band-ink); }
@media (max-width: 59.99rem) {
  .ardoise { grid-template-columns: 1fr; }
}
@media (max-width: 29.99rem) {
  .ardoise { padding: var(--space-3); border-width: 6px; }
  .ardoise-row { grid-template-columns: 5rem minmax(0, 1fr); }
  .ardoise-fig { grid-column: 1 / -1; text-align: left; }
}

/* The days: a column each, the forecast on top, then the sessions as
   cards to drag, each ruled on top by what it is for: hard in orange,
   long and tempo in black. A day that takes a session is a drop target. */
.planner { margin: var(--space-6) 0 0; }
.planner-title { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: var(--space-1) var(--space-4); }
.planner-title .hint { margin: 0; font-size: var(--text-sm); }
.planner-days { list-style: none; padding: 0; margin: var(--space-3) 0 0; display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--space-2); }
.planner-day { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; min-height: 22rem; padding: var(--space-2); background: var(--surface); border-top: 4px solid var(--rule); }
.planner-day.today { border-top-color: var(--accent); }
.planner-day.past { border-top-color: var(--line-strong); }
.planner-day.past .planner-date { color: var(--ink-2); }
.planner-day.drop { outline: 2px dashed var(--accent); outline-offset: -2px; background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
.planner-day p { margin: 0; }
.planner-date { font-family: var(--display); font-weight: 800; font-size: var(--text-lg); text-transform: uppercase; letter-spacing: 0.03em; }
.planner-date a { color: inherit; }
.planner-wx { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 0 var(--space-2); padding-bottom: var(--space-2); border-bottom: 1px solid var(--line-strong); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.planner-sky { grid-row: span 3; }
.planner-sky .wx-sky { width: 2rem; height: 2rem; vertical-align: middle; }
.planner-temp { font-family: var(--display); font-weight: 700; font-size: var(--text-md); }
.planner-wind, .planner-rain { color: var(--ink-2); }
.wind-arrow { width: 0.85em; height: 0.85em; margin-right: 0.25em; vertical-align: -0.05em; fill: var(--ink); }
.planner-wx.none { display: flex; align-items: center; min-height: calc(4.7rem + var(--space-2) + 1px); color: var(--ink-2); font-size: var(--text-xs); }
.planner-wx.wet .planner-rain { color: var(--link); font-weight: 700; }
.planner-race { font-weight: 600; }
.planner-rest { font-family: var(--display); font-weight: 700; text-transform: uppercase; color: var(--ink-2); }
.planner-card { display: flex; flex-direction: column; gap: 0.2rem; padding: var(--space-2); background: var(--bg); border: 1px solid var(--line-strong); border-top: 5px solid var(--line-strong); font-size: var(--text-sm); }
.planner-card[draggable="true"] { cursor: grab; }
.planner-card.dragging { opacity: 0.4; }
.planner-card.role-hard, .planner-card.role-test { border-top-color: var(--accent); }
.planner-card.role-long, .planner-card.role-quality { border-top-color: var(--ink); }
.planner-card.status-done { background: var(--surface); }
.planner-card.status-missed { border: 2px dashed var(--warn); }
.planner-card.status-past { opacity: 0.6; }
.planner-card.selected { outline: 3px solid var(--accent); outline-offset: 1px; }
.planner-card p { margin: 0; }
.planner-card-head { display: flex; justify-content: space-between; align-items: center; gap: var(--space-1); }
.planner-role { font-family: var(--display); font-weight: 700; font-size: var(--text-xs); letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-2); }
.planner-card.role-hard .planner-role { color: var(--link); }
.planner-card.status-done .planner-role { color: var(--ok); }
.planner-card.status-missed .planner-role { color: var(--warn); }
.planner-x-form { margin: 0; }
.planner-x { min-height: 0; width: 1.75rem; height: 1.75rem; padding: 0; border: 0; background: transparent; color: var(--ink-2); font-size: var(--text-sm); }
.planner-x:hover { background: var(--ink); color: var(--bg); }
.planner-name { font-family: var(--display); font-weight: 800; font-size: var(--text-lg); line-height: 1.05; text-transform: uppercase; color: var(--ink); text-decoration: none; overflow-wrap: anywhere; }
.planner-name:hover { color: var(--link); }
.planner-shape, .planner-reach { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.planner-figs { font-family: var(--display); font-weight: 700; font-size: var(--text-md); font-variant-numeric: tabular-nums; }
.planner-figs small { font-weight: 600; color: var(--ink-2); }
.planner-ridden { color: var(--ok); font-weight: 600; font-variant-numeric: tabular-nums; }
.planner-note { color: var(--warn); font-weight: 600; font-size: var(--text-xs); }
/* "+ Add" folds out the team car: the workouts, those that fit the day's
   time first in weight. */
.planner-add { margin-top: auto; }
.planner-add summary { list-style: none; cursor: pointer; padding: var(--space-2); border: 2px dashed var(--line-strong); text-align: center; font-family: var(--display); font-weight: 700; text-transform: uppercase; color: var(--ink-2); }
.planner-add summary::-webkit-details-marker { display: none; }
.planner-add summary:hover { border-color: var(--ink); color: var(--ink); }
.planner-add[open] summary { border-style: solid; border-color: var(--rule); background: var(--rule); color: var(--bg); }
.planner-add-list { display: flex; flex-direction: column; border: 2px solid var(--rule); border-top: 0; background: var(--bg); }
.planner-add-head { padding: var(--space-1) var(--space-2) !important; border-bottom: 3px solid var(--accent); font-family: var(--display); font-weight: 700; font-size: var(--text-xs); text-transform: uppercase; color: var(--ink-2); }
.planner-add-list button { display: block; width: 100%; min-height: 2.75rem; padding: var(--space-1) var(--space-2); border: 0; border-top: 1px solid var(--line); border-radius: 0; background: transparent; color: var(--ink-2); text-align: left; text-transform: none; font-family: var(--font); font-size: var(--text-sm); letter-spacing: 0; }
.planner-add-list button.fits { color: var(--ink); }
.planner-add-list button small { display: block; font-size: var(--text-xs); }
.planner-add-list button:hover { background: var(--ink); color: var(--bg); }
@media (max-width: 63.99rem) {
  .planner-days { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .planner-day { min-height: 0; }
}
@media (max-width: 35.99rem) {
  .planner-days { grid-template-columns: 1fr; }
}

/* The session picked, under the days: what it is, the day's weather, its
   workout, and every change to it. */
.planner-sel { margin: var(--space-6) 0; padding-top: var(--space-4); border-top: 3px solid var(--rule); scroll-margin-top: calc(var(--header-h, 4rem) + var(--space-4)); }
.planner-sel-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: var(--space-4); }
.planner-sel-head h2 { margin: 0; }
.planner-sel-head .lead { margin: var(--space-1) 0 0; }
.planner-sel-wx { padding: var(--space-2) var(--space-3); background: var(--surface); font-variant-numeric: tabular-nums; }
.planner-sel-wx > strong:first-child { font-family: var(--display); text-transform: uppercase; letter-spacing: 0.04em; margin-right: 0.35em; }
.planner-edit { display: flex; flex-wrap: wrap; gap: var(--space-4) var(--space-6); align-items: flex-end; margin: var(--space-4) 0; }
.planner-label { margin: 0 0 var(--space-1); font-weight: 600; }
.planner-levels .levels { margin: 0; }
.planner-levels .levels button { min-width: 2.75rem; }
.planner-levels .levels button.current { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.planner-moves { margin: var(--space-4) 0; }
.planner-move-days { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.planner-move-days small { display: block; font-family: var(--font); text-transform: none; letter-spacing: 0; font-weight: 400; }
.day-extra { margin: var(--space-4) 0; padding-top: var(--space-3); border-top: 1px solid var(--line); }
.day-extra h3 { margin: 0; }

/* Where the rider rides: home, and the places away. */
.place { margin: var(--space-5) 0; }
.place-now { margin: 0 0 var(--space-2); }
.place-search { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); margin: var(--space-3) 0; }
.place-search label { flex: 1 1 12rem; }
.place-locate { margin: var(--space-2) 0; }
.place-away, .place-results ul { list-style: none; padding: 0; margin: var(--space-3) 0; }
.place-away li { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--space-2); padding: var(--space-2) 0; border-bottom: 1px solid var(--line); }
.place-away li.past { opacity: 0.6; }
.place-results li { margin: var(--space-1) 0; }
.place-windows { display: grid; gap: var(--space-2); margin: var(--space-3) 0; max-width: 28rem; }
.place-windows label { display: grid; grid-template-columns: 7rem minmax(0, 1fr); align-items: center; gap: var(--space-2); }
.place-windows label span { text-transform: capitalize; }
.place-windows button { justify-self: start; }
/* Running cold, normal or warm: three choices in a row. */
.place-runs fieldset { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); border: 0; padding: 0; margin: var(--space-2) 0; }
.place-runs legend { padding: 0; margin-bottom: var(--space-1); }
/* Interval routes (Recon): the workouts a route serves, one per line, with
   the routes a full workout has beside it. */
.route-workouts ul { list-style: none; padding: 0; margin: var(--space-2) 0 0; display: grid; gap: var(--space-1); }
.route-workouts li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); }
.route-workouts label:has(input:disabled) { color: var(--ink-2); }

/* A route's check warnings: each ruled in the warning colour with its
   dismiss button; dismissed ones quiet. */
.route-warnings { list-style: none; padding: 0; margin: var(--space-2) 0; display: grid; gap: var(--space-1); }
.route-warnings li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); padding-left: var(--space-2); border-left: 3px solid var(--warn); }
.route-warnings li.dismissed { border-left-color: var(--line-strong); color: var(--ink-2); }
.route-warnings form { margin: 0; }

/* A session's route: the directeur sportif's briefing, the route to ride
   under a heavy rule, the other one below it. */
.session-route-main { border-top: 3px solid var(--rule); padding-top: var(--space-2); }
.session-route-name { font-family: var(--display); font-weight: 800; font-size: 1.25rem; margin: 0; }
.session-route-other p { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); }
/* Changing a session: each change a row of its own, the choice and its
   button side by side. The steps are written in a fixed-width font, so
   the columns of a block line up. */
.session-edit-form { display: flex; flex-wrap: wrap; align-items: end; gap: var(--space-2); margin: var(--space-2) 0; }
.session-edit-form label { display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--text-sm); font-weight: 600; }
.session-edit-form select { max-width: 100%; }
.planner-form textarea.steps-text { font-family: var(--mono); font-size: var(--text-sm); }
/* Another route for the day: folded away, one of the rider's routes or a
   GPX of their own. */
.route-pick { margin: var(--space-2) 0; }
.route-pick summary { cursor: pointer; font-family: var(--display); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
.route-pick form { display: grid; gap: var(--space-2); margin-top: var(--space-2); max-width: 32rem; }
.route-pick-saved { grid-template-columns: 1fr auto; align-items: end; }
.route-pick select, .route-pick input[type="text"] { width: 100%; }
/* The best time to ride: the start as a readout and why, then every start
   as a table (.start-table) with its columns in the order they count: rain,
   road, temperature, wind. The best row shaded and ruled in orange, the
   column that decided it headed in orange; a value well worse than the
   best's, or a wet or icy road, in --warn or --bad. Five narrow columns fit
   a phone: each cell a figure over a small line. */
.session-start { margin-top: var(--space-3); }
.start-why { margin: var(--space-2) 0 var(--space-3); padding-left: var(--space-2); border-left: 3px solid var(--accent); }
.start-table { border-collapse: collapse; width: 100%; font-size: var(--text-sm); }
.start-table th, .start-table td { text-align: left; vertical-align: top; padding: var(--space-2) var(--space-2) var(--space-2) 0; border-bottom: 1px solid var(--line); }
.start-table thead th { font-family: var(--display); font-size: var(--text-sm); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink); border-bottom: 3px solid var(--rule); white-space: nowrap; }
.start-table b, .start-table strong { display: block; font-family: var(--display); font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; }
.start-table b { font-size: 1.125rem; }
.start-table strong { font-size: 1.25rem; }
.start-table small { display: block; color: var(--ink-2); font-size: var(--text-xs); line-height: 1.3; }
.start-table td small { white-space: nowrap; }
.start-table svg { display: block; width: 100%; max-width: 5rem; height: 6px; margin-top: 0.2rem; }
.start-table .fill { fill: var(--rel); }
.start-table .badge { display: inline-block; margin-top: 0.15rem; }
.start-table tr.current th, .start-table tr.current td { background: var(--surface); }
.start-table .c-start { width: 4.5rem; }
.start-table tbody th { padding-left: var(--space-2); border-left: 3px solid transparent; font-weight: 400; }
.start-table tr.current th { border-left-color: var(--accent); }
.start-table tr.current strong { color: var(--link); }
.start-table .off b, .start-table .road-wet b { color: var(--warn); }
.start-table .road-icy b { color: var(--bad); }
.decided-start thead .c-start, .decided-rain thead .c-rain, .decided-road thead .c-road,
.decided-temp thead .c-temp, .decided-wind thead .c-wind { color: var(--link); border-bottom-color: var(--accent); }
@media (max-width: 22rem) {
  .start-table b { font-size: 1rem; }
  .start-table thead th { letter-spacing: 0; }
  .start-table td small { white-space: normal; }
}
/* The day hour by hour (.day-board, Stage weather): a black band with the
   day's figures over the header's orange stripe, then a column per hour,
   the ride at the best start shaded orange across them. The road a strip
   in its state's colour, named where it changes; ice, showers and strong
   gusts as filled bars across the hours they last. On a phone the hours
   scroll sideways under the row names, which stay put. */
.day-board { margin: var(--space-4) 0 var(--space-5); }
.day-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: var(--space-3) var(--space-5); padding: var(--space-4); background: var(--band); color: var(--band-ink); border-bottom: 6px solid var(--accent); }
.day-head .eyebrow { display: block; margin: 0 0 var(--space-1); color: var(--band-accent); }
.day-head strong { display: block; font-family: var(--display); font-weight: 800; font-size: 1.75rem; line-height: 1; text-transform: uppercase; }
.day-stats { display: flex; gap: var(--space-5); margin: 0; }
.day-stats div { display: flex; flex-direction: column-reverse; }
.day-stats dt { font-family: var(--display); font-weight: 700; font-size: var(--text-xs); letter-spacing: 0.06em; text-transform: uppercase; color: var(--band-ink-2); }
.day-stats dd { margin: 0; font-family: var(--display); font-weight: 800; font-size: 1.75rem; line-height: 1; font-variant-numeric: tabular-nums; white-space: nowrap; }
.day-table { border-collapse: collapse; width: 100%; font-family: var(--display); font-variant-numeric: tabular-nums; text-align: center; }
.day-table th, .day-table td { padding: var(--space-1) 0.15rem; border-bottom: 1px solid var(--line); min-width: 2.5rem; }
.day-table thead th { font-weight: 700; color: var(--ink-2); border-bottom: 3px solid var(--rule); }
.day-table thead th.ride { color: var(--link); }
.day-table tbody th { position: sticky; left: 0; z-index: 1; background: var(--bg); text-align: left; padding-right: var(--space-2); font-weight: 700; font-size: var(--text-sm); letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-2); white-space: nowrap; }
.day-table tbody th small { display: block; font-family: var(--font); font-size: var(--text-xs); letter-spacing: 0; text-transform: none; font-weight: 400; }
.day-table b { display: block; font-weight: 800; }
.day-table td small { display: block; font-size: var(--text-xs); color: var(--ink-2); }
.day-table .ride { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.day-ride td { position: relative; height: 1.5rem; padding: 0; border-bottom: 0; }
.day-ride span { position: absolute; left: 0; bottom: 0; min-width: 100%; box-sizing: border-box; padding: 0.15rem 0.35rem; background: var(--accent); color: var(--accent-ink); font-weight: 800; font-size: var(--text-xs); letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap; }
.day-sky .wx-sky { width: 1.5rem; height: 1.5rem; vertical-align: middle; }
.day-temp b { font-size: 1.5rem; line-height: 1.1; }
.day-temp .frost b { color: var(--bad); }
.day-rain svg { display: block; width: 1.1rem; height: 2.5rem; margin: 0 auto 0.15rem; }
.day-rain .track { fill: var(--surface); }
.day-rain .bar { fill: var(--ink-2); }
.day-rain .showers .bar { fill: var(--accent); }
.day-rain b { min-height: 1.25em; }
.day-road td { padding: var(--space-2) 0; font-weight: 700; font-size: var(--text-xs); letter-spacing: 0.04em; text-transform: uppercase; }
.day-road .road-dry { background: var(--surface); color: var(--ink-2); }
.day-road .road-damp { background: color-mix(in srgb, var(--warn) 22%, var(--bg)); color: var(--ink); }
.day-road .road-wet { background: var(--warn); color: var(--bg); }
.day-road .road-icy { background: var(--bad); color: var(--bg); }
.day-road td + .road-start { border-left: 2px solid var(--bg); }
.day-wind svg { display: block; width: 1.1rem; height: 1.1rem; margin: 0 auto 0.15rem; fill: none; stroke: var(--ink); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.day-wind b { font-size: 1.125rem; }
.day-wind .strong small { color: var(--warn); font-weight: 800; }
.day-alert th, .day-alert td { padding: 0.15rem 0; border-bottom: 0; }
.day-alert td.on span { display: block; padding: 0.2rem 0.35rem; font-weight: 700; font-size: var(--text-xs); letter-spacing: 0.04em; text-transform: uppercase; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.alert-ice td.on span { background: var(--bad); color: var(--bg); }
.alert-showers td.on span { background: var(--accent); color: var(--accent-ink); }
.alert-gusts td.on span { background: var(--warn); color: var(--bg); }
.day-board > .hint { margin-top: var(--space-2); }
/* What to wear: the soigneur's call. Coldest and warmest as two ruled
   lines, cold in the headwind's red, warm in the accent; then the kit, and
   what comes off or along. */
.session-kit { margin: 0; }
.kit-span { list-style: none; padding: 0; margin: var(--space-2) 0; display: grid; gap: var(--space-1); }
.kit-span li { padding-left: var(--space-2); border-left: 3px solid var(--line-strong); }
.kit-span li.kit-cold { border-left-color: var(--bad); }
.kit-span li.kit-warm { border-left-color: var(--accent); }
.kit-wear { font-weight: 700; }
.kit-lines { margin: var(--space-2) 0; padding-left: var(--space-5); }

/* The day (Training › Day), read top down. The pager to the days around
   it; Race radio, a black band of five lines, each with a small version of
   the part below it; then the parts, numbered 01, 02, 03 like stages, each
   under a heavy rule, the detail folded away. */
.day-pager { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--space-2); padding-bottom: var(--space-2); margin-bottom: var(--space-3); border-bottom: 1px solid var(--line); font-family: var(--display); font-weight: 700; text-transform: uppercase; }
.day-pager a { display: flex; flex-direction: column; min-height: 44px; justify-content: center; color: var(--ink); text-decoration: none; }
.day-pager a[rel="next"] { text-align: right; }
.day-pager a small { font-family: var(--font); font-weight: 400; text-transform: none; color: var(--ink-2); }
.day-pager a:hover span { color: var(--link); }
.day-pager-now { font-size: 1.125rem; text-align: center; }
.day-radio { margin-top: var(--space-4); padding: var(--space-3) 0 var(--space-2); border-bottom: 4px solid var(--accent); }
.day-radio .eyebrow { margin: 0 0 var(--space-1); }
.day-radio ul { list-style: none; margin: 0; padding: 0; max-width: var(--measure); }
.day-radio li + li { border-top: 1px solid #2e2e2e; }
.day-radio li a { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) 0; color: var(--band-ink); text-decoration: none; }
.day-radio li a:hover strong { color: var(--band-accent); }
.radio-key { flex: 0 0 3.5rem; font-family: var(--display); font-weight: 700; font-size: var(--text-sm); letter-spacing: 0.06em; text-transform: uppercase; color: var(--band-ink-2); }
.radio-what { flex: 1 1 auto; min-width: 0; }
.radio-what strong { display: block; font-family: var(--display); font-weight: 800; font-size: 1.3125rem; line-height: 1.05; text-transform: uppercase; }
.radio-what small { display: block; color: #d4d4d4; }
.radio-mini { flex: 0 0 auto; }
.radio-rain { width: 5rem; height: 2rem; }
.radio-rain rect { fill: #5c5c5c; }
.radio-rain rect.wet { fill: var(--band-accent); }
.radio-rain rect.ride { stroke: var(--band-ink); stroke-width: 1.5; }
.radio-temps { display: flex; flex-direction: column; align-items: flex-end; font-family: var(--display); font-weight: 800; font-size: 1.125rem; line-height: 1.1; }
.radio-temps .cold { color: #f87171; }
.radio-temps .warm { color: var(--band-accent); }
.radio-profile { width: 5.5rem; padding: 3px 3px 0; background: var(--bib); }
.radio-profile .workout-profile { height: 1.5rem; }
.radio-profile .ftp { display: none; }
.radio-profile .z-threshold { fill: var(--bib-ink); }
.day-parts { counter-reset: day-part; }
.day-part > h2 { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); padding-bottom: var(--space-1); border-bottom: 3px solid var(--rule); }
.day-part > h2::before { counter-increment: day-part; content: counter(day-part, decimal-leading-zero); color: var(--link); }
.day-part > h2 .eyebrow, .day-seen { margin: 0 0 0 auto; font-family: var(--display); font-size: var(--text-sm); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2); }
.day-part > h2 .eyebrow { color: var(--link); }
.day-seen.first { color: var(--link); }
.workout-shape { margin: var(--space-2) 0; font-family: var(--display); font-weight: 700; font-size: 1.375rem; }
.workout-shape strong { font-weight: 800; }
.workout-why { font-weight: 600; max-width: var(--measure); }
.workout-profile { display: block; width: 100%; height: 7rem; border-bottom: 2px solid var(--rule); }
.workout-profile .z-easy { fill: #d4d4d4; }
.workout-profile .z-endurance { fill: var(--line-strong); }
.workout-profile .z-threshold { fill: var(--ink); }
.workout-profile .z-above { fill: var(--accent); }
.workout-profile .ftp { stroke: var(--ink); stroke-width: 1.5; stroke-dasharray: 4 3; }
details.fold { border-bottom: 1px solid var(--line); }
details.fold > summary { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-2); min-height: 48px; padding: var(--space-2) 0; cursor: pointer; font-family: var(--display); font-weight: 700; font-size: 1.125rem; letter-spacing: 0.04em; text-transform: uppercase; }
details.fold > summary small { font-family: var(--font); font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--ink-2); }
details.fold[open] > summary { color: var(--link); }
details.fold > :not(summary) { margin-bottom: var(--space-3); }

/* A session's steps: repeats are one group under a heavy rule. */
.workout-steps tbody.repeat { border-left: 3px solid var(--accent); }
.workout-steps tbody.repeat th[scope="row"] { padding-left: var(--space-3); }
.workout-steps .repeat-head th { font-family: var(--display); font-weight: 800; font-size: 1.125rem; padding-left: var(--space-3); }
.workout-steps tr.work th { font-weight: 700; }
.workout-steps .num { white-space: nowrap; }
.levels { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: var(--space-4) 0; font-family: var(--display); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; }
.levels a { min-width: 2.5rem; padding: 0.25rem 0.6rem; border: 2px solid var(--line-strong); border-radius: var(--radius); text-align: center; text-decoration: none; color: var(--ink); }
.levels a[aria-current] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.race-radio form.inline { margin: 0; }

/* ---------- Top-tube sticker ---------- */
/* Profile of the day: a race's course, climbs and feeds on a strip to tape
   to the top tube or stem, drawn on the server in millimetres so it prints
   at its true size. It is paper, so it stays white in both themes, and its
   colours are fixed: black bands, the signal orange, the profile shaded by
   gradient from pale to black so it still reads printed in grey. */
.sticker-intro .eyebrow { margin-bottom: var(--space-2); }
.sticker-intro h2 { margin-top: 0; }
.sticker-formats { margin: var(--space-2) 0 var(--space-4); }
.sticker-formats small { font-family: var(--font); font-weight: 500; letter-spacing: 0; text-transform: none; color: inherit; opacity: 0.75; }
.sticker-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); margin: var(--space-5) 0 var(--space-2); }
.sticker-sheet { display: flex; flex-wrap: wrap; gap: var(--space-5); margin: var(--space-5) 0; padding: var(--space-5); background: var(--surface); }
.sticker-svg { display: block; max-width: 100%; height: auto; print-color-adjust: exact; -webkit-print-color-adjust: exact; }
.sticker-svg text { font-family: var(--display); font-weight: 700; font-variant-numeric: tabular-nums; font-kerning: none; }
.sticker-svg .st-heavy { font-weight: 800; }
.sticker-svg .st-paper { fill: #ffffff; }
.sticker-svg .st-band, .sticker-svg .st-ink, .sticker-svg .st-accent-ink, .sticker-svg .st-icon { fill: #111111; }
.sticker-svg .st-accent { fill: #ea580c; }
.sticker-svg .st-ink-2 { fill: #525252; }
.sticker-svg .st-link { fill: #c2410c; }
.sticker-svg .st-band-ink { fill: #ffffff; }
.sticker-svg .st-band-ink-2 { fill: #a3a3a3; }
.sticker-svg .st-band-accent { fill: #fb923c; }
.sticker-svg .st-g0 { fill: #e7e5e4; }
.sticker-svg .st-g1 { fill: #fdba74; }
.sticker-svg .st-g2 { fill: #ea580c; }
.sticker-svg .st-g3 { fill: #111111; }
.sticker-svg .st-road { fill: none; stroke: #111111; stroke-width: 0.22; stroke-linejoin: round; }
.sticker-svg .st-base { stroke: #111111; stroke-width: 0.3; }
.sticker-svg .st-tick { stroke: #111111; stroke-width: 0.2; }
.sticker-svg .st-leader { fill: none; stroke: #a3a3a3; stroke-width: 0.2; }
.sticker-svg .st-leader-feed, .sticker-svg .st-pole { stroke: #ea580c; }
.sticker-svg .st-pole { fill: none; stroke-width: 0.25; }
.sticker-svg .st-pole-climb { stroke: #111111; stroke-width: 0.18; stroke-dasharray: 0.5 0.35; }
.sticker-svg .st-descent { fill: #a3a3a3; }
.sticker-svg .st-hair { fill: #d4d4d4; }
.sticker-svg .st-outline { fill: none; stroke: #111111; stroke-width: 0.2; }
.sticker-svg .st-crop { stroke: #111111; stroke-width: 0.15; }
.sticker-svg .st-icon-line { fill: none; stroke: #111111; stroke-width: 0.7; }
.sticker-svg .st-icon-cut { fill: none; stroke: #ffffff; stroke-width: 0.7; stroke-linecap: round; }
.sticker-svg .st-mark-bg { fill: #ea580c; }
.sticker-svg .st-mark-peak { fill: #111111; }
@page sticker { margin: 8mm; }
@media print {
  .sticker-main > :not(#sticker), #sticker > :not(.sticker-sheet) { display: none; }
  .sticker-sheet { page: sticker; margin: 0; padding: 0; gap: 4mm; background: none; flex-direction: column; }
  .sticker-sheet.vertical { flex-direction: row; }
  .sticker-svg { max-width: none; }
  .sticker-spare.print-only { display: block; }
}
