/* 24h du Mans — paper-collage Le Mans race strip (62 cars, 3 classes) */

:root {
  --paper: #ece3d0;
  --paper-2: #e2d7bf;
  --ink: #1d1a16;
  --ink-soft: #4a443a;
  --road: #2b2926;
  --accent: #e10600;
  --card: #f7f1e3;
  --shadow: rgba(30, 20, 5, 0.35);
  /* class identity colors (mirrors CLASS_COLORS in js/entrylist.js) */
  --cls-hyper: #e8453c;
  --cls-lmp2: #4d8fe8;
  --cls-gt3: #e8a13c;
  --live-green: #2e9e44;
  --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2'/><feColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0'/></filter><rect width='180' height='180' filter='url(%23n)'/></svg>");
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { height: 100%; }

body {
  margin: 0;
  font-family: "Space Grotesk", system-ui, sans-serif;
  color: var(--ink);
  background: var(--paper);
  background-image: var(--grain);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  user-select: none;
}

/* ---------- top bar ---------- */
#topbar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 18px 14px;
  background: var(--ink);
  background-image: var(--grain);
  color: var(--card);
  clip-path: polygon(0 0, 100% 0, 100% 88%, 97% 100%, 93% 90%, 88% 99%, 83% 91%, 77% 100%, 71% 92%, 66% 99%, 60% 90%, 54% 100%, 48% 91%, 42% 99%, 36% 90%, 30% 100%, 24% 92%, 18% 99%, 12% 90%, 6% 100%, 2% 91%, 0 97%);
  padding-bottom: 22px;
  z-index: 30;
}

.brand { display: flex; align-items: baseline; gap: 12px; min-width: 0; }

.brand h1 {
  font-family: "Archivo Black", sans-serif;
  font-size: 26px;
  letter-spacing: 1px;
  margin: 0;
  color: var(--card);
  text-shadow: 3px 3px 0 var(--accent);
  white-space: nowrap;
}

.brand .sub {
  font-family: "Permanent Marker", cursive;
  font-size: 13px;
  color: #cfc4ac;
  white-space: nowrap;
}

.race-info { display: flex; align-items: center; gap: 10px; font-weight: 600; flex-wrap: wrap; justify-content: flex-end; }
#race-name { font-size: 14px; letter-spacing: 0.4px; }

.chip {
  display: inline-block;
  padding: 3px 10px;
  background: var(--card);
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.6px;
  border-radius: 3px;
  transform: rotate(-1.2deg);
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.5);
  font-variant-numeric: tabular-nums;
}

/* 24h countdown sits between weather and lap — counter-rotate so the
   chip row doesn't read as one slanted block */
#remain-chip { transform: rotate(0.9deg); }

