/*
 * Race area: two cabin cards, clocks, control bar, and the time-split bars.
 *
 * Desktop: cards stack vertically, canvas fills the card, horizontal orientation.
 * Phone (< 900 px): the two canvases sit side by side in vertical orientation, each half width.
 * Only the moving passenger dots on the canvas are saturated; everything else is a gray on paper.
 */

.race {
  display: flex;
  flex-direction: column;
  gap: var(--gap-m);
  margin-top: var(--gap-l);
}

.race .cabin-card {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-l);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.race .cabin-card.winner .clock { color: var(--moving); font-weight: 700; }

.card-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: var(--gap-m);
  align-items: center;
  min-height: 46px;
}

.card-header .strategy-picker {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  justify-self: start;
}

.card-header .strategy-picker select {
  font-size: 15px;
  font-weight: 600;
  padding: 8px 26px 8px 8px;
  border-color: transparent;
  background-color: transparent;
  /* Bumped from 34 px to 44 px (round-02 NEW-m4 carry-over): the strategy dropdown is the
   * primary tap target on each cabin card and must meet the spec. */
  min-height: var(--tap);
  min-width: 12ch;
  max-width: 40ch;
  color: var(--ink);
}
.card-header .strategy-picker select:hover {
  border-color: var(--rule);
  background-color: var(--paper-2);
}

.card-header .strategy-picker .blurb {
  font-size: 12px;
  color: var(--ink-muted);
  line-height: 1.3;
  max-width: 46ch;
  padding-left: 8px;
  min-height: 1em;
}

.card-header .count {
  text-align: center;
  color: var(--ink-soft);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  justify-self: center;
}
.card-header .count .num { color: var(--ink); font-weight: 600; }

.card-header .clock-block {
  justify-self: end;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0;
  line-height: 1;
}

.card-header .clock {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: clamp(28px, 4.4vw, 36px);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.01em;
}

.card-header .clock.pre-door {
  color: var(--ink-muted);
  font-weight: 500;
}

.card-header .margin {
  font-size: 12px;
  color: var(--moving);
  font-weight: 600;
  min-height: 1em;
  margin-top: 2px;
}
.card-header .margin.behind { color: var(--ink-soft); }

.card-header .door-status {
  font-size: 11px;
  color: var(--ink-muted);
  font-style: italic;
  min-height: 1em;
  margin-top: 1px;
}

/* Canvas fills the card. Height is set inline from js/ui/race.js based on the layout: seat
   columns plus aisles determine the vertical (long-axis) space we need so a 777 draws bigger than
   a CRJ instead of both being clamped to a fixed 180 px. */

.canvas-wrap {
  position: relative;
  width: 100%;
  overflow: hidden;
  border-radius: var(--radius-m);
  background: var(--paper);
}

.canvas-wrap canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: pointer;
}

.canvas-wrap .tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--ink);
  color: var(--paper);
  font-size: 12px;
  padding: 4px 8px;
  border-radius: 6px;
  white-space: nowrap;
  transform: translate(-50%, calc(-100% - 8px));
  opacity: 0;
  transition: opacity 0.12s ease-out;
  z-index: 2;
}
.canvas-wrap .tooltip.on { opacity: 1; }
@media (hover: none) { .canvas-wrap .tooltip { display: none; } }

.race-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  padding: 2px 4px 0;
  color: var(--ink-muted);
  font-size: 12px;
  margin: 0;
  min-height: 1.2em;
}
.cabin-card[data-lane="b"] .race-legend {
  /* Present but non-informative under lane B so both cards keep the same height. When the heat
   * view is on, this same slot carries the heat caption (see .heat-caption). Screen readers are
   * told to skip via aria-hidden="true" in index.html. */
  visibility: hidden;
}
.cabin-card[data-lane="b"] .race-legend.heat-caption { visibility: visible; }

