/* Daily Derby styling.
   WHY one flat stylesheet and no framework: the whole visual identity is big
   type, silk colour and a green track. A framework would fight all three.
   The look is loud in scale, not in count of colours.

   THE COLOUR RULE, because it was broken once and cost a redesign:
   paper and ink carry the whole page. Orange is the ONE accent and only one
   use of it should be visible per screen (the main CTA, a live/urgent state,
   the stage word in an H1). Gold means winner and nothing else: the podium's
   first step and the winner's interview. Green means turf and nothing else:
   the track and podium panels. Anything that just wanted "a colour" gets ink,
   paper or an opacity instead. */

:root {
  --ink: #12140f;
  --paper: #f4efe2;
  /* Muted a step from the old #1f6b3a: a turf panel is a surface the result
     is read off, not a signal in its own right. */
  --turf: #2b6140;
  --turf-dark: #1c4a2f;
  --rail: #ffffff;
  --pop: #ff5714;
  --pop-dark: #d8430a;
  /* Winner only. See the colour rule above. */
  --gold: #f2c14e;
  --line: rgba(18, 20, 15, 0.14);
  /* Quiet text on a dark or turf panel, where ink is invisible and gold was
     doing the job by accident. */
  --on-dark-quiet: rgba(255, 255, 255, 0.72);
  /* ONE hard-offset shadow, ink, one size. The old stylesheet had ink, orange
     and gold at 6px and 8px, which made every panel argue for the same rank.
     Hierarchy is type size and position now; the shadow is just the paper
     edge the whole design shares. */
  --shadow: 5px 5px 0 var(--ink);
  --shadow-press: 3px 3px 0 var(--ink);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.5;
}

a { color: var(--ink); text-decoration-thickness: 2px; text-underline-offset: 2px; }
a:hover { color: var(--pop); }

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

/* ---- chrome ---- */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  max-width: 1060px; margin: 0 auto; padding: 18px 20px;
}
.brand {
  font-weight: 900; font-size: 22px; letter-spacing: -0.03em;
  text-decoration: none; text-transform: lowercase;
}
/* The wordmark used to split DAILY/DERBY in orange, which spent the page's one
   accent before the page had said anything. It is ink; the weight is the mark. */
/* The domain is the joke, so the wordmark is the domain: the TLD stays
   lowercase against the uppercase name, and the horse sits on top of "lol"
   like a silk over a number. */
.brand-lol { text-transform: none; color: var(--turf-dark); font-size: 13px; }
.brand-lol-word { position: relative; }
/* Absolute so the horse is outside the line box entirely: the topbar's height
   is set by the wordmark, and a mark that leans on the text would grow it. */
.brand-mark {
  position: absolute; left: 0; right: 0; top: -11px;
  text-align: center; font-size: 13px; line-height: 1;
  pointer-events: none;
}
.topbar nav { display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }
.topbar nav a { font-weight: 700; text-decoration: none; font-size: 15px; }
/* The pill is a button sitting in a row of plain links, so it carries its own
   clearance rather than trusting the nav gap alone. Without it the pill's
   background starts a hair after the previous link's last glyph and the two
   read as one run-on control. */
.cta-mini {
  background: var(--ink); color: var(--paper) !important;
  padding: 8px 14px; border-radius: 999px;
  margin-left: 6px; white-space: nowrap;
}
.cta-mini:hover { background: var(--pop); }

/* Neutral, not gold: a dev banner is a note to the operator, and gold means
   winner. Ink on paper with a rule under it is loud enough for that. */
.devbar {
  background: var(--paper); color: var(--ink); font-weight: 700;
  border-bottom: 2px solid var(--ink);
  text-align: center; padding: 8px 16px; font-size: 14px;
  letter-spacing: 0.04em;
}

footer {
  border-top: 3px solid var(--ink);
  max-width: 1060px; margin: 0 auto; padding: 24px 20px 60px;
}
footer p { margin: 6px 0; }

/* ---- hero ---- */
.hero { padding: 40px 0 28px; }
.hero.small { padding: 28px 0 20px; }
/* An eyebrow is a label, not a signal. It used to be turf green, which put the
   track's colour at the top of pages that have no track on them. */
.eyebrow {
  font-weight: 800; letter-spacing: 0.16em; font-size: 12px;
  text-transform: uppercase; margin: 0 0 10px; color: rgba(18, 20, 15, 0.58);
}
.hero h1 {
  font-size: clamp(42px, 8vw, 86px); line-height: 0.92; margin: 0;
  letter-spacing: -0.04em; font-weight: 900; text-transform: uppercase;
}
.hero h1 .stage { color: var(--turf-dark); }
.countdown { font-weight: 700; margin-top: 16px; }
.countdown #clock { background: var(--ink); color: var(--paper); padding: 2px 8px; border-radius: 6px; }

/* ---- panels ---- */
.panel {
  background: var(--rail); border: 3px solid var(--ink); border-radius: 14px;
  padding: 20px 22px; margin: 18px 0;
  box-shadow: var(--shadow);
}
.panel h2 {
  font-size: 14px; text-transform: uppercase; letter-spacing: 0.14em;
  margin: 0 0 12px; font-weight: 900;
}
.panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.panel-head h2 { margin: 0; }
/* A panel head can carry a section label above its title. The label says
   where in the day you are; the title says what the panel is. */
.panel-head .eyebrow { margin: 0 0 4px; }
/* Each panel hugs its own content. A short list stretched to a long
   paragraph's height is a panel with a hole in it. */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
.grid-2 > .panel { margin: 18px 0; }
@media (max-width: 780px) { .grid-2 { grid-template-columns: 1fr; } }

.big { font-size: 24px; font-weight: 800; margin: 4px 0 8px; letter-spacing: -0.02em; }
.fine { font-size: 14px; opacity: 0.66; }
/* An empty fine-print holder (the notify note before it has anything to say)
   must not spend its margin: in a flex column nothing collapses it away. */