.chip.mode { background: var(--accent); color: #fff; transform: rotate(1.4deg); }
.chip.flag-green { background: var(--live-green); color: #fff; }
.chip.flag-yellow { background: #f3c623; color: var(--ink); }
.chip.flag-sc { background: #f57f17; color: #fff; }
.chip.flag-red { background: #d32f2f; color: #fff; }
.chip.flag-chequered { background: repeating-conic-gradient(#1d1a16 0 90deg, #fff 0 180deg) 0 0/12px 12px; color: transparent; }

/* ---------- race library ---------- */
.brand .home-link { text-decoration: none; }

body.library #stage,
body.library #trace,
body.library #controls,
body.library #lap-counter,
body.library #flag-chip,
body.library #mode-chip { display: none; }

#library {
  flex: 1;
  overflow-y: auto;
  padding: 28px 34px 50px;
}

.lib-title {
  font-family: "Permanent Marker", cursive;
  font-size: 20px;
  color: var(--ink-soft);
  margin: 0 0 20px;
  transform: rotate(-1deg);
}

#lib-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 26px;
  max-width: 1200px;
}

.lib-card {
  background: var(--card);
  background-image: var(--grain);
  padding: 16px 18px 14px;
  box-shadow: 5px 6px 0 var(--shadow);
  clip-path: polygon(1% 3%, 99% 0%, 100% 97%, 2% 100%);
  transform: rotate(-0.8deg);
}
.lib-card:nth-child(2n) { transform: rotate(0.9deg); }
.lib-card:nth-child(3n) { transform: rotate(-1.4deg); }

.lib-year {
  font-family: "Permanent Marker", cursive;
  font-size: 13px;
  color: var(--accent);
}
.lib-gp {
  font-family: "Archivo Black", sans-serif;
  font-size: 18px;
  line-height: 1.15;
  margin: 2px 0 4px;
}
.lib-where { font-size: 12.5px; font-weight: 600; color: var(--ink-soft); }
.lib-date { font-size: 11.5px; color: var(--ink-soft); margin-top: 2px; }

.lib-sessions { display: flex; gap: 8px; margin-top: 12px; }
.lib-btn {
  font-family: "Space Grotesk", sans-serif;
  font-weight: 700;
  font-size: 12px;
  text-decoration: none;
  background: var(--ink);
  color: var(--card);
  padding: 5px 12px;
  box-shadow: 2px 2px 0 var(--shadow);
  transform: rotate(-1deg);
}
.lib-btn:nth-child(2n) { transform: rotate(1.2deg); }
.lib-btn:hover { background: var(--accent); color: #fff; }
.lib-btn:active { transform: translate(2px, 2px); box-shadow: none; }

/* handwritten aside under the race buttons ("recorded live · …") */
.lib-note {
  font-family: "Permanent Marker", cursive;
  font-size: 10.5px;
  color: var(--ink-soft);
  opacity: 0.55;
  margin-top: 10px;
  transform: rotate(-0.6deg);
}

/* LIVE NOW card: the lib-card clip-path would clip an outline/outset glow,
   so the pulse is an INSET ring that survives the torn edge */
.lib-card.live {
  background: #e9f1de;
  background-image: var(--grain);
  animation: live-pulse 1.6s ease-in-out infinite;
}
@keyframes live-pulse {
  0%, 100% { box-shadow: inset 0 0 0 3px rgba(46, 158, 68, 0.95); }
  50% { box-shadow: inset 0 0 0 7px rgba(46, 158, 68, 0.35); }
}
.lib-card.live .lib-gp::before {
  content: "";
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #d32f2f;
  margin-right: 8px;
  animation: live-blink 1.2s steps(2, start) infinite;
}
@keyframes live-blink { to { visibility: hidden; } }

/* ---------- stage ---------- */
#stage { flex: 1; display: flex; min-height: 0; }

#viewport {
  position: relative;
  flex: 1;
  overflow: hidden;
  cursor: grab;
  touch-action: none;
  /* the three class lanes (BY CLASS layout) — single source of truth for the
     lane-strip tops and the per-car --track-y the view sets in split mode */
  --lane-hyper: 34%;
  --lane-lmp2: 59%;
  --lane-gt3: 84%;
}
#viewport.dragging { cursor: grabbing; }

#track-strip {
  position: absolute;
  left: 0; right: 0;
  top: calc(var(--track-y, 62%));
  height: 34px;
  background: var(--road);
  background-image: var(--grain);
  clip-path: polygon(0 6%, 3% 0, 9% 5%, 17% 1%, 26% 6%, 35% 0, 44% 5%, 53% 1%, 62% 6%, 71% 0, 80% 5%, 89% 1%, 100% 5%, 100% 94%, 96% 100%, 88% 95%, 79% 100%, 70% 94%, 61% 99%, 52% 94%, 43% 100%, 34% 95%, 25% 100%, 16% 94%, 8% 99%, 0 95%);
}

#track-strip::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 3px;
  background: repeating-linear-gradient(90deg, #d9cfb8 0 26px, transparent 26px 52px);
  opacity: 0.85;
}

/* ---------- class lanes (BY CLASS layout) ---------- */
#lane-strips { position: absolute; inset: 0; pointer-events: none; display: none; }
body[data-lanes="split"] #lane-strips { display: block; }
body[data-lanes="split"] #track-strip { display: none; }
.lane-strip {
  position: absolute;
  left: 0; right: 0;
  height: 26px;
  background: var(--road);
  background-image: var(--grain);
}
.lane-strip::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 2px;
  transform: translateY(-50%);
  background: repeating-linear-gradient(90deg, #d9cfb8 0 24px, transparent 24px 48px);
  opacity: 0.7;
}
.lane-strip[data-cls="HYPERCAR"] { top: var(--lane-hyper); }
.lane-strip[data-cls="LMP2"] { top: var(--lane-lmp2); }
.lane-strip[data-cls="LMGT3"] { top: var(--lane-gt3); }
.lane-tag {
  position: absolute;
  left: 12px; top: 50%;
  transform: translateY(-50%);
  font: 700 11px/1 "Space Grotesk", sans-serif;
  letter-spacing: 0.07em;
  color: #fff;
  padding: 3px 8px;
  border-radius: 3px;
  box-shadow: 2px 2px 0 var(--shadow);
}
.lane-strip[data-cls="HYPERCAR"] .lane-tag { background: var(--cls-hyper); }
.lane-strip[data-cls="LMP2"] .lane-tag { background: var(--cls-lmp2); }
.lane-strip[data-cls="LMGT3"] .lane-tag { background: var(--cls-gt3); color: var(--ink); }
/* BY CLASS + a class filter: only the chosen lane's strip stays */
body[data-lanes="split"][data-class-filter="HYPERCAR"] .lane-strip:not([data-cls="HYPERCAR"]),
body[data-lanes="split"][data-class-filter="LMP2"] .lane-strip:not([data-cls="LMP2"]),
body[data-lanes="split"][data-class-filter="LMGT3"] .lane-strip:not([data-cls="LMGT3"]) { display: none; }

/* gap gridlines */
#gridlines { position: absolute; inset: 0; pointer-events: none; }
.gridline {
  position: absolute;
  top: 8%;
  bottom: 18%;
  width: 2px;
  background: rgba(60, 50, 30, 0.12);
}
.gridline .gl-label {
  position: absolute;
  bottom: -22px;
  left: -30px;
  width: 60px;
  text-align: center;
  font-size: 11px;
  font-weight: 700;
  color: rgba(60, 50, 30, 0.55);
  font-variant-numeric: tabular-nums;
}

/* ---------- car sprites ---------- */
.car {
  position: absolute;
  bottom: calc(100% - var(--track-y, 62%));
  left: 0;
  width: 0;
  cursor: pointer;
  transition: opacity 0.4s, bottom 0.5s ease; /* bottom eases the lane swap */
}

.car-inner {
  position: absolute;
  bottom: -6px;
  left: 0;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  transform-origin: bottom center;
  transition: transform 0.4s ease; /* eases the BY CLASS shrink */
}

/* BY CLASS stacks three lanes — shrink each car so the heads don't collide */
body[data-lanes="split"] .car-inner { transform: translateX(-50%) scale(0.6); }

.car.selected .car-inner { z-index: 25 !important; }
.car.selected { z-index: 400 !important; } /* beats the inline x-based z so the picked head surfaces */
.car.out { opacity: 0.72; filter: grayscale(0.55); }
.car.idle { opacity: 0.55; filter: saturate(0.5); } /* quali: in the garage */

/* silent >7min, wrenches out: dimmer than running, livelier than .out —
   the car stays on the line but visibly isn't racing */
.car.garage { opacity: 0.55; filter: grayscale(0.7); }
.car.garage .head-anim { animation-play-state: paused; }

/* the comically large head, emerging from the cockpit */
.stack {
  position: relative;
  width: var(--car-w, 120px);
}

.head-wrap {
  position: absolute;
  /* SVG side-profiles put the canopy near 52%; collage-PNG cars set --head-left
     inline to sit the head over the photographed cockpit */
  left: var(--head-left, 52%);
  bottom: 24%;
  transform: translateX(-50%);
  transition: transform 0.35s ease-in-out; /* eases the look-back lean */
  z-index: 1; /* behind the car body — neck disappears into the cockpit */
  filter:
    drop-shadow(2px 0 0 #fff) drop-shadow(-2px 0 0 #fff)
    drop-shadow(0 2px 0 #fff) drop-shadow(0 -2px 0 #fff)
    drop-shadow(4px 6px 5px var(--shadow));
}

.head-anim {
  animation: bob var(--bob-dur, 2.3s) ease-in-out var(--bob-delay, 0s) infinite alternate;
  transform-origin: 50% 95%;
}

.head-wrap img {
  display: block;
  /* full 62-car field — heads run ~15% smaller than the F1 strip */
  width: calc(var(--head-size, 92px) * 0.85);
  height: auto;
  clip-path: polygon(2% 38%, 9% 12%, 22% 4%, 38% 0%, 57% 2%, 73% 7%, 86% 15%, 95% 31%, 98% 52%, 93% 71%, 97% 86%, 84% 95%, 65% 99%, 42% 97%, 24% 100%, 10% 91%, 4% 74%, 0% 55%);
  pointer-events: none;
}

/* generated collage art carries its own scissor-cut edges — drop the CSS
   clip/white-outline and keep only the soft paper-lift shadow.
   (.head-wrap without .art still happens when a real photo overrides the
   focused face, so the clipped variant above must stay.) */
.head-wrap.art {
  filter: drop-shadow(4px 6px 5px var(--shadow));
}
.head-wrap.art img {
  clip-path: none;
}

@keyframes bob {
  from { transform: rotate(var(--tilt, -3deg)) translateY(0); }
  to   { transform: rotate(calc(var(--tilt, -3deg) * -1)) translateY(-3px); }
}

/* mood changes: quick pop on any swap (also fired on driver-stint head
   swaps), rage-shake while angry, joy-bounce while happy */
.head-wrap img.pop { animation: mood-pop 0.45s ease; }
@keyframes mood-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.22) rotate(2deg); }
  100% { transform: scale(1); }
}

body.playing .head-wrap.angry .head-anim { animation: rage var(--bob-dur, 2.3s) ease-in-out infinite; }
@keyframes rage {
  0%, 100% { transform: rotate(-2.5deg) translateX(-1.5px); }
  12% { transform: rotate(2deg) translateX(1.5px); }
  24% { transform: rotate(-2deg) translateX(-1px); }
  36% { transform: rotate(1.5deg) translateX(1px); }
  50% { transform: rotate(-1deg); }
}

body.playing .head-wrap.happy .head-anim { animation: joy calc(var(--bob-dur, 2.3s) * 0.55) ease-in-out infinite alternate; }

/* retired: head droops and shudders with sobs */
body.playing .head-wrap.crying .head-anim { animation: sob calc(var(--bob-dur, 2.3s) * 0.8) ease-in-out infinite; }
@keyframes sob {
  0%, 100% { transform: rotate(4deg) translateY(2px); }
  18% { transform: rotate(5.5deg) translateY(4px) translateX(-1px); }
  26% { transform: rotate(4.5deg) translateY(3px) translateX(1px); }
  34% { transform: rotate(6deg) translateY(4.5px) translateX(-1px); }
  42% { transform: rotate(4.5deg) translateY(3px); }
  70% { transform: rotate(3deg) translateY(1.5px); }
}

/* glancing back at the car behind: lean the whole head rearward a touch.
   the lean lives on .head-wrap (no animation runs there) so the 0.35s
   transition tweens it; the bob keeps running underneath, no snap */
.head-wrap.back { transform: translateX(-50%) rotate(-7deg) translateX(-5px); }
@keyframes joy {
  from { transform: rotate(var(--tilt, -3deg)) translateY(0) scale(1); }
  to   { transform: rotate(calc(var(--tilt, -3deg) * -1)) translateY(-7px) scale(1.05); }
}

body.paused .head-anim { animation-play-state: paused; }

/* car body: always an inline livery-painted 420x170 svg (.car-body.art) —
   it draws its own bold outlines, so just the paper-lift shadow here */
.car-body {
  position: relative;
  z-index: 2;
  width: var(--car-w, 120px);
  filter: drop-shadow(3px 5px 4px var(--shadow));
}
.car-body svg { display: block; width: 100%; height: auto; }
/* generated paper-collage car PNG (.car-body.art); carries its own cut edges */
.car-body img { display: block; width: 100%; height: auto; }

/* wheel spokes: sprites.js pins each group's transform-origin inline in
   viewBox px, which only resolves against the view-box reference box —
   keep transform-box there so the hubs stay put while spinning */
.wheel-spin { transform-box: view-box; }
body.playing .wheel-spin { animation: spin 0.6s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
/* wheels stop when the car isn't moving */
.car.out .wheel-spin,
.car.garage .wheel-spin,
.car.idle .wheel-spin { animation: none; }

/* tag under the car */
.tag {
  margin-top: 10px;
  font-size: 11px;
  font-weight: 700;
  background: var(--card);
  border-left: 4px solid var(--team, #888);
  padding: 2px 7px 2px 5px;
  border-radius: 2px;
  white-space: nowrap;
  box-shadow: 2px 2px 0 var(--shadow);
  transform: rotate(var(--tag-tilt, -1.5deg));
  font-variant-numeric: tabular-nums;
}
.tag .pos { font-family: "Archivo Black", sans-serif; font-size: 11px; margin-right: 2px; color: var(--ink); }
/* tiny paper swatch in the class color (bg arrives inline) */
.tag .class-chip {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.4);
  vertical-align: middle;
  margin: 0 4px 0 2px;
}
.tag .gap { color: var(--ink-soft); margin-left: 4px; }
.tag .gap.lapped { color: #b3382c; }

.car.alt .car-inner .tag { margin-top: 26px; }

/* ---------- detail card ---------- */
#detail-card {
  position: absolute;
  top: 16px;
  left: 16px;
  z-index: 5000;
  width: 270px;
  background: var(--card);
  background-image: var(--grain);
  padding: 12px 14px;
  transform: rotate(-1deg);
  box-shadow: 5px 6px 0 var(--shadow);
  clip-path: polygon(1% 3%, 99% 0%, 100% 97%, 2% 100%);
}

/* spotter beauty render: a polaroid taped to the top of the card */
#detail-card .dc-render {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
  background: #fff;
  padding: 5px 5px 7px;
  margin: 2px 0 9px;
  transform: rotate(-1.4deg);
  box-shadow: 3px 3px 0 var(--shadow);
  clip-path: polygon(0.5% 2%, 99% 0.5%, 100% 98%, 1.5% 99.5%);
}

#detail-card .dc-head { display: flex; gap: 10px; align-items: center; margin-bottom: 8px; }
#detail-card .dc-name { font-family: "Archivo Black", sans-serif; font-size: 16px; line-height: 1.1; }
#detail-card .dc-team { font-size: 12px; color: var(--ink-soft); font-weight: 600; }
#detail-card .dc-close { position: absolute; top: 6px; right: 10px; cursor: pointer; font-weight: 700; font-size: 14px; background: none; border: none; color: var(--ink-soft); z-index: 1; }

/* class chip in the subtitle — bg/fg arrive inline from PLATE_COLORS */
.dc-class {
  display: inline-block;
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  vertical-align: 1px;
}

/* crew list: three lines, the one behind the wheel gets the highlighter */
.dc-crew {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 8px 0;
  padding: 7px 0;
  border-top: 1px dashed rgba(0, 0, 0, 0.15);
  border-bottom: 1px dashed rgba(0, 0, 0, 0.15);
}
.dc-crew-row {
  display: flex;
  gap: 6px;
  align-items: baseline;
  font-size: 11px;
  padding: 1px 3px;
}
.dc-crew-row.driving {
  font-weight: 700;
  background: linear-gradient(100deg, transparent 1%, rgba(243, 198, 35, 0.55) 5% 95%, transparent 99%);
}
.dc-cat {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  align-self: center;
  border-radius: 3px;
  text-align: center;
  line-height: 14px;
  font-size: 9.5px;
  font-weight: 800;
}
/* FIA driver categorisation metals */
.dc-cat.cat-p { background: #26242b; color: #eceaf2; }
.dc-cat.cat-g { background: #d4a017; color: #1d1a16; }
.dc-cat.cat-s { background: #c4c8cf; color: #2b2b2b; }
.dc-cat.cat-b { background: #a4632a; color: #fff; }
.dc-cat.cat-x { background: transparent; color: var(--ink-soft); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25); }
.dc-crew-tla { font-weight: 800; width: 30px; flex-shrink: 0; }
.dc-crew-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

#detail-card table { width: 100%; border-collapse: collapse; font-size: 12.5px; font-variant-numeric: tabular-nums; }
#detail-card td { padding: 3px 0; border-top: 1px dashed rgba(0,0,0,0.15); }
#detail-card td:last-child { text-align: right; font-weight: 700; }

/* ---------- driver stints panel ---------- */
#strategy {
  position: absolute;
  inset: 10px 12px 14px;
  z-index: 4500;
  background: var(--card);
  background-image: var(--grain);
  box-shadow: 6px 7px 0 var(--shadow);
  clip-path: polygon(0.5% 1%, 99.5% 0%, 100% 99%, 1% 100%);
  padding: 12px 18px 14px;
  transform: translateY(24px) rotate(-0.4deg);
  opacity: 0;
  transition: transform 0.25s ease, opacity 0.25s ease;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#strategy.open { transform: translateY(0) rotate(-0.4deg); opacity: 1; }

.strat-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 4px; }
.strat-title { font-family: "Archivo Black", sans-serif; font-size: 15px; letter-spacing: 1.2px; }
.strat-lap { font-size: 11px; white-space: nowrap; } /* "+5:12:08 · LAP 84" */

.strat-ruler { position: relative; height: 14px; margin-left: 46px; }
.strat-tick {
  position: absolute;
  transform: translateX(-50%);
  font-size: 9px;
  font-weight: 700;
  color: var(--ink-soft);
}

.strat-rows { position: relative; flex: 1; overflow-y: auto; min-height: 0; }
.strat-row {
  display: flex;
  align-items: center;
  height: 21px;
  gap: 8px;
}
.strat-row.out { opacity: 0.45; }

/* row label = car number on its WEC class plate (bg/fg inline), tinted by
   the car color via --team. Stays 38px wide — the playhead math assumes
   the 38px column + 8px gap = 46px offset */
.strat-acr {
  width: 38px;
  flex-shrink: 0;
  font-size: 10.5px;
  font-weight: 800;
}
.strat-acr.strat-plate {
  border-left: 3px solid var(--team, #888);
  border-radius: 3px;
  text-align: center;
  height: 16px;
  line-height: 16px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.4), 1px 1px 0 rgba(0, 0, 0, 0.3);
}

.strat-track { position: relative; flex: 1; height: 15px; }

/* stint bars: background + torn clip-path arrive inline per bar — CSS only
   keeps the tla legible over arbitrary team colors */
.stint {
  position: absolute;
  top: 0;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 8.5px;
  font-weight: 800;
  letter-spacing: 0.3px;
  overflow: hidden;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
}
/* d2 is the lightest crew shade — lean harder on the dark halo */
.stint.stint-d2 { text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85), 0 0 4px rgba(0, 0, 0, 0.55); }

.strat-pit {
  position: absolute;
  top: -2px;
  width: 2px;
  height: 19px;
  background: var(--ink);
}
.strat-pit::after {
  content: "";
  position: absolute;
  bottom: -3px; left: -2px;
  width: 6px; height: 3px;
  background: var(--ink);
}

.strat-x { position: absolute; top: 0; font-size: 11px; font-weight: 700; color: var(--ink-soft); }

.strat-playhead {
  position: absolute;
  top: 0; bottom: 0;
  width: 2px;
  background: var(--accent);
  box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
  pointer-events: none;
}

/* ---------- battle chips ---------- */
#battle-chips {
  position: absolute;
  top: 12px;
  right: 14px;
  z-index: 900;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
}

.battle-chip {
  font-family: "Space Grotesk", sans-serif;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: var(--card);
  background-image: var(--grain);
  color: var(--ink);
  border: none;
  border-left: 4px solid var(--team-a, #888);
  border-right: 4px solid var(--team-b, #888);
  padding: 4px 9px;
  cursor: pointer;
  box-shadow: 2px 2px 0 var(--shadow);
  transform: rotate(-1deg);
  opacity: 0;
  transition: opacity 0.2s, transform 0.2s;
}
.battle-chip:nth-child(2n) { transform: rotate(1.1deg); }
.battle-chip.show { opacity: 1; }
.battle-chip.on { background: var(--accent); color: #fff; }
.battle-chip b { font-family: "Archivo Black", sans-serif; font-size: 11px; }
.battle-chip i { font-family: "Permanent Marker", cursive; font-style: normal; margin: 0 2px; }
.battle-chip span { color: var(--ink-soft); margin-left: 3px; }
.battle-chip.on span { color: #ffd9d6; }

/* ---------- lap-time sparkline (detail card) ---------- */
.dc-spark { margin-top: 8px; padding-top: 6px; border-top: 1px dashed rgba(0, 0, 0, 0.15); }
.dc-spark-svg { display: block; width: 100%; height: auto; }
.dc-spark-cap {
  font-family: "Permanent Marker", cursive;
  font-size: 10px;
  color: var(--ink-soft);
}

.hint {
  position: absolute;
  bottom: 10px;
  left: 50%;
  transform: translateX(-50%) rotate(-0.6deg);
  font-family: "Permanent Marker", cursive;
  font-size: 12px;
  color: rgba(60, 50, 30, 0.5);
  pointer-events: none;
}

/* ---------- leaderboard ---------- */
#leaderboard {
  width: 320px;
  flex-shrink: 0;
  background: var(--paper-2);
  background-image: var(--grain);
  border-left: 3px solid var(--ink);
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.board-head {
  font-family: "Archivo Black", sans-serif;
  font-size: 13px;
  letter-spacing: 1.5px;
  padding: 10px 14px 6px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
#board-note { font-family: "Space Grotesk"; font-size: 10px; color: var(--ink-soft); }

#board-rows {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 10px 14px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

/* 62 cars: rows are squeezed to 24px; flex `order` driven by --ord keeps
   them sorted (out rows arrive as ord 200+i, so order — not a translate —
   is the only mechanism that survives those sparse values) */
.brow {
  display: grid;
  grid-template-columns: 24px 28px 20px 1fr 54px 52px;
  align-items: center;
  gap: 5px;
  height: 24px;
  flex: 0 0 auto;
  background: var(--card);
  padding: 2px 6px;
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  border-left: 4px solid var(--team, #888);
  box-shadow: 2px 2px 0 rgba(30, 20, 5, 0.18);
  cursor: pointer;
  order: var(--ord, 99);
}
.brow:hover, .brow.selected { outline: 2px solid var(--ink); }
.brow.out { opacity: 0.45; filter: grayscale(0.8); }
.brow.filtered { display: none; } /* class view folds the other classes away */

.brow .bpos { font-family: "Archivo Black", sans-serif; font-size: 10px; }

/* WEC class number plate — bg/fg colors arrive inline from PLATE_COLORS */
.brow .bplate {
  display: inline-block;
  width: 28px;
  height: 16px;
  line-height: 16px;
  text-align: center;
  font-family: "Archivo Black", sans-serif;
  font-size: 9.5px;
  letter-spacing: -0.2px;
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.45), 1px 1px 0 rgba(0, 0, 0, 0.3);
  transform: rotate(-1deg); /* paper-sticker slap */
}

.brow .bhead { width: 20px; height: 20px; object-fit: cover; object-position: top; border-radius: 50%; background: #d8cdb4; }

/* team name truncates; the current driver's tla rides along after it */
.brow .bacr {
  letter-spacing: 0.3px;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.brow .bacr .bdrv {
  font-family: "Permanent Marker", cursive;
  font-size: 9px;
  color: var(--ink-soft);
  margin-left: 5px;
}

.brow .bgap { text-align: right; color: var(--ink-soft); font-size: 10px; }
.brow .blap { text-align: right; font-size: 10.5px; }
.brow .blap.best { color: #7b1fa2; font-weight: 800; } /* class best */

/* ---------- race trace scrubber ---------- */
#trace {
  position: relative;
  height: 96px;
  flex-shrink: 0;
  background: var(--ink);
  background-image: var(--grain);
  cursor: ew-resize;
  touch-action: none;
  z-index: 25;
  clip-path: polygon(0 10%, 4% 2%, 9% 9%, 15% 1%, 22% 8%, 28% 0, 35% 7%, 41% 1%, 48% 9%, 55% 2%, 61% 8%, 68% 0, 74% 7%, 81% 1%, 87% 8%, 93% 2%, 100% 9%, 100% 100%, 0 100%);
}
#trace.disabled { cursor: default; }
#trace canvas { position: absolute; inset: 0; width: 100%; height: 100%; }

.trace-playhead {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 2px;
  background: var(--accent);
  pointer-events: none;
  will-change: transform;
}
.trace-playhead::after {
  content: "";
  position: absolute;
  bottom: 0; left: -3px;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-bottom: 6px solid var(--accent);
}

.trace-label {
  position: absolute;
  top: 12px; right: 10px;
  font-size: 11px;
  font-weight: 700;
  color: var(--card);
  background: rgba(0, 0, 0, 0.45);
  padding: 2px 7px;
  border-radius: 2px;
  pointer-events: none;
  font-variant-numeric: tabular-nums;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  clip-path: inset(50%);
  overflow: hidden;
  border: 0;
}

/* ---------- controls ---------- */
#controls {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 16px 14px;
  background: var(--ink);
  background-image: var(--grain);
  color: var(--card);
  z-index: 30;
}

#controls .btn,
#controls .group button {
  font-family: "Space Grotesk", sans-serif;
  font-weight: 700;
  font-size: 12px;
  background: var(--card);
  color: var(--ink);
  border: none;
  padding: 6px 10px;
  cursor: pointer;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.55);
}

#controls .btn.big { font-size: 16px; padding: 6px 16px; transform: rotate(-1deg); }
#controls .group { display: flex; gap: 4px; }
#controls .group button.on,
#controls .btn.on { background: var(--accent); color: #fff; } /* .btn.on: the STINTS toggle */
#controls .group button:active, #controls .btn:active { transform: translate(2px, 2px); box-shadow: none; }

/* class filter: each class button wears its color as an underline swatch,
   and goes full class-color when active */
#class-group button { position: relative; }
#class-group .cls-HYPERCAR::after,
#class-group .cls-LMP2::after,
#class-group .cls-LMGT3::after {
  content: "";
  position: absolute;
  left: 7px; right: 7px; bottom: 3px;
  height: 2.5px;
}
#class-group .cls-HYPERCAR::after { background: var(--cls-hyper); }
#class-group .cls-LMP2::after { background: var(--cls-lmp2); }
#class-group .cls-LMGT3::after { background: var(--cls-gt3); }
/* button element keeps these level with `#controls .group button.on` so the
   later class-color rule wins over the generic accent red */
#class-group button.cls-HYPERCAR.on { background: var(--cls-hyper); color: #fff; }
#class-group button.cls-LMP2.on { background: var(--cls-lmp2); color: #fff; }
#class-group button.cls-LMGT3.on { background: var(--cls-gt3); color: var(--ink); }
#class-group button.on::after { background: rgba(255, 255, 255, 0.9); }

.scrub-wrap { flex: 1; display: flex; align-items: center; gap: 12px; min-width: 100px; }
.clock { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13px; min-width: 80px; }

/* mobile-only chrome (tab bar, filters sheet, etc.). Hidden by default; the
   phone media query below reveals each piece. On desktop #control-adv and its
   .adv-rows are display:contents, so the control groups stay direct flex items
   of #controls exactly as before — the wrappers are invisible to layout. */
.m-only { display: none; }
#control-adv, .adv-row { display: contents; }

/* ---------- tablets ---------- */
@media (max-width: 900px) {
  #stage { flex-direction: column; }
  #leaderboard { width: 100%; max-height: 30%; border-left: none; border-top: 3px solid var(--ink); }
  .brand .sub { display: none; }
  #controls { flex-wrap: wrap; }
  #trace { height: 64px; }
  .trace-label { display: none; }
}

/* ---------- phones: hero LINE + TIMING/TRACE toggle + filters sheet ----------
   A 24h field of 62 cars over four desktop panels is a smear at 390px. On a
   phone we make the LINE the hero up top, swap the board and trace in the slot
   below it via a segmented toggle, and fold every secondary control into a
   slide-up sheet so the always-on bar is just play / clock / ADJUST. */
@media (max-width: 600px) {
  /* reveal the phone-only bits */
  #m-tabs,
  #m-sheet-head,
  .adv-label { display: flex; }
  #m-filters { display: inline-flex; align-items: center; }

  /* keep only the most useful share affordances on a phone */
  .topbar-share .tsh[data-net="x"],
  .topbar-share .tsh[data-net="facebook"] { display: none; }

  /* ---- topbar: compact, no long race title ---- */
  #topbar { padding: 8px 12px 16px; gap: 8px; align-items: center; }
  .brand h1 { font-size: 19px; text-shadow: 2px 2px 0 var(--accent); }
  #race-name { display: none; }
  .race-info { gap: 6px; }
  .race-info .chip { padding: 2px 7px; font-size: 11px; }

  /* ---- stage becomes a column: LINE hero, then the swap slot ---- */
  #stage { flex-direction: column; flex: 1 1 auto; min-height: 0; }
  #viewport { flex: 0 0 42vh; min-height: 188px; }
  .hint { display: none; }

  /* segmented toggle that lives between the hero and the panel below it */
  #m-tabs {
    flex: 0 0 auto;
    gap: 8px;
    padding: 7px 12px;
    background: var(--ink);
    background-image: var(--grain);
  }
  #m-tabs button {
    flex: 1;
    font: 700 12px/1 "Space Grotesk", sans-serif;
    letter-spacing: 1.2px;
    padding: 9px 6px;
    color: var(--card);
    background: rgba(247, 241, 227, 0.12);
    border: none;
    border-radius: 7px;
    cursor: pointer;
  }
  #m-tabs button.on {
    background: var(--card);
    color: var(--ink);
    box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.5);
  }

  /* TIMING tab (default): board fills the slot, trace is hidden */
  #leaderboard {
    width: auto;
    max-height: none;
    flex: 1 1 auto;
    border-left: none;
    border-top: none;
  }
  #trace { display: none; }
  #board-rows { padding-bottom: 20px; }

  /* TRACE tab: hero shrinks to its own height, trace fills the rest */
  body.m-tab-trace #stage { flex: 0 0 auto; }
  body.m-tab-trace #leaderboard { display: none; }
  body.m-tab-trace #trace {
    display: block;
    flex: 1 1 auto;
    height: auto;
    min-height: 150px;
  }

  /* ---- LINE hero: shrink each car so heads stop colliding at 390px ---- */
  body:not([data-lanes="split"]) .car-inner { transform: translateX(-50%) scale(0.78); }
  body[data-lanes="split"] .car-inner { transform: translateX(-50%) scale(0.5); }

  /* battle chips: a horizontal scroll strip pinned to the top of the hero */
  #battle-chips {
    top: 6px;
    left: 8px;
    right: 8px;
    flex-direction: row;
    align-items: flex-start;
    gap: 6px;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  #battle-chips::-webkit-scrollbar { display: none; }
  .battle-chip { flex: 0 0 auto; font-size: 11px; padding: 3px 8px; }

  /* tapping a car opens the detail as a bottom sheet, not a tiny floating card */
  #detail-card {
    position: fixed;
    inset: auto 0 0 0;
    top: auto;
    width: auto;
    max-height: 76vh;
    overflow-y: auto;
    transform: none;
    border-radius: 16px 16px 0 0;
    clip-path: none;
    z-index: 7000;
    box-shadow: 0 -8px 26px rgba(0, 0, 0, 0.45);
    padding: 14px 16px calc(16px + env(safe-area-inset-bottom));
  }
  /* bigger, easier-to-hit close — and a tap-away backdrop wired in mobile.js,
     since the card now covers the controls bar */
  #detail-card .dc-close {
    top: 8px;
    right: 10px;
    font-size: 20px;
    padding: 4px 10px;
    line-height: 1;
  }

  /* ---- bottom bar: play / clock / ADJUST ---- */
  #controls { gap: 8px; padding: 8px 12px calc(8px + env(safe-area-inset-bottom)); flex-wrap: nowrap; }
  #play-btn.big { font-size: 16px; padding: 7px 15px; }
  .scrub-wrap { flex: 1 1 auto; min-width: 0; gap: 6px; }
  .clock { font-size: 12px; min-width: 0; }
  #m-filters { flex: 0 0 auto; gap: 4px; }

  /* ---- the filters sheet (#control-adv) ---- */
  #control-adv {
    display: flex;
    flex-direction: column;
    gap: 13px;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 6000;
    background: var(--ink);
    background-image: var(--grain);
    color: var(--card);
    padding: 8px 16px calc(20px + env(safe-area-inset-bottom));
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -10px 28px rgba(0, 0, 0, 0.45);
    transform: translateY(112%);
    transition: transform 0.26s ease;
    max-height: 82vh;
    overflow-y: auto;
  }
  body.sheet-open #control-adv { transform: translateY(0); }
  body.sheet-open #m-backdrop,
  body.detail-open #m-backdrop { display: block; }
  #m-backdrop {
    position: fixed;
    inset: 0;
    z-index: 5900; /* under the sheet (6000) and the detail card (7000) */
    background: rgba(0, 0, 0, 0.45);
  }

  /* STINTS panel: it's absolutely-positioned inside #viewport, so without this
     it'd be trapped/clipped inside the 42vh hero. Lift it to a full-screen
     fixed overlay (above the controls bar) so all 62 stint rows get the screen. */
  #strategy {
    position: fixed;
    inset: 6vh 8px calc(8px + env(safe-area-inset-bottom));
    z-index: 6800;
    transform: translateY(24px) rotate(-0.4deg);
  }
  #strategy.open { transform: translateY(0) rotate(-0.4deg); }

  #m-sheet-head {
    justify-content: space-between;
    align-items: center;
    position: sticky;
    top: 0;
    margin: 0 -16px;
    padding: 6px 16px 10px;
    background: var(--ink);
    background-image: var(--grain);
    border-bottom: 1px dashed rgba(247, 241, 227, 0.2);
  }
  .m-sheet-title { font: 800 13px/1 "Archivo Black", sans-serif; letter-spacing: 1.2px; }
  #m-sheet-done {
    background: var(--card);
    color: var(--ink);
    border: none;
    border-radius: 7px;
    padding: 7px 16px;
    font: 700 13px "Space Grotesk", sans-serif;
    cursor: pointer;
  }

  .adv-row { display: flex; align-items: center; gap: 10px; }
  .adv-label {
    flex: 0 0 50px;
    font: 700 11px/1 "Space Grotesk", sans-serif;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: #cfc4ac;
  }
  #control-adv .group { flex: 1; gap: 6px; }
  #control-adv .group button { flex: 1; padding: 11px 6px; font-size: 13px; }
  #control-adv #stints-btn { width: 100%; padding: 12px; }
}

/* short portrait (reduced-height in-app browsers / split view, e.g. ~390x500):
   a 42vh hero + tabs + bar would leave the panel a sliver. Shrink the hero and
   the floors so the fixed chrome plus one usable panel still fit — body has
   overflow:hidden, so anything that doesn't fit is clipped, not scrolled. */
@media (max-width: 600px) and (max-height: 620px) {
  #viewport { flex: 0 0 36vh; min-height: 132px; }
  #topbar { padding: 5px 12px 12px; }
  .brand h1 { font-size: 17px; }
  #m-tabs { padding: 4px 10px; }
  #m-tabs button { padding: 6px; }
  body.m-tab-trace #trace { min-height: 104px; }
}