.race-legend.heat-caption {
  gap: 6px 10px;
  color: var(--ink-soft);
}
.race-legend.heat-caption .swatch { display: none; }
.race-legend.heat-caption .heat-ramp {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.race-legend.heat-caption .heat-ramp .bar {
  width: 80px;
  height: 8px;
  border-radius: 2px;
  background: linear-gradient(90deg, #f0e4d2 0%, #c99f5a 50%, #382507 100%);
  display: inline-block;
}
.race-legend.heat-caption .heat-ramp .end { color: var(--ink-muted); font-size: 11px; }
.race-legend.heat-caption .heat-caption-text {
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
}
.race-legend .swatch {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  position: relative;
}
.race-legend .swatch::before {
  content: "";
  width: 9px; height: 9px;
  border-radius: 999px;
  background: currentColor;
  display: inline-block;
  flex: 0 0 auto;
}
.race-legend .swatch.moving  { color: var(--moving); }
.race-legend .swatch.blocked { color: var(--blocked); }
.race-legend .swatch.blocked::before { background: transparent; border: 1.5px solid currentColor; }
.race-legend .swatch.bag { color: var(--blocked); }
.race-legend .swatch.bag::before {
  background: transparent;
  border: 1.5px solid currentColor;
}
/* NEW3-m1: the amber square must sit INSIDE the ring so the legend teaches "bag = amber glyph
 * inside a hollow ring". The prior rule appended it after the text with margin-left: -8px,
 * which landed the square on the descender of "g" and read as a rendering fault on the one
 * element whose job is to teach the colour language. Absolute-positioning it on top of the
 * ring pin keeps the geometry stable across font-size and gap tweaks. */
.race-legend .swatch.bag::after {
  content: "";
  width: 5px; height: 5px;
  border-radius: 1px;
  background: var(--bag);
  position: absolute;
  left: 2px;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
}
.race-legend .swatch.seated  { color: #a9a193; }

.follow-line {
  padding: 2px 4px 0;
  color: var(--ink-soft);
  font-size: 12px;
  min-height: 1.2em;
  margin: 0;
}
.follow-line.stable { color: var(--ink); font-weight: 500; }

.live-gap {
  padding: 0 4px;
  color: var(--ink);
  font-size: clamp(18px, 3vw, 24px);
  font-weight: 700;
  min-height: 1.2em;
  margin: 0;
}
.live-gap:empty { display: none; }

/* Suppress the door-status line the moment it goes empty so the header layout stops carrying an
 * invisible line that reads as a permanent gap in the card once the door has opened. */
.card-header .door-status:empty { display: none; }

/* Phone: two cabins side by side, vertical, each half width. Keep the legend compact but visible;
   B3 in the critic pass was `display: none` here, which stranded a phone visitor with no key. */
@media (max-width: 899px) {
  .race { flex-direction: row; gap: 8px; }
  .race .cabin-card { flex: 1 1 0; min-width: 0; padding: 10px 8px 8px; gap: 6px; }
  .card-header {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
    gap: 4px;
    text-align: left;
  }
  .card-header .strategy-picker { justify-self: stretch; }
  .card-header .strategy-picker select { width: 100%; font-size: 14px; }
  .card-header .strategy-picker .blurb { display: none; }
  .card-header .count { justify-self: start; }
  .card-header .clock-block { justify-self: start; align-items: flex-start; }
  .card-header .clock { font-size: 24px; }

  /* Compact legend at phone width: one line, wrap allowed. Lane B keeps a hidden placeholder
   * so both card heights stay equal. */
  .race-legend {
    font-size: 11px;
    gap: 4px 10px;
    padding: 2px 2px 0;
  }
  .cabin-card[data-lane="b"] .race-legend {
    visibility: hidden;
    height: 1.2em;
    overflow: hidden;
  }
  .cabin-card[data-lane="b"] .race-legend.heat-caption {
    visibility: visible;
    height: auto;
    overflow: visible;
  }
}

/* Race-controls row: sits directly under the finish-card slot so Restart, speed, seed, heat
 * toggle, and chime are always visible when a race is running or has just finished. NEW-M3
 * moved these out of the deep-below-fold controls block. */
.race-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin-top: var(--gap-s);
  padding: 8px 4px;
}

.race-controls .spacer { flex: 1 1 auto; }
.race-controls button,
.race-controls .segmented .seg {
  min-height: var(--tap);
}
.race-controls #btn-race {
  min-width: 96px;
  padding: 10px 20px;
  font-size: 14px;
}
.race-controls .segmented .seg {
  padding: 10px 16px;
  font-size: 13px;
}
.race-controls .seed-row {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.race-controls .seed-row button {
  padding: 8px 12px;
  font-size: 13px;
}
.race-controls .seed-row input[type="text"] {
  width: 14ch;
  min-height: 40px;
  font-size: 13px;
}

.race-controls .heat-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink-soft);
  font-size: 13px;
  cursor: pointer;
}
.race-controls .heat-toggle:hover { border-color: var(--ink); color: var(--ink); }
.race-controls .heat-toggle.on { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.race-controls .heat-toggle::before {
  content: "";
  width: 44px;
  height: 8px;
  border-radius: 2px;
  display: inline-block;
  background: linear-gradient(90deg, #f0e4d2 0%, #c99f5a 50%, #382507 100%);
  flex: 0 0 auto;
}

/* Control bar (knobs only, below the race controls). */

.controls {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-l);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: var(--gap-m);
}

.control-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 14px;
  align-items: center;
}