.fine:empty, .bigcount .fine:empty { display: none; }
/* A confirmation is not a prize, so it is not gold. */
.flash {
  background: rgba(18, 20, 15, 0.06); border-left: 4px solid var(--ink);
  font-weight: 700; padding: 8px 12px; border-radius: 0 8px 8px 0;
}
.error { background: var(--pop); color: #fff; font-weight: 700; padding: 8px 12px; border-radius: 8px; }

.byline-card {
  position: fixed; right: 14px; bottom: 14px;
  background: var(--rail); border: 3px solid var(--ink); border-radius: 10px;
  box-shadow: var(--shadow-press);
  padding: 4px 10px; font-size: 13px; font-weight: 700;
  text-decoration: none;
}
.byline-card:hover { background: var(--gold); color: var(--ink); }

/* ---- track ---- */
.track-panel { background: var(--turf); border-color: var(--turf-dark); color: #fff; }
.track-panel h2 { color: #fff; }
.track {
  position: relative; margin-top: 14px; padding: 10px 0;
  background: repeating-linear-gradient(90deg, rgba(255,255,255,0.05) 0 2px, transparent 2px 60px);
  border-radius: 8px;
}
.lane { display: grid; grid-template-columns: 190px 1fr; gap: 10px; align-items: center; padding: 3px 0; }
.lane-label { font-size: 13px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lane-label a { color: #fff; text-decoration: none; }
.lane-strip {
  position: relative; height: 26px; border-bottom: 1px dashed rgba(255,255,255,0.28);
}
.runner {
  position: absolute; left: 0; top: 0; height: 26px;
  display: flex; align-items: center; gap: 4px;
  transform: translateX(0); transition: transform 90ms linear;
}
.silks {
  width: 14px; height: 14px; border-radius: 3px;
  background: var(--c1);
  border: 1px solid rgba(0,0,0,0.35);
}
.glyph { font-size: 18px; }
.finish-line {
  position: absolute; right: 0; top: 0; bottom: 0; width: 8px;
  background: repeating-linear-gradient(180deg, #fff 0 8px, #111 8px 16px);
  border-radius: 2px;
}

/* ---- finish order ----
   Every beaten horse is already carrying a distance, so the row draws it:
   one shared wire on the right, each runner standing back from it in
   proportion to the worst margin in the field. The number stays on the row
   because the picture is the impression and the number is the fact. */
.finish { list-style: none; margin: 0; padding: 0; }
.finish li {
  display: grid; align-items: center; gap: 10px;
  grid-template-columns: 26px 16px minmax(110px, 1.5fr) minmax(90px, 1fr) minmax(84px, 1.2fr) 64px 62px;
  position: relative; min-height: 34px; padding: 4px 8px 4px 14px;
  border-bottom: 1px solid var(--line); font-weight: 600;
  transition: background 120ms ease;
}
/* The running style is on the horse's own page. On this row it was a fifth
   thing to read on a line that only has to say who, how fast, how far. */
.finish .style-tag { display: none; }
/* The silks are the horse's identity, so they own the edge of its row. A
   pseudo element rather than a border, so the row divider stays a divider. */
.finish li::before {
  content: ""; position: absolute; left: 0; top: 2px; bottom: 2px; width: 6px;
  border-radius: 3px; background: linear-gradient(180deg, var(--c1), var(--c2));
}
.finish li:hover { background: rgba(18, 20, 15, 0.045); }
/* An empty state is a sentence, not a result row, so it opts out of the grid
   instead of being folded into the first 26px column. */
.finish li.fine { display: block; border-bottom: none; padding-left: 8px; }
.finish li.fine::before { content: none; }
.finish li.pos1 { background: linear-gradient(90deg, rgba(242,193,78,0.4), transparent); }
/* Long lists ship collapsed to the first ten rows; the toggle flips the class. */
.is-collapsed .overflow-row { display: none; }
.row-toggle { margin-top: 12px; }
.finish-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.finish-name .style-tag { margin-left: 6px; }
.pos {
  min-width: 26px; height: 26px; display: grid; place-items: center;
  background: var(--ink); color: var(--paper); border-radius: 50%;
  font-size: 13px; font-weight: 900;
}
.silk-dot {
  width: 14px; height: 14px; border-radius: 3px; display: inline-block;
  background: var(--c1);
  border: 1px solid rgba(0,0,0,0.3);
}
.finish .silk-dot { width: 16px; height: 16px; border-radius: 4px; }
.style-tag { font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; opacity: 0.6; }
/* The breeder credit is an attribution, not a runner, so it sits at the
   weight of the margin rather than of the name it follows. */
.finish-by {
  font-size: 13px; opacity: 0.6; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.finish .time { font-variant-numeric: tabular-nums; text-align: right; }
.finish .margin { font-size: 13px; opacity: 0.6; text-align: right; font-variant-numeric: tabular-nums; }

/* The photo of the wire, borrowing the live track's own language: dashed
   ground, striped post on the right, silks and a horse standing off it. */
.wire { position: relative; height: 26px; min-width: 90px; }
.wire::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 6px;
  border-bottom: 2px dashed rgba(18, 20, 15, 0.3);
}
/* The silks alone. The glyph was a third horse icon on a row that already
   had a silk dot, and at this size it read as noise rather than as a horse. */
.wire-runner { position: absolute; bottom: 4px; display: flex; align-items: center; }
.wire-runner .silks { width: 13px; height: 13px; }
.wire .finish-line {
  width: 6px; background: repeating-linear-gradient(180deg, var(--ink) 0 6px, #fff 6px 12px);
  border: 1px solid var(--ink); border-radius: 2px;
}
@media (max-width: 780px) {
  /* No room to read a picture and a number, so the number wins. The breeder
     credit goes with it: the podium above still carries the credit that
     matters most, and the name has to stay readable. */
  .finish li { grid-template-columns: 26px 16px 1fr auto 62px; }
  .wire, .finish-by { display: none; }
}

/* A named horse in the narration wears its own colours as a highlighter
   stripe. It was an underline, which put a dozen underlines in one paragraph
   and made the recap read as a page of links competing with the real ones.
   The gradient is carried by a pseudo element at low opacity rather than by
   the text's own background, so any silk pair lands at the same weight and
   the text itself stays ink on paper. */
.horse-ink {
  position: relative; isolation: isolate;
  font-weight: 700; color: var(--ink);
  padding: 1px 2px; border-radius: 3px;
}
.horse-ink::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: 3px; opacity: 0.18;
  background: linear-gradient(90deg, var(--c1), var(--c2));
}

/* A breeder credit inside narration is a real outbound link, so it reads as
   one, but quietly: a dotted underline rather than the highlighter used for
   horses, so a paragraph with both in it stays a paragraph. */
.breeder-ink {
  color: inherit; font-weight: 700;
  text-decoration: underline; text-decoration-style: dotted;
  text-underline-offset: 2px; text-decoration-thickness: 1px;
}
a.breeder-ink:hover { color: var(--pop); }

/* ---- CTAs ---- */
.cta-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin: 18px 0; }
@media (max-width: 780px) { .cta-row { grid-template-columns: 1fr; } }
.cta {
  display: block; text-decoration: none; padding: 24px;
  border: 3px solid var(--ink); border-radius: 14px; box-shadow: var(--shadow);
  background: var(--ink); color: var(--paper);
}
.cta:hover { transform: translate(2px, 2px); box-shadow: var(--shadow-press); }
.cta-k { display: block; font-size: 30px; font-weight: 900; letter-spacing: -0.03em; }
.cta-v { display: block; margin-top: 6px; opacity: 0.85; font-size: 15px; }

/* ---- the price ladder ---- */
/* This panel used to shout with a fat orange shadow. It is the most important
   card on the page because of where it sits and how big its number is, which
   is what earns rank; a louder shadow only made the page louder. */
.ladder-panel { text-align: center; }
.ladder-price { font-size: clamp(28px, 5vw, 44px); margin: 4px 0 0; letter-spacing: -0.03em; }
/* The next price is a fact under the headline, not a second call to action.
   It was orange, on a card that already had an orange button and an orange
   rung, which is three accents saying one thing. */
.ladder-next { font-size: 19px; font-weight: 800; margin: 4px 0 10px; opacity: 0.75; }
.ladder-panel .sell { margin: 0 auto 16px; max-width: 44ch; }
.ladder-line { font-weight: 700; }
.hero.small .sell { font-weight: 600; max-width: 52ch; }
.foal-stamp {
  display: inline-block; margin: 6px 0 0; padding: 2px 9px;
  border: 2px solid var(--ink); border-radius: 999px;
  font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em;
}

/* ---- buttons + forms ---- */
.btn {
  display: inline-block; background: var(--ink); color: var(--paper);
  border: 3px solid var(--ink); border-radius: 999px; padding: 10px 20px;
  font-weight: 800; text-decoration: none; cursor: pointer; font-size: 15px;
  /* A <button> does not inherit the page face or line-height, an <a> does.
     Pinning both here keeps a button pill and a link pill the same height. */
  font-family: inherit; line-height: 1.5;
}
.btn:hover { background: var(--pop); border-color: var(--pop); color: #fff; }
.btn.ghost { background: transparent; color: var(--ink); }
.btn.small { padding: 6px 14px; font-size: 13px; }
.btn.tiny { padding: 4px 10px; font-size: 12px; border-width: 2px; }
.btn.big { font-size: 19px; padding: 14px 26px; }

.stack { display: flex; flex-direction: column; gap: 12px; }
.stack label { font-size: 13px; font-weight: 700; display: block; }
input, select {
  display: block; width: 100%; margin-top: 4px; padding: 10px 12px;
  border: 2px solid var(--ink); border-radius: 8px; font-size: 16px;
  font-family: inherit; background: #fff;
}
input[type="color"] { height: 44px; padding: 4px; }
.colors { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.ticks { padding-left: 20px; }
.ticks li { margin: 6px 0; }

/* ---- standings ---- */
.standings { width: 100%; border-collapse: collapse; font-size: 15px; }
.standings th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.1em;
  border-bottom: 3px solid var(--ink); padding: 6px 8px;
}
.standings td { padding: 8px; border-bottom: 1px solid var(--line); }
/* Zebra first, so a wide row of small numbers stays trackable across the
   table; the silk bar second, so you can find a horse by its colours. */
.standings tbody tr:nth-child(even) { background: rgba(18, 20, 15, 0.035); }
.standings tbody tr:hover { background: rgba(18, 20, 15, 0.075); }
/* Seven columns do not fit a phone, and a table that will not shrink widens
   the whole document, which leaves every other panel on the page looking
   clipped. Let the table scroll inside itself instead of dragging the page
   sideways with it. */
@media (max-width: 780px) {
  .standings { display: block; overflow-x: auto; }
}
.std-name { position: relative; padding-left: 16px !important; }
.std-name::before {
  content: ""; position: absolute; left: 2px; top: 7px; bottom: 7px; width: 5px;
  border-radius: 3px; background: linear-gradient(180deg, var(--c1), var(--c2));
}
/* Ink, not turf: this badge is in a table, and there is no grass in a table. */
.owned { font-size: 11px; background: var(--ink); color: var(--paper); padding: 1px 6px; border-radius: 4px; font-weight: 800; }
/* The owner line is the fastest way to read what this game is, so it sits
   under every name rather than in a column people can skip. */
.bred-by { display: block; font-size: 12px; font-weight: 700; opacity: 0.75; }
.step-owner { margin: 2px 0 0; font-size: 12px; font-weight: 700; opacity: 0.75; }
/* On turf, the owner credit was ink on green at three quarters opacity,
   which is the one line on the podium nobody could read. */
.podium-panel .step-owner { opacity: 1; color: rgba(255, 255, 255, 0.85); }
.podium-panel .step-owner a { color: #fff; text-decoration-thickness: 1px; }
.podium-panel .step-owner a:hover { color: #fff; text-decoration-thickness: 3px; }

/* ---- stat card ---- */
.stable { display: grid; grid-template-columns: 1.15fr 1fr; gap: 20px; align-items: start; padding-top: 24px; }
@media (max-width: 860px) { .stable { grid-template-columns: 1fr; } }

.statcard {
  border: 4px solid var(--ink); border-radius: 18px; padding: 22px;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.92), rgba(255,255,255,0.98)),
    linear-gradient(135deg, var(--c1), var(--c2));
  box-shadow: var(--shadow); margin: 18px 0;
}
.statcard-top { display: flex; gap: 14px; align-items: center; border-bottom: 3px solid var(--ink); padding-bottom: 14px; }
.statcard-glyph {
  font-size: 34px; width: 62px; height: 62px; display: grid; place-items: center;
  border-radius: 14px; border: 3px solid var(--ink);
  background: var(--c1);
}
.statcard-name { margin: 0; font-size: clamp(26px, 5vw, 40px); font-weight: 900; letter-spacing: -0.03em; line-height: 1; }
.statcard-sub { margin: 4px 0 0; text-transform: uppercase; font-size: 12px; letter-spacing: 0.12em; font-weight: 800; opacity: 0.7; }

.bars { margin: 16px 0 6px; display: flex; flex-direction: column; gap: 9px; }
.bar { display: grid; grid-template-columns: 96px 1fr 34px; gap: 10px; align-items: center; }
.bar-label { font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em; }
.bar-track { height: 14px; background: rgba(18,20,15,0.12); border-radius: 7px; overflow: hidden; border: 2px solid var(--ink); }
.bar-fill { display: block; height: 100%; background: var(--c1); }
.bar-val { font-weight: 900; font-variant-numeric: tabular-nums; text-align: right; }
.budget-note { font-size: 12px; opacity: 0.6; margin: 4px 0 14px; }

.quirklist { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.quirk {
  border: 2px solid var(--ink); border-radius: 10px; padding: 9px 12px; background: #fff;
}
.quirk strong { display: block; font-size: 16px; }
.quirk em { display: block; font-size: 13px; opacity: 0.7; font-style: normal; }
.rarity {
  float: right; font-size: 10px; font-weight: 900; text-transform: uppercase;
  letter-spacing: 0.1em; padding: 2px 8px; border-radius: 999px;
  background: #ddd; border: 2px solid var(--ink);
}
/* Rarity is a ladder, so it is drawn as one: a ramp of ink, not three unrelated
   hues. Gold is reserved for the horse that actually won something. */
.r-common .rarity { background: transparent; }
.r-rare .rarity { background: rgba(18, 20, 15, 0.16); }
.r-legendary .rarity { background: var(--ink); color: var(--paper); }
.r-legendary { box-shadow: 0 0 0 2px var(--ink) inset; }
.hidden-trait { background: repeating-linear-gradient(45deg, #efefef 0 8px, #e5e5e5 8px 16px); }
.hidden-trait.revealed { background: #fff; }

.career { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.career li { font-size: 13px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 700; }
.career span { display: block; font-size: 30px; font-weight: 900; letter-spacing: -0.03em; }
.namelist { list-style: none; padding: 0; margin: 0; }
.namelist li { padding: 7px 0; border-bottom: 1px solid var(--line); }
.namelist .amt { float: right; font-weight: 800; }
.namelist em { display: block; font-size: 13px; opacity: 0.7; font-style: normal; }

/* ---- the live window ----
   The countdown stops being a footnote in the pre phase, because waiting is
   the product for twenty two hours a day. */
.bigcount {
  margin-top: 22px; padding: 18px 22px;
  border: 3px solid var(--ink); border-radius: 14px; background: var(--ink);
  color: var(--paper); box-shadow: var(--shadow);
  display: inline-block;
}
.bigcount .eyebrow { color: var(--on-dark-quiet); margin-bottom: 4px; }
.clockface {
  font-size: clamp(34px, 7vw, 62px); font-weight: 900; letter-spacing: -0.04em;
  margin: 0 0 12px; font-variant-numeric: tabular-nums; line-height: 1;
  background: none; color: inherit; padding: 0; border-radius: 0;
}
.hero-pre .clockface { font-size: clamp(40px, 9vw, 78px); }
.bigcount .btn.ghost { color: var(--paper); border-color: var(--paper); }
.bigcount .btn.ghost:hover { background: var(--pop); border-color: var(--pop); }
.bigcount .fine { display: block; margin-top: 8px; font-weight: 400; }
/* Supporting text on a dark card has ONE voice, shared with the foal card:
   15px, medium, the quiet on-dark tone. Two cards side by side with two
   different supporting styles read as two different products. */
.bigcount .sell { max-width: 48ch; margin: 0 0 14px; font-size: 15px; font-weight: 500; color: var(--on-dark-quiet); }
.livedot {
  background: var(--pop); color: #fff; padding: 1px 8px; border-radius: 999px;
  font-weight: 900; letter-spacing: 0.1em;
}
.live-note { max-width: 640px; }
/* Playback drives transform every animation frame, so a CSS transition on
   top of it would fight the interpolation and lag behind the field. */
.track-panel[data-live="1"] .runner { transition: none; }

/* ---- the commentary ticker ---- */
.ticker {
  margin-top: 16px; padding-top: 14px;
  border-top: 2px dashed rgba(255, 255, 255, 0.3);
}
.ticker-head { color: var(--on-dark-quiet); margin-bottom: 10px; }
.ticker-head .livedot { margin-right: 6px; }
.ticker-feed {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 6px;
  max-height: 190px; overflow-y: auto;
}
.ticker-feed li {
  background: rgba(0, 0, 0, 0.22); border-left: 4px solid rgba(255, 255, 255, 0.4);
  border-radius: 0 8px 8px 0; padding: 8px 12px;
  font-size: 15px; font-weight: 600; line-height: 1.35;
  opacity: 0; transform: translateY(-6px);
  transition: opacity 320ms ease, transform 320ms cubic-bezier(.2,.8,.2,1);
}
.ticker-feed li.in { opacity: 1; transform: none; }
/* The newest call is the one being shouted, so it stays the loud one, and it
   is the only line in the feed that gets to spend the accent. */
.ticker-feed li:first-child {
  background: rgba(0, 0, 0, 0.34); color: #fff; border-left-color: var(--pop);
}
.ticker-feed li:not(:first-child) { opacity: 0.72; font-weight: 500; }
.ticker-feed li:not(:first-child).in { opacity: 0.72; }
@media (prefers-reduced-motion: reduce) {
  .ticker-feed li { transition: none; }
}
/* Mid-race holding panel: an urgent state, so it borrows the accent as an edge
   rather than as a full gold fill. */
.holding { border-color: var(--pop); }
.holding .big { font-size: 30px; }

/* ---- the podium ----
   WHY this replaces the track outside the live window: the race is an
   event. If you can scrub back through it all evening there is no reason to
   turn up at 17:00. What survives the day is a result, so the result gets
   the big treatment and the animation gets deleted. */
.podium-panel { background: var(--turf); border-color: var(--turf-dark); color: #fff; }
.podium-panel h2, .podium-panel .fine { color: #fff; }
/* The eyebrow's default muted ink disappears on a turf panel, so it lightens
   rather than changing hue. It was gold, which said "winner" above a panel
   where only one of the three horses won anything. */
.podium-panel .eyebrow, .track-panel .eyebrow { color: var(--on-dark-quiet); }
/* The rostrum is one structure, not three cards. The columns carry no
   gutter and the plinths sit flush against each other on a shared ground
   line, so the three steps read as a single object that the horses are
   standing on. */
.podium {
  display: grid; grid-template-columns: 1fr 1.3fr 1fr;
  align-items: end; gap: 0; margin: 20px auto 14px;
  /* Capped so the rostrum keeps its proportions on a wide screen instead of
     stretching into a low letterbox that reads as three bars. */
  max-width: 720px;
  border-bottom: 4px solid var(--ink);
}
.step { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; }
.step p { margin: 0; }
.step-body {
  display: flex; flex-direction: column; align-items: center;
  text-align: center; padding: 0 8px 10px; gap: 2px;
}
.silk-block {
  width: 46px; height: 46px; display: grid; place-items: center;
  border: 3px solid var(--ink); border-radius: 12px; margin-bottom: 6px;
  background: var(--c1);
  box-shadow: var(--shadow-press);
}
.silk-block .glyph { font-size: 24px; }
/* Gold is legitimate here: this is the winner. It is the light around the
   block, not a second shadow colour, so the offset stays ink like everywhere. */
.step-1 .silk-block {
  width: 70px; height: 70px; border-radius: 14px;
  box-shadow: var(--shadow-press), 0 0 20px rgba(242, 193, 78, 0.45);
  animation: winner-in 620ms cubic-bezier(.2,.9,.25,1.2) both;
}
.step-1 .silk-block .glyph { font-size: 36px; }
/* The winner arrives; the other two were already there. One beat on load,
   never on a loop, so the page settles instead of fidgeting. */
@keyframes winner-in {
  from { opacity: 0; transform: translateY(14px) scale(0.86); }
  to { opacity: 1; transform: none; }
}
.step-name { font-size: 15px; font-weight: 900; letter-spacing: -0.02em; line-height: 1.15; }
.step-name a { color: #fff; text-decoration: none; }
.step-name a:hover { color: #fff; text-decoration: underline; text-decoration-thickness: 3px; }
.step-1 .step-name { font-size: 21px; }
.step-time { font-weight: 800; font-variant-numeric: tabular-nums; font-size: 15px; }
.step-1 .step-time { font-size: 17px; }
.step-margin { font-size: 12px; opacity: 0.72; }

/* Open at the bottom so every plinth stands on the podium's ground line,
   and pulled together horizontally so neighbouring borders overlap into one
   shared edge instead of stacking into a six pixel seam. */
.plinth {
  width: 100%; height: 44px; display: grid; place-items: center;
  border: 3px solid var(--ink); border-bottom: none; border-radius: 0;
  background: rgba(255, 255, 255, 0.14);
}
.plinth-num {
  font-size: 26px; font-weight: 900; line-height: 1; letter-spacing: -0.03em;
  color: rgba(255, 255, 255, 0.85);
}
.step-1 .plinth {
  height: 128px; border-radius: 6px 6px 0 0; margin: 0 -3px;
  /* Gold reads as metal when it has a light on it, and as a flat swatch
     when it does not. The gradient is the light. */
  background: linear-gradient(180deg, #ffe6a3 0%, var(--gold) 42%, #c8942b 100%);
  box-shadow: 0 -6px 26px rgba(242, 193, 78, 0.35);
}
.step-1 .plinth-num { font-size: 46px; color: var(--ink); }
.step-2 .plinth { height: 88px; border-radius: 6px 0 0 0; }
.step-3 .plinth { height: 62px; border-radius: 0 6px 0 0; }

@media (max-width: 700px) {
  /* No rostrum on a phone: three stacked columns cannot step. The plinth
     becomes a slim numbered bar under each horse, which keeps the ranking
     obvious without pretending to be a structure. */
  .podium { grid-template-columns: 1fr; align-items: stretch; border-bottom: none; }
  /* The 2, 1, 3 arrangement is a rostrum's shape, and a rostrum needs three
     columns. Stacked into one, it just looks like the wrong order, so put
     the finishers back into finishing order. */
  .step-1 { order: 1; }
  .step-2 { order: 2; }
  .step-3 { order: 3; }
  .step { margin-bottom: 14px; }
  .step-1 .step-name { font-size: 24px; }
  .plinth, .step-1 .plinth, .step-2 .plinth, .step-3 .plinth {
    height: 34px; border-radius: 8px; border-bottom: 3px solid var(--ink); margin: 0;
  }
  .plinth-num, .step-1 .plinth-num { font-size: 20px; }
}

/* ---- feuds ---- */
/* A dormant side panel does not get the page's accent. It is a panel. */
.feudlist { list-style: none; margin: 0; padding: 0; }
.feudlist li { padding: 9px 0; border-bottom: 1px solid var(--line); }
.feudlist strong { display: block; font-size: 19px; letter-spacing: -0.02em; }
.feud-pair { display: block; font-size: 15px; font-weight: 700; }
.feudlist .fine { display: block; }
.feudlist em { display: block; font-size: 13px; opacity: 0.7; font-style: normal; }
.cta-row-3 { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 980px) { .cta-row-3 { grid-template-columns: 1fr; } }

/* ---- the paper ----
   The recap is a written report of something that already happened, which is
   what a newspaper is, so the post-race panel is set as one. The rest of the
   site is sans-serif ink on cream inside rounded, hard-shadowed cards; the
   paper is serif on a whiter stock with square corners and hairline rules and
   no shadow at all. Nothing about it is borrowed from the panel language,
   which is the point: it should read as a sheet lying on the page.

   It runs full width because two columns of body text need the width. The
   rest of the field, which used to sit beside the recap, now sits under the
   paper at full width rather than alone in half a grid. */
.newspaper {
  margin: 18px 0 0; padding: 22px 26px 18px;
  background: #fbfaf5; color: #17170f;
  border: 1px solid rgba(23, 23, 15, 0.55);
  border-radius: 0;
  font-family: Georgia, "Iowan Old Style", "Times New Roman", Times, serif;
}
.np-masthead { border-bottom: 1px solid rgba(23, 23, 15, 0.5); padding-bottom: 8px; }
.np-name {
  margin: 0; text-align: center; line-height: 1;
  font-size: clamp(26px, 5.6vw, 52px); font-weight: 700;
  letter-spacing: 0.02em; text-transform: uppercase;
}
/* Hairline over hairline: the double rule under a masthead is the one piece
   of newspaper furniture worth copying literally. */
.np-dateline {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px 18px;
  margin: 8px 0 0; padding-top: 6px;
  border-top: 1px solid rgba(23, 23, 15, 0.3);
  font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.12em; font-variant-numeric: tabular-nums;
}
.np-headline {
  margin: 18px 0 0; text-align: center;
  font-size: clamp(30px, 6.4vw, 60px); line-height: 0.98;
  font-weight: 700; letter-spacing: -0.015em; text-transform: uppercase;
  text-wrap: balance;
}
.np-deck {
  margin: 8px 0 14px; text-align: center;
  font-size: clamp(15px, 2.2vw, 19px); font-style: italic;
  padding-bottom: 14px; border-bottom: 3px double rgba(23, 23, 15, 0.5);
}
/* Two columns of newsprint, with the quote and the agate box allowed to break
   across them so the page sets itself rather than being laid out by hand. */
.np-body { columns: 2; column-gap: 34px; column-rule: 1px solid rgba(23, 23, 15, 0.22); }
.np-story {
  margin: 0; font-size: 16px; line-height: 1.52; text-align: justify;
  hyphens: auto;
  /* The commentator writes in paragraphs and HTML was collapsing them into
     one slab. In a column of newsprint that slab is the whole story, so the
     breaks the writer put in are kept. */
  white-space: pre-line;
}
/* No drop cap: the lede's first word is often a horse wearing its silks as a
   highlighter, and a floated first letter cuts that overlay in half. */
.np-lede { font-weight: 700; }
.np-quote {
  break-inside: avoid; margin: 16px 0 0; padding: 12px 0;
  border-top: 1px solid rgba(23, 23, 15, 0.5);
  border-bottom: 1px solid rgba(23, 23, 15, 0.5);
}
.np-quote p { margin: 0; font-size: 17px; line-height: 1.4; font-style: italic; }
.np-quote-head {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 10px; font-weight: 800; letter-spacing: 0.16em;
  text-transform: uppercase; font-style: normal !important;
  margin: 0 0 6px !important; opacity: 0.65;
}
.np-quote cite {
  display: block; margin-top: 8px; font-size: 12px; font-style: normal;
  font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; opacity: 0.7;
}
/* The agate box: the same three finishers as the podium, in the small ruled
   type a paper prints results in. */
.np-result {
  break-inside: avoid; margin: 16px 0 0; padding: 8px 10px;
  border: 1px solid rgba(23, 23, 15, 0.55);
}
.np-result-head {
  margin: 0 0 4px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 10px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase;
}
.np-result ol { list-style: none; margin: 0; padding: 0; }
.np-result li {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 13px; line-height: 1.5;
  border-bottom: 1px dotted rgba(23, 23, 15, 0.35);
}
.np-result li:last-child { border-bottom: none; }
.np-pos { font-weight: 700; min-width: 12px; font-variant-numeric: tabular-nums; }
.np-runner { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.np-time { font-variant-numeric: tabular-nums; }
/* The horse ink highlighter is tuned for the site's cream; on newsprint it
   only has to be a shade, so it drops back and keeps the columns readable. */
.newspaper .horse-ink::before { opacity: 0.14; }
.newspaper .horse-ink { font-weight: 700; }
@media (max-width: 780px) {
  /* One column, and the masthead gives back the size it was borrowing. */
  .newspaper { padding: 16px 16px 14px; }
  .np-body { columns: 1; }
  .np-story { text-align: left; hyphens: manual; }
  .np-dateline { justify-content: flex-start; font-size: 11px; letter-spacing: 0.08em; }
  .np-headline { margin-top: 14px; }
}

/* ---- foal reveal ---- */
.reveal { padding: 40px 0; text-align: center; }
.reveal h1 { font-size: clamp(44px, 9vw, 92px); margin: 0; font-weight: 900; letter-spacing: -0.04em; text-transform: uppercase; line-height: 0.95; }
.reveal-sub { font-size: 20px; font-weight: 600; }
.reveal .statcard { text-align: left; max-width: 640px; margin: 24px auto; }
.reveal-step { opacity: 0; transform: translateY(18px) scale(0.98); transition: opacity 520ms ease, transform 520ms cubic-bezier(.2,.8,.2,1); }
.reveal-step.in { opacity: 1; transform: none; }
.reveal-actions { display: flex; gap: 12px; justify-content: center; align-items: center; flex-wrap: wrap; }

/* ---- the weather ----
   There is no overlay. Ambient streaks over the podium turned a result into
   a screensaver: the eye tracked the moving lines instead of the finish, and
   a panel you have to read is the wrong place to put motion. The weather
   still ships on the panel as a class and reads as the emoji in the eyebrow,
   which is the whole of what it needs to say. */

/* ---- the last hour ----
   Twenty two hours of countdown look the same, which is correct, right up
   until they are not. "soon" is the last hour, "imminent" the last five
   minutes; race.js decides when, this decides what it looks like. */
/* This is the one place the accent is allowed to take over a whole card: the
   race is about to start, which is the only genuinely urgent state the site
   has. The shadow keeps its shared geometry and only changes colour. */
.bigcount.soon { box-shadow: 5px 5px 0 var(--pop); border-color: var(--pop); }
/* #clock carries the base colour, so the hot state has to answer it. */
.bigcount.soon #clock.clockface { color: var(--pop); }
.bigcount.soon .eyebrow { color: var(--pop); }
.bigcount.imminent .clockface { animation: clock-pulse 1s ease-in-out infinite; }
@keyframes clock-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.035); }
}
@media (prefers-reduced-motion: reduce) {
  .bigcount.imminent .clockface { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  .step-1 .silk-block { animation: none; }
}

/* ---- the top row ----
   The countdown and the price are the two numbers on this page that cost
   something, so they wear the same clothes and stand next to each other. */
.top-row {
  display: grid; grid-template-columns: 1fr 1fr; gap: 18px;
  /* Stretch, not start: two dark tiles of different heights leave a slab of
     paper hanging under the shorter one and stop reading as a pair. */
  align-items: stretch; margin: 22px 0 0;
}
.top-row-single { grid-template-columns: 1fr; }
/* The countdown has less to say than the price does, so it spends the
   difference on space rather than letting the card end early. */
.top-row .bigcount {
  display: flex; flex-direction: column; width: 100%; height: 100%; margin-top: 0;
  /* Same padding as .panel, so the two cards' contents start and end on the
     same lines. */
  padding: 20px 22px;
}
/* Both cards pin sell → button → fine to the foot of the tile, so the three
   rows land on the same lines in both. Spare height goes above the sell. */
.top-row .bigcount .sell { margin-top: auto; margin-bottom: 0; }
/* The auto margins above absorb spare height, but when the card is exactly
   full they collapse to nothing and the button touches the text. The button
   carries its own minimum gap so that can't happen. */
.top-row .bigcount .btn { align-self: flex-start; margin-top: 14px; }
/* One footer rhythm for both tiles: same gap above the fine print, none
   below, so the last line of each card sits on the same baseline. */
.top-row .bigcount .fine, .top-row .ladder-panel .fine { margin: 10px 0 0; }
/* Same column mechanics as the countdown, so the two cards distribute their
   contents the same way and both pills land on the same line. */
.top-row .ladder-panel { margin: 0; display: flex; flex-direction: column; }
.foal-led .btn { align-self: flex-start; margin-top: 14px; }
/* .btn defaults to ink on ink, which on this card is an invisible button. Any
   pill here that is not the primary orange one is a ghost, whether the
   template remembered to say so or not. */
.ladder-panel .btn:not(.big) {
  background: transparent; color: var(--paper); border-color: var(--paper);
}
.ladder-panel .btn.ghost { color: var(--paper); border-color: var(--paper); }
.ladder-panel .btn:not(.big):hover,
.ladder-panel .btn.ghost:hover { background: var(--pop); border-color: var(--pop); color: #fff; }
/* Half a page is not the whole page, so the clock gives back some of the
   size it was borrowing from the hero. */
.top-row .clockface { font-size: clamp(34px, 5.8vw, 72px); margin-bottom: 4px; }
@media (max-width: 860px) {
  /* Stacked, the countdown comes first: it is the thing with a deadline. */
  .top-row { grid-template-columns: 1fr; }
  .top-row .clockface { font-size: clamp(34px, 9vw, 62px); }
  .top-row .bigcount .sell { margin-top: 0; margin-bottom: 14px; }
}
.ladder-panel {
  background: var(--ink); color: var(--paper); border-color: var(--ink);
}
/* .ladder-price was always authored as a headline and always lost to
   .panel h2, which is more specific. The price is the whole card, so it
   gets the size it was asking for. */
.ladder-panel .ladder-price {
  font-size: clamp(24px, 3.4vw, 38px); text-transform: none;
  letter-spacing: -0.03em; line-height: 1.05;
}
.ladder-panel .eyebrow { color: var(--on-dark-quiet); }
/* Same supporting voice as .bigcount .sell above. */
.ladder-panel .sell { font-size: 15px; font-weight: 500; color: var(--on-dark-quiet); }
/* The one orange button on the page. Its hover darkens the same orange rather
   than swapping to gold, which used to make the primary CTA read as a prize. */
.ladder-panel .btn.big { background: var(--pop); border-color: var(--pop); color: #fff; }
.ladder-panel .btn.big:hover { background: var(--pop-dark); border-color: var(--pop-dark); color: #fff; }
/* The countdown card's answer to the staircase: same spot (between the sell
   line and the button), same left alignment, same footprint. */
.forecast-block {
  margin: 12px 0 0; display: flex; flex-direction: column;
  align-items: flex-start; gap: 6px;
}
.forecast-emoji { font-size: 36px; line-height: 1; }
.forecast-label {
  font-size: 11px; font-weight: 800; letter-spacing: -0.02em;
  color: var(--on-dark-quiet);
}
.ladder-steps {
  list-style: none; margin: 18px auto 20px; padding: 0;
  display: flex; align-items: flex-end; justify-content: center; gap: 6px;
}
.rung { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.rung-bar {
  display: block; width: 34px; border-radius: 4px 4px 0 0;
  height: calc(14px + var(--h) * 9px);
  background: rgba(244, 239, 226, 0.22);
}
.rung-price {
  font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums;
  opacity: 0.6; letter-spacing: -0.02em;
}
/* The step you can actually buy is the only one that is lit, and it is
   marked rather than captioned. Flat orange, not a gold-to-orange gradient:
   the rung is the current price, not a trophy. */
.rung-now .rung-bar { background: var(--pop); }
.rung-now .rung-price { opacity: 1; font-size: 14px; color: var(--pop); }
.rung-now::before { content: "▼"; font-size: 12px; color: var(--on-dark-quiet); line-height: 1; }
/* The rung nobody has bought yet: outline only, so the doubling is drawn
   without the step reading as available. Border-box keeps it on the same
   baseline as the solid bars. */
.rung-next .rung-bar {
  box-sizing: border-box; background: none;
  border: 2px dashed rgba(244, 239, 226, 0.35); border-bottom: 0;
}
@media (max-width: 700px) {
  .rung-bar { width: 22px; }
  .rung-price { font-size: 10px; }
}

/* ---- the latest foal ----
   The last person to buy a rung, leading the card that sells the next one.
   Same anatomy as the countdown: eyebrow, one big thing, small supporting
   text, ghost pill at the foot. The foal is this card's clock. */
.foal-led { text-align: left; }
.foal-led .eyebrow { color: var(--on-dark-quiet); }
.foal-hero { display: flex; align-items: center; gap: 14px; margin: 6px 0 4px; }
.foal-hero .silk-block {
  flex: 0 0 auto; width: 62px; height: 62px; border-radius: 14px;
  /* Same offset geometry as every other block, but an ink shadow vanishes
     against this card's own ink background, so it flips to paper. */
  border-width: 3px; margin-bottom: 0; box-shadow: 3px 3px 0 rgba(244, 239, 226, 0.28);
}
.foal-hero .silk-block .glyph { font-size: 32px; }
.foal-meta { min-width: 0; }
.foal-name {
  display: block; font-size: clamp(26px, 3.6vw, 44px); font-weight: 900;
  letter-spacing: -0.035em; line-height: 1.02;
}
.foal-name a { color: var(--paper); text-decoration: none; }
.foal-name a:hover { color: var(--pop); text-decoration: underline; }
/* The owner's link defaults to ink, which is the card's own background. */
.foal-meta .bred-by { opacity: 0.6; }
.foal-meta .bred-by a { color: inherit; }
.foal-meta .bred-by a:hover { color: var(--pop); }
/* The receipt is this card's accent. When the card is foal-led its button is a
   ghost pill, so the orange is spent here and nowhere else on the card. */
.foal-paid {
  display: block; font-weight: 900; font-size: 13px;
  font-variant-numeric: tabular-nums; color: var(--pop);
}

/* The price demoted to supporting text. Every word it had, none of the
   headline treatment, because the card now leads with the horse. */
.foal-led .ladder-lines { margin-top: auto; margin-bottom: 0; padding-top: 14px; }
.foal-led .ladder-lines .eyebrow { color: var(--on-dark-quiet); opacity: 0.75; margin-bottom: 2px; }
.foal-led .ladder-price {
  font-size: 17px; font-weight: 800; letter-spacing: -0.01em; margin: 0;
}
.foal-led .ladder-next { font-size: 15px; font-weight: 700; margin: 2px 0 0; }
.foal-led .sell { margin: 8px 0 0; max-width: none; }
.foal-led .ladder-steps { margin: 12px 0 0; justify-content: flex-start; }
.foal-led .rung-bar { width: 22px; height: calc(10px + var(--h) * 6px); }
.foal-led .rung-price { font-size: 10px; }
.foal-led .rung-now .rung-price { font-size: 11px; }

/* ---- links ----
   One hover behaviour everywhere a horse is named, and a focus ring that is
   visible on both the paper and the turf. */
.step-name a, .lane-label a, .finish-name a, .std-name > a {
  display: inline-block; transition: transform 120ms ease;
}
.step-name a:hover, .lane-label a:hover, .finish-name a:hover, .std-name > a:hover {
  transform: translateY(-1px);
}
.finish-name a:hover, .std-name > a:hover {
  text-decoration-color: var(--c1); text-decoration-thickness: 3px;
}
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible {
  outline: 3px solid var(--pop); outline-offset: 2px; border-radius: 4px;
}
.track-panel a:focus-visible, .podium-panel a:focus-visible, .bigcount a:focus-visible,
.bigcount button:focus-visible, .ladder-panel a:focus-visible {
  /* Paper, not gold: a focus ring is not a result. It reads on both the turf
     and the ink cards, which is the whole job. */
  outline-color: var(--paper);
}
.cta-price { opacity: 0.75; font-weight: 800; }
@media (prefers-reduced-motion: reduce) {
  .step-name a, .lane-label a, .finish-name a, .std-name > a { transition: none; }
  .step-name a:hover, .lane-label a:hover, .finish-name a:hover, .std-name > a:hover { transform: none; }
}