.control-row .grow { flex: 1 1 auto; }
.control-row .spacer { flex: 1 1 auto; }

.knob {
  display: inline-flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.knob .knob-label {
  color: var(--ink-muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
}
.knob .knob-value {
  color: var(--ink-soft);
  font-size: 12px;
  min-height: 1em;
  font-variant-numeric: tabular-nums;
}

.knob.slider { min-width: 180px; flex: 1 1 180px; }
.knob.slider input[type="range"] { min-height: 24px; }

.knob.pick select { min-width: 12ch; }

.seed-row {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.seed-row input[type="text"] { width: 12ch; font-size: 13px; }

.more-knobs {
  border-top: 1px dashed var(--rule);
  padding-top: 12px;
  margin-top: 4px;
}
.more-knobs summary {
  cursor: pointer;
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 500;
  padding: 4px 0;
}
.more-knobs summary:focus-visible { outline: 2px solid var(--moving); outline-offset: 2px; }
.more-knobs[open] summary { color: var(--ink); }
.more-knobs .grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px 18px;
  padding-top: 10px;
}

/* Time-split section */

.time-split {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.time-split .header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-m);
  flex-wrap: wrap;
}
.time-split .toggle-row .segmented .seg { padding: 4px 10px; font-size: 12px; }
.time-split .bar-row {
  display: grid;
  grid-template-columns: minmax(120px, 22%) 1fr;
  gap: 12px;
  align-items: center;
}
.time-split .bar-label {
  color: var(--ink-soft);
  font-size: 12px;
  font-weight: 500;
}
.time-split .bar-label .strat {
  color: var(--ink);
  font-weight: 600;
  display: block;
  font-size: 13px;
}
.time-split .bar-label .total {
  color: var(--ink);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  display: block;
  margin-top: 2px;
  font-size: 12px;
}
.time-split svg { width: 100%; height: auto; display: block; }

@media (max-width: 620px) {
  .time-split .bar-row { grid-template-columns: 1fr; gap: 4px; }
}

.time-split .bar-wrap { min-width: 0; }
.time-split .below-labels {
  margin-top: 4px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 11px;
  color: var(--ink-muted);
}
.time-split .below-labels .chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.time-split .below-labels .swatch {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  display: inline-block;
}

/* Follow-active state on the split-target toggle: while a passenger is being followed, both
 * Last and Average read as inactive so the toggle stops claiming ownership of a state the UI
 * is not in. Round-01 n3 / round-02 NEW-m5: the toggle used to stay lit on "Last" while the
 * subtitle simultaneously named a followed passenger and the follow line described them, three
 * surfaces disagreeing at once. Now the group carries `.following` for the CSS below and the
 * subtitle names the followed seat. */
.time-split .toggle-row .segmented.following .seg {
  background: transparent;
  color: var(--ink-muted);
  opacity: 0.65;
}

/* Compare "Run it" button: bump to the 44 px tap-target spec (round-02 NEW-m4 carry-over). */
.compare .controls-row #btn-compare {
  min-height: var(--tap);
  padding: 10px 22px;
  font-size: 14px;
}

/* --- Finish-mode chrome (NEW3-M3) ---------------------------------------------------------
 *
 * When both lanes have finished, collapse each cabin card into its heat-map essentials so both
 * cabins AND the finish card fit inside a 1280x800 laptop viewport at once (round-3 critic
 * measured only lane B on screen at 1280x720/800, 1440x900 and 1512x982). We keep the cabin the
 * largest element after the clocks — the cabin's canvas still fills the card — but shrink the
 * card chrome around it and cap the canvas per viewport height so two of them plus the finish
 * card can share the fold. Everything is CSS-only: race-finish.js just toggles the body class.
 *
 * `.finish-mode-one-lane` applies while ONLY the fast lane has crossed; it shows the finish
 * card (compact "still going" state) without shrinking the still-racing canvas, so the losing
 * lane's live seat activity stays legible until both are done.
 */

body.finish-mode .race { gap: 8px; margin-top: 8px; }
body.finish-mode .race .cabin-card {
  padding: 6px 10px;
  gap: 4px;
}

/* Desktop-only compact card header at finish. On phone (< 900 px) the header stays a single-
 * column stack (strategy above count above clock), the same shape it uses during the race, so
 * a 400 px viewport never has to fight three columns for space. */
@media (min-width: 900px) {
  body.finish-mode .race .cabin-card .card-header {
    grid-template-columns: minmax(0, 1fr) auto auto;
    min-height: 34px;
    gap: 12px;
    align-items: center;
  }
}
body.finish-mode .race .cabin-card .card-header .strategy-picker { gap: 0; }
body.finish-mode .race .cabin-card .card-header .strategy-picker .blurb { display: none; }
body.finish-mode .race .cabin-card .card-header .strategy-picker select {
  min-height: 34px;
  padding: 4px 22px 4px 6px;
  font-size: 14px;
}
body.finish-mode .race .cabin-card .card-header .count { font-size: 12px; }
body.finish-mode .race .cabin-card .card-header .clock {
  font-size: clamp(24px, 3vw, 32px);
}
body.finish-mode .race .cabin-card .card-header .margin {
  font-size: 11px;
  margin-top: 0;
}
body.finish-mode .race .cabin-card .card-header .door-status { display: none; }

/* Cap the canvas per viewport height so two cabin cards AND the finish card fit inside
 * 800 px (round-3 NEW3-M3: the prior layout showed only one cabin at the finish on every
 * laptop viewport up to 1512x982). Budget: 800 vh - 40 vh margins for gaps and finish card
 * chrome, divided by two cabins. Inline `wrap` heights come from canvas-sizing.js; we
 * override with !important because a specific 220 px inline height otherwise wins here.
 * Phone (vertical orientation): out of scope for the cap. The 400 px phone already shows
 * both cabins side by side plus the card (`21-phone-finish.png` in the round-3 pass). */
@media (min-width: 900px) {
  body.finish-mode .race .canvas-wrap {
    height: clamp(140px, calc((100vh - 470px) / 2), 200px) !important;
    max-height: 200px;
  }
}

/* Round-02 NEW-M3 carry-over, round-09 N9-m1 extension: shave the cabin card and canvas so
 * Restart / speed / seed / heat sit fully inside the fold at every common laptop viewport.
 * Previously this rule capped at max-height 850 px, so 1440x900, 1512x982 and 1600x900 all
 * fell back to the roomy layout and clipped the controls by up to 104 px. Raising the
 * ceiling to 1010 px covers the popular 900-1003 px viewport heights while the tighter
 * max-height: 749 rule below still overrides for very short viewports. Only applies at
 * desktop widths (≥ 900 px). */
@media (min-width: 900px) and (max-height: 1010px) {
  body:not(.finish-mode) .race { gap: 8px; margin-top: 10px; }
  body:not(.finish-mode) .race .cabin-card {
    padding: 6px 12px;
    gap: 4px;
  }
  body:not(.finish-mode) .race .cabin-card .card-header { min-height: 36px; }
  body:not(.finish-mode) .race .cabin-card .card-header .clock {
    font-size: clamp(22px, 3.4vw, 30px);
  }
  body:not(.finish-mode) .race .canvas-wrap {
    /* Canvas height derived from the AVAILABLE HEIGHT so the two cabin cards plus the race
     * controls always add up to less than the fold. `(100vh - 620px) / 2` reserves 620 px
     * for chrome + controls, splits the rest between the two cabins, then clamps to
     * [130, 190] so the cabin still renders its stand-up animation and does not balloon on
     * a 1000-px viewport. At 800vh this yields 130 px; at 900vh, 140 px; at 982vh, 181 px.
     * The old formula (`(100vh - 520px) / 2` capped at 200) let 900vh keep 213 px, which
     * pushed Restart 104 px below the fold. */
    height: clamp(130px, calc((100vh - 620px) / 2), 190px) !important;
  }
  body:not(.finish-mode) .race .follow-line,
  body:not(.finish-mode) .race .race-legend { min-height: 1em; }
  body:not(.finish-mode) .race-controls { margin-top: 4px; padding: 2px 4px; }
  body:not(.finish-mode) .race-controls #btn-race { padding: 8px 16px; }
  body:not(.finish-mode) .race-controls .segmented .seg { padding: 8px 14px; }
}

/* Tighter still on very short viewports (13-inch laptops in split view, ~720 px). Same
 * strategy: shave the canvas and the card chrome, keep the race controls above the fold. */
@media (min-width: 900px) and (max-height: 749px) {
  body:not(.finish-mode) .race { gap: 6px; margin-top: 6px; }
  body:not(.finish-mode) .race .cabin-card { padding: 4px 12px; gap: 2px; }
  body:not(.finish-mode) .race .cabin-card .card-header { min-height: 30px; }
  body:not(.finish-mode) .race .cabin-card .card-header .clock {
    font-size: clamp(20px, 3vw, 26px);
  }
  body:not(.finish-mode) .race .canvas-wrap {
    height: clamp(105px, calc((100vh - 460px) / 2), 200px) !important;
  }
  body:not(.finish-mode) .race .follow-line { display: none; }
  body:not(.finish-mode) .race .race-legend { font-size: 10px; }
  body:not(.finish-mode) .race-controls { margin-top: 2px; padding: 0 4px; }
}

/* The bottom-of-card lines are noise in the finish view: the follow line has no target once
 * the cabins are empty and the legend has been swapped to the heat caption which is the only
 * legend the reader needs at the finish. */
body.finish-mode .race .follow-line { display: none; }
body.finish-mode .race .cabin-card[data-lane="a"] .race-legend:not(.heat-caption) { display: none; }
body.finish-mode .race .cabin-card[data-lane="b"] .race-legend:not(.heat-caption) { display: none; }

/* Finish card packs tighter, too, so the whole payoff strip is one clean bar the eye reads at
 * a glance. */
body.finish-mode .finish-card { padding: 10px 14px; margin-top: 8px; }
body.finish-mode .finish-card .headline { font-size: 16px; line-height: 1.3; }
body.finish-mode .finish-card .why { font-size: 12px; }
body.finish-mode .finish-card .facts { font-size: 11px; }

/* Provisional (one-lane-done) styling: show the finish card while the second lane keeps
 * running. Deliberately quiet: it's a status readout, not the final answer. */
.finish-card.provisional { background: var(--paper); border-style: dashed; }
.finish-card.provisional .headline { font-size: 15px; }
.finish-card.provisional .why { color: var(--ink-soft); font-style: italic; }
body.finish-mode-one-lane .finish-card.provisional { margin-top: 10px; }
