/* Wreckway - interface skin.

   One scale unit (--u) drives every size in the game. It is derived from the SHORTER
   viewport edge, so the whole interface grows and shrinks as one piece and a button
   is the same physical size on a phone in portrait as on a laptop in landscape. No
   media queries adjust individual widgets; the unit does all of it.

   Style rules that keep the game looking like one thing:
     - chunky, fully rounded, thick dark outline, hard bottom shadow (candy buttons)
     - every interactive element drops onto its shadow when pressed
     - text is uppercase, heavy and outlined so it survives on top of bright scenery
     - nothing is dark: the darkest surface in the game is the ink outline */

:root {
  /* Sizing. Driven by whichever viewport edge is tighter, so a widget is never
     cramped in landscape nor comically large on a tall phone. Clamped at both ends
     so a watch-sized window is still legible and a 4K monitor is not absurd. */
  --u: clamp(11px, min(3.6vw, 3.2vh), 22px);

  --ink: #2b2f4a;
  --ink-soft: #4a5170;

  --cream: #fff6e8;
  --cream-2: #ffeccf;
  --pink: #ff5f7e;
  --pink-d: #d93a5c;
  --sky: #3fa9ff;
  --sky-d: #1f7fd0;
  --lime: #7be04f;
  --lime-d: #4fb32b;
  --sun: #ffd93d;
  --sun-d: #e0ab00;
  --tan: #ffab5e;
  --tan-d: #d97d2c;
  --grape: #b07bff;
  --grape-d: #8149d6;
  --grey: #cdd6e4;
  --grey-d: #9aa6b8;

  --r-lg: calc(var(--u) * 1.5);
  --r-md: calc(var(--u) * 1.0);
  --r-sm: calc(var(--u) * 0.6);

  --line: calc(var(--u) * 0.24);
  --drop: calc(var(--u) * 0.42);

  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);

  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-back: cubic-bezier(.34, 1.56, .64, 1);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0; padding: 0;
  width: 100%; height: 100%;
  overflow: hidden;
  background: #8fe0ff;
  color: var(--ink);
  font-family: "Trebuchet MS", "Segoe UI", Verdana, system-ui, -apple-system, sans-serif;
  font-weight: 700;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
  overscroll-behavior: none;
}

#stage { position: fixed; inset: 0; width: 100%; height: 100%; display: block; }

#ui {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 10;
  padding: calc(var(--safe-t) + var(--u) * 0.7) calc(var(--safe-r) + var(--u) * 0.7)
           calc(var(--safe-b) + var(--u) * 1.1) calc(var(--safe-l) + var(--u) * 0.7);
}

button { pointer-events: auto; }

/* ------------------------------------------------------------------ type */

.fat {
  font-weight: 900;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #fff;
  -webkit-text-stroke: calc(var(--u) * 0.11) var(--ink);
  paint-order: stroke fill;
  text-shadow: 0 calc(var(--u) * 0.16) 0 rgba(43, 47, 74, .35);
}

/* ------------------------------------------------------------------ buttons */

.btn {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--u) * 0.4);
  position: relative;
  border: var(--line) solid var(--ink);
  border-radius: var(--r-lg);
  padding: calc(var(--u) * 0.72) calc(var(--u) * 1.35);
  font: inherit;
  font-weight: 900;
  font-size: calc(var(--u) * 1.06);
  letter-spacing: .03em;
  text-transform: uppercase;
  color: #fff;
  -webkit-text-stroke: calc(var(--u) * 0.075) var(--ink);
  paint-order: stroke fill;
  background: var(--sun);
  box-shadow: 0 var(--drop) 0 var(--sun-d), 0 calc(var(--drop) + 2px) calc(var(--u) * 0.5) rgba(43,47,74,.22);
  cursor: pointer;
  transition: transform .11s var(--ease-out), box-shadow .11s var(--ease-out), filter .15s;
  white-space: nowrap;
}
.btn:active, .btn.press {
  transform: translateY(var(--drop));
  box-shadow: 0 0 0 var(--sun-d), 0 2px calc(var(--u) * 0.3) rgba(43,47,74,.25);
}
.btn.big { font-size: calc(var(--u) * 1.35); padding: calc(var(--u) * 0.9) calc(var(--u) * 1.9); }

.btn.lime  { background: var(--lime);  box-shadow: 0 var(--drop) 0 var(--lime-d),  0 calc(var(--drop) + 2px) calc(var(--u)*.5) rgba(43,47,74,.22); }
.btn.lime:active, .btn.lime.press  { box-shadow: 0 0 0 var(--lime-d); }
.btn.sky   { background: var(--sky);   box-shadow: 0 var(--drop) 0 var(--sky-d),   0 calc(var(--drop) + 2px) calc(var(--u)*.5) rgba(43,47,74,.22); }
.btn.sky:active, .btn.sky.press   { box-shadow: 0 0 0 var(--sky-d); }
.btn.pink  { background: var(--pink);  box-shadow: 0 var(--drop) 0 var(--pink-d),  0 calc(var(--drop) + 2px) calc(var(--u)*.5) rgba(43,47,74,.22); }
.btn.pink:active, .btn.pink.press  { box-shadow: 0 0 0 var(--pink-d); }
.btn.tan   { background: var(--tan);   box-shadow: 0 var(--drop) 0 var(--tan-d),   0 calc(var(--drop) + 2px) calc(var(--u)*.5) rgba(43,47,74,.22); }
.btn.tan:active, .btn.tan.press   { box-shadow: 0 0 0 var(--tan-d); }
.btn.purple{ background: var(--grape);box-shadow: 0 var(--drop) 0 var(--grape-d), 0 calc(var(--drop) + 2px) calc(var(--u)*.5) rgba(43,47,74,.22); }
.btn.purple:active, .btn.purple.press{ box-shadow: 0 0 0 var(--grape-d); }
.btn.grey  { background: var(--grey);  color: var(--ink); -webkit-text-stroke: 0;
             box-shadow: 0 var(--drop) 0 var(--grey-d); }
.btn.grey:active, .btn.grey.press  { box-shadow: 0 0 0 var(--grey-d); }

.btn.locked { filter: saturate(.35) brightness(1.05); }

.icon-btn {
  pointer-events: auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: calc(var(--u) * 3.1); height: calc(var(--u) * 3.1);
  border: var(--line) solid var(--ink);
  border-radius: var(--r-md);
  background: var(--cream);
  box-shadow: 0 var(--drop) 0 #e0c9a8;
  cursor: pointer;
  transition: transform .11s var(--ease-out), box-shadow .11s var(--ease-out);
  padding: 0;
}
.icon-btn:active, .icon-btn.press { transform: translateY(var(--drop)); box-shadow: 0 0 0 #e0c9a8; }
.icon-btn.small { width: calc(var(--u) * 2.5); height: calc(var(--u) * 2.5); font-size: calc(var(--u)*1.7);
                  color: var(--ink); line-height: 1; font-weight: 900; }

/* Pictograms are inline SVG in the markup rather than image files: no extra requests,
   they inherit the ink colour, and they stay crisp at any size. An earlier version drew
   them with CSS mask compositing, which renders inconsistently across browsers - several
   came out as solid blocks. */
.ico {
  display: block;
  width: 58%; height: 58%;
  fill: var(--ink);
  pointer-events: none;
}
.btn .ico { width: calc(var(--u) * 1.25); height: calc(var(--u) * 1.25); fill: #fff; flex: none; }

/* Any button that costs an ad wears this, so the price is never a surprise. */
.ad-badge {
  position: absolute;
  top: calc(var(--u) * -0.62); right: calc(var(--u) * -0.5);
  display: inline-flex; align-items: center; gap: calc(var(--u) * 0.18);
  background: #ff3b52;
  color: #fff;
  border: calc(var(--u) * 0.16) solid var(--ink);
  border-radius: 999px;
  padding: calc(var(--u) * 0.1) calc(var(--u) * 0.42);
  font-size: calc(var(--u) * 0.62);
  font-weight: 900;
  letter-spacing: .06em;
  -webkit-text-stroke: 0;
  box-shadow: 0 calc(var(--u)*0.16) 0 #b81f32;
  animation: adpulse 1.8s ease-in-out infinite;
}
.ad-badge .play {
  width: 0; height: 0;
  border-left: calc(var(--u) * 0.34) solid #fff;
  border-top: calc(var(--u) * 0.2) solid transparent;
  border-bottom: calc(var(--u) * 0.2) solid transparent;
}
@keyframes adpulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.09); }
}

.coin {
  display: inline-block;
  width: calc(var(--u) * 1.15); height: calc(var(--u) * 1.15);
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #fff3a8, var(--sun) 55%, var(--sun-d));
  border: calc(var(--u) * 0.14) solid var(--ink);
  flex: none;
}
.coin.big { width: calc(var(--u) * 1.7); height: calc(var(--u) * 1.7); }
.car-cell .coin { width: calc(var(--u) * 0.75); height: calc(var(--u) * 0.75);
                  border-width: calc(var(--u) * 0.1); }

/* ------------------------------------------------------------------ chrome */

#chrome {
  position: absolute; inset: 0;
  z-index: 1;
  display: flex; flex-direction: column; justify-content: space-between;
  padding: inherit;
  pointer-events: none;
}
#chrome.gone .periph { animation: none; }

.chrome-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--u); }
.rail { display: flex; gap: calc(var(--u) * 0.55); }
.rail.right { justify-content: flex-end; }

#wordmark {
  display: flex; flex-direction: column; align-items: center; line-height: .92;
  transform: rotate(-2deg);
  margin-top: calc(var(--u) * -0.2);
}
#wordmark .wm-a, #wordmark .wm-b {
  font-weight: 900; text-transform: uppercase;
  -webkit-text-stroke: calc(var(--u) * 0.16) var(--ink);
  paint-order: stroke fill;
  text-shadow: 0 calc(var(--u) * 0.2) 0 rgba(43,47,74,.3);
}
/* A name over a descriptor, not a matched pair - so the two lines are sized
   independently, and the descriptor is tracked out to the width of the name above it.
   Both are capped against the viewport as well as the scale unit: on a 320px-wide
   phone the two icon buttons and the coin pill leave very little middle, and a
   wordmark sized purely from --u would run under them. */
#wordmark .wm-a {
  color: var(--sun);
  font-size: min(calc(var(--u) * 2.1), 7vw);
  letter-spacing: .01em;
}
#wordmark .wm-b {
  color: var(--pink);
  font-size: min(calc(var(--u) * 0.72), 2.4vw);
  letter-spacing: .17em;
  margin-top: calc(var(--u) * 0.12);
  margin-right: -.17em;
}

.coin-pill {
  display: inline-flex; align-items: center; gap: calc(var(--u) * 0.4);
  background: var(--cream);
  border: var(--line) solid var(--ink);
  border-radius: 999px;
  padding: calc(var(--u) * 0.32) calc(var(--u) * 0.9);
  box-shadow: 0 var(--drop) 0 #e0c9a8;
  font-size: calc(var(--u) * 1.15);
  font-weight: 900;
  color: var(--ink);
}

.chrome-bottom {
  display: flex; align-items: flex-end; justify-content: center;
  gap: calc(var(--u) * 0.7);
  padding-bottom: calc(var(--u) * 0.4);
}

#bestLine {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--safe-b) + var(--u) * 5.6);
  font-size: calc(var(--u) * 0.92);
  color: var(--ink);
  background: rgba(255,246,232,.85);
  border: calc(var(--u)*0.14) solid var(--ink);
  border-radius: 999px;
  padding: calc(var(--u)*0.16) calc(var(--u)*0.8);
  letter-spacing: .08em;
}
#bestLine b { color: var(--pink-d); }

/* Peripheral chrome enters with a stagger and leaves the same way in reverse. */
.periph {
  opacity: 0;
  transform: translateY(calc(var(--u) * 1.4));
  transition: opacity .34s var(--ease-out), transform .42s var(--ease-back);
}
#chrome.in .periph { opacity: 1; transform: none; }
#chrome.in .chrome-top .rail:first-child .periph { transition-delay: .04s; }
#chrome.in #wordmark { transition-delay: .10s; }
#chrome.in .chrome-bottom .periph:nth-child(1) { transition-delay: .14s; }
#chrome.in .chrome-bottom .periph:nth-child(2) { transition-delay: .20s; }
#chrome.in .chrome-bottom .periph:nth-child(3) { transition-delay: .26s; }
#chrome.out .periph { opacity: 0; transform: translateY(calc(var(--u) * 2.2)) scale(.9); }
#chrome.out #wordmark { transform: translateY(calc(var(--u) * -2.4)) scale(.85); }
#chrome.out .chrome-top .rail .periph { transform: translateY(calc(var(--u) * -2.4)) scale(.85); }
#chrome.hidden { visibility: hidden; }

/* ------------------------------------------------------------------ HUD */

/* Hidden means hidden. `opacity: 0` still hit-tests, and two children in here
   re-enable pointer-events (the end-run button and the drift pad), so an idle HUD
   would silently eat the taps aimed at SETTINGS and FREE COINS underneath it. The
   zero-length visibility transition is delayed by the fade so the fade-out still
   plays, and undelayed on the way in so the HUD is live immediately. It also takes
   the idle HUD out of the accessibility tree, which opacity alone does not. */
#hud {
  position: absolute; inset: 0;
  z-index: 2;
  padding: inherit;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s var(--ease-out), visibility 0s linear .3s;
}
#hud.in {
  opacity: 1;
  visibility: visible;
  transition: opacity .3s var(--ease-out), visibility 0s linear 0s;
}

.hud-top {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--u);
}
.score-stack { display: flex; flex-direction: column; align-items: center; line-height: .95; }
.score { font-size: calc(var(--u) * 2.9); color: #fff; }
.delta {
  font-size: calc(var(--u) * 1.1); color: var(--sun);
  opacity: 0; transform: translateY(calc(var(--u) * -0.5));
}
.delta.pop { animation: deltaPop .55s var(--ease-out); }
@keyframes deltaPop {
  0% { opacity: 0; transform: translateY(0) scale(.7); }
  25% { opacity: 1; transform: translateY(calc(var(--u) * -0.35)) scale(1.12); }
  100% { opacity: 0; transform: translateY(calc(var(--u) * -1.1)) scale(1); }
}

.combo {
  font-size: calc(var(--u) * 1.7);
  color: var(--sun);
  min-width: calc(var(--u) * 3.4);
  text-align: right;
  transition: transform .16s var(--ease-back), color .2s;
}
.combo.hot { color: var(--pink); }
.combo.bump { transform: scale(1.28) rotate(-4deg); }

#speedo {
  position: absolute;
  right: calc(var(--safe-r) + var(--u) * 0.8);
  bottom: calc(var(--safe-b) + var(--u) * 7.4);
  display: flex; flex-direction: column; align-items: flex-end;
  line-height: .9;
}
.sp-val { font-size: calc(var(--u) * 2.6); color: #fff; }
/* Trailing letter-spacing adds a phantom space after the last glyph, which pushes
   right-aligned text off the edge. The negative margin takes it back. */
.sp-unit { font-size: calc(var(--u) * 0.78); color: var(--ink); letter-spacing: .16em;
           margin-top: calc(var(--u)*.1); margin-right: -.16em; }
.sp-track {
  width: calc(var(--u) * 7.5); height: calc(var(--u) * 0.7);
  margin-top: calc(var(--u) * 0.35);
  background: rgba(255,246,232,.8);
  border: calc(var(--u) * 0.14) solid var(--ink);
  border-radius: 999px; overflow: hidden;
}
#speedBar {
  height: 100%; width: 0%;
  background: linear-gradient(90deg, var(--lime), var(--sun) 55%, var(--pink));
  transition: width .08s linear;
}

#dmgWrap {
  position: absolute;
  left: calc(var(--safe-l) + var(--u) * 0.8);
  bottom: calc(var(--safe-b) + var(--u) * 1.2);
  width: calc(var(--u) * 8);
}
.dmg-label { font-size: calc(var(--u) * 0.75); letter-spacing: .16em; color: var(--ink);
             margin-bottom: calc(var(--u)*.2); }
.dmg-track {
  height: calc(var(--u) * 0.85);
  background: rgba(255,246,232,.85);
  border: calc(var(--u) * 0.14) solid var(--ink);
  border-radius: 999px; overflow: hidden;
}
#dmgBar {
  height: 100%; width: 0%;
  background: linear-gradient(90deg, var(--lime), var(--sun) 50%, var(--pink));
  transition: width .2s var(--ease-out);
}

/* Anchored clear of the idle chrome's bottom row. The visibility gate above already
   makes the overlap harmless, but two controls sharing a corner is one z-order
   accident away from being a bug again. */
.drift-pad {
  pointer-events: auto;
  position: absolute;
  right: calc(var(--safe-r) + var(--u) * 0.8);
  bottom: calc(var(--safe-b) + var(--u) * 1.0);
  width: calc(var(--u) * 5.4); height: calc(var(--u) * 5.4);
  border-radius: 50%;
  border: var(--line) solid var(--ink);
  background: var(--pink);
  box-shadow: 0 var(--drop) 0 var(--pink-d);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: calc(var(--u) * 0.15);
  color: #fff; font-weight: 900; font-size: calc(var(--u) * 0.8);
  -webkit-text-stroke: calc(var(--u) * 0.07) var(--ink);
  paint-order: stroke fill;
  transition: transform .1s var(--ease-out), box-shadow .1s var(--ease-out), background .12s;
  cursor: pointer;
}
.drift-pad .dp-ico {
  width: calc(var(--u) * 1.7); height: calc(var(--u) * 1.1);
  border-radius: calc(var(--u) * 0.3);
  background: #fff;
  border: calc(var(--u) * 0.14) solid var(--ink);
  transform: skewX(-22deg);
}
.drift-pad.held { transform: translateY(var(--drop)); box-shadow: 0 0 0 var(--pink-d); background: var(--sun); }

.banner {
  position: absolute; left: 50%; top: 38%;
  transform: translate(-50%, -50%) scale(.6);
  font-size: calc(var(--u) * 2.6);
  color: var(--sun);
  opacity: 0;
  pointer-events: none;
}
.banner.show { animation: bannerPop 1.1s var(--ease-out); }
@keyframes bannerPop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.5) rotate(-8deg); }
  18% { opacity: 1; transform: translate(-50%, -50%) scale(1.15) rotate(3deg); }
  72% { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0); }
  100% { opacity: 0; transform: translate(-50%, -80%) scale(1); }
}

/* ------------------------------------------------------------------ tutorial */

/* Sits high, over the empty sky band. The car lives at the bottom centre of the
   frame and the coaching card must never be on top of it. */
#tutorial {
  position: absolute; left: 50%; top: 21%;
  transform: translateX(-50%);
  pointer-events: none;
  opacity: 0;
  transition: opacity .35s var(--ease-out), transform .45s var(--ease-back);
}
#tutorial.in { opacity: 1; }
#tutorial.out { opacity: 0; transform: translateX(-50%) scale(.82) translateY(calc(var(--u) * -1.2)); }
.tut-card {
  display: flex; flex-direction: column; align-items: center;
  gap: calc(var(--u) * 0.45);
  background: rgba(255, 246, 232, .92);
  border: var(--line) solid var(--ink);
  border-radius: var(--r-lg);
  padding: calc(var(--u) * 0.9) calc(var(--u) * 1.5);
  box-shadow: 0 var(--drop) 0 #e0c9a8;
}
.tut-title { font-size: calc(var(--u) * 1.5); color: var(--pink); }
.tut-sub { font-size: calc(var(--u) * 0.85); color: var(--ink-soft); letter-spacing: .03em; }
.tut-row { position: relative; display: flex; align-items: center; justify-content: center; height: calc(var(--u) * 2.6); width: calc(var(--u) * 10); }
.tut-hand { position: absolute; left: 50%; animation: handSwipe 2.4s var(--ease-out) infinite; }
.tut-hand .hand {
  display: block;
  width: calc(var(--u) * 1.5); height: calc(var(--u) * 1.5);
  border-radius: 50% 50% 50% 12%;
  background: #fff;
  border: calc(var(--u) * 0.16) solid var(--ink);
  box-shadow: inset 0 calc(var(--u)*-0.25) 0 rgba(43,47,74,.12);
}
@keyframes handSwipe {
  0%, 100% { transform: translate(-50%, 0) scale(1); }
  20% { transform: translate(-190%, 0) scale(.94); }
  55% { transform: translate(90%, 0) scale(.94); }
  80% { transform: translate(-50%, 0) scale(1); }
}
.tut-arrows { position: absolute; inset: 0; display: flex; align-items: center; justify-content: space-between; }
.tut-arrows .a {
  width: 0; height: 0;
  border-top: calc(var(--u) * 0.65) solid transparent;
  border-bottom: calc(var(--u) * 0.65) solid transparent;
  opacity: .75;
}
.tut-arrows .a.left { border-right: calc(var(--u) * 0.9) solid var(--sky); }
.tut-arrows .a.right { border-left: calc(var(--u) * 0.9) solid var(--sky); }

/* ------------------------------------------------------------------ panels */

.panel {
  position: absolute; inset: 0;
  z-index: 20;
  display: none;
  align-items: center; justify-content: center;
  padding: calc(var(--safe-t) + var(--u)) calc(var(--safe-r) + var(--u))
           calc(var(--safe-b) + var(--u)) calc(var(--safe-l) + var(--u));
  background: rgba(43, 47, 74, .34);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  pointer-events: auto;
  opacity: 0;
}
/* The open state is a STATIC style and the keyframes only supply the motion into it.
   Relying on `animation-fill-mode: forwards` to hold the final value leaves the panel
   invisible anywhere animations do not run - reduced-motion settings, a throttled
   background tab, a capture browser. The interface has to be correct without them. */
.panel.open { display: flex; opacity: 1; animation: panelIn .26s var(--ease-out); }
/* Nothing is hit-testable while a panel is leaving: for 240 ms the card was still
   catching taps aimed at whatever it was uncovering, and swallowing them silently. */
.panel.closing { display: flex; opacity: 0; pointer-events: none; animation: panelOut .2s var(--ease-out); }
@keyframes panelIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes panelOut { from { opacity: 1; } to { opacity: 0; } }

.panel-card {
  width: min(calc(var(--u) * 32), 96%);
  max-height: 94%;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  background: linear-gradient(180deg, var(--cream), var(--cream-2));
  border: calc(var(--u) * 0.28) solid var(--ink);
  border-radius: calc(var(--u) * 2);
  box-shadow: 0 calc(var(--u) * 0.7) 0 rgba(43,47,74,.35);
  padding: calc(var(--u) * 1.1);
  display: flex; flex-direction: column; gap: calc(var(--u) * 0.8);
  transform: scale(.86) translateY(calc(var(--u) * 1.2));
  opacity: 0;
}
.panel.open .panel-card {
  transform: scale(1) translateY(0); opacity: 1;
  animation: cardIn .34s var(--ease-back) .04s backwards;
}
.panel.closing .panel-card {
  transform: scale(.9) translateY(calc(var(--u) * .8)); opacity: 0;
  animation: cardOut .2s var(--ease-out);
}
@keyframes cardIn { from { transform: scale(.86) translateY(calc(var(--u) * 1.2)); opacity: 0; } }
@keyframes cardOut { from { transform: scale(1); opacity: 1; } }

.small-card { width: min(calc(var(--u) * 22), 92%); align-items: center; text-align: center; }
/* .small-card centres its children, which was also centring the header - and with it
   the close button. The head is always full width so the X stays in the corner. */
.small-card .panel-head { width: 100%; }

.panel-head { display: flex; align-items: center; justify-content: space-between; gap: var(--u); }
.ph-title { font-size: calc(var(--u) * 1.7); color: var(--pink); }

/* --------- map list --------- */

.map-list { display: flex; flex-direction: column; gap: calc(var(--u) * 0.7); }

.map-row {
  pointer-events: auto;
  display: flex; align-items: center; gap: calc(var(--u) * 0.8);
  background: #fff;
  border: calc(var(--u) * 0.22) solid var(--ink);
  border-radius: var(--r-lg);
  padding: calc(var(--u) * 0.7);
  box-shadow: 0 calc(var(--u) * 0.34) 0 rgba(43,47,74,.2);
  cursor: pointer;
  transition: transform .12s var(--ease-out), box-shadow .12s var(--ease-out);
  position: relative;
}
.map-row:active { transform: translateY(calc(var(--u) * 0.28)); box-shadow: 0 calc(var(--u) * .06) 0 rgba(43,47,74,.2); }
.map-row.active { border-color: var(--lime-d); background: #f2ffe9; }
.map-row.locked .map-thumb { filter: saturate(.3) brightness(1.06); }

.map-thumb {
  width: calc(var(--u) * 5.2); height: calc(var(--u) * 3.6);
  border-radius: var(--r-md);
  border: calc(var(--u) * 0.18) solid var(--ink);
  flex: none;
  position: relative;
  overflow: hidden;
}
.map-thumb .road { position: absolute; left: 0; right: 0; top: 55%; height: 22%; opacity: .85; }
.map-thumb .sun  { position: absolute; right: 12%; top: 12%; width: 22%; aspect-ratio: 1; border-radius: 50%; background: #fff3a8; border: calc(var(--u)*.12) solid var(--ink); }

.map-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: calc(var(--u) * 0.18); }
.map-name { font-size: calc(var(--u) * 1.02); font-weight: 900; color: var(--ink);
            text-transform: uppercase; line-height: 1.05; }
/* Two lines, hard stop. A long blurb must never be able to push a row tall enough to
   scroll the third map off a phone screen. */
.map-blurb {
  font-size: calc(var(--u) * 0.76); color: var(--ink-soft); font-weight: 700; line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.map-tag {
  align-self: flex-start;
  font-size: calc(var(--u) * 0.66); letter-spacing: .1em;
  background: var(--lime); color: #fff;
  -webkit-text-stroke: calc(var(--u)*0.05) var(--ink); paint-order: stroke fill;
  border: calc(var(--u) * 0.12) solid var(--ink);
  border-radius: 999px; padding: 0 calc(var(--u) * 0.45);
}
.map-tag.locked { background: var(--tan); }
.map-cta { flex: none; display: flex; align-items: center; }
.map-cta .btn { padding: calc(var(--u) * 0.55) calc(var(--u) * 0.95); font-size: calc(var(--u) * 0.95); }

/* --------- garage --------- */

.garage-top { display: flex; flex-direction: column; align-items: center; gap: calc(var(--u) * 0.4); text-align: center; }
.g-name { font-size: calc(var(--u) * 1.4); color: var(--sky-d); -webkit-text-stroke: 0; text-shadow: none; }
.g-blurb { font-size: calc(var(--u) * 0.78); color: var(--ink-soft); font-weight: 700;
           line-height: 1.28; min-height: calc(var(--u) * 2.0); }
.g-stats { display: flex; flex-direction: column; gap: calc(var(--u) * 0.22); width: 100%; }
.st { display: flex; align-items: center; gap: calc(var(--u) * 0.5); font-size: calc(var(--u) * 0.76); letter-spacing: .08em; color: var(--ink); }
.st > span { width: calc(var(--u) * 3.6); text-align: left; }
.st-track { flex: 1; height: calc(var(--u) * 0.62); background: #fff; border: calc(var(--u) * 0.12) solid var(--ink); border-radius: 999px; overflow: hidden; }
.st-track > div { height: 100%; width: 0%; background: var(--sky); transition: width .3s var(--ease-out); }

.garage-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: calc(var(--u) * 0.45); }
/* Cars are wide, so the cell is wide: a square cell wastes a third of its height
   on empty sky and pushes the bottom row off a phone screen. */
.car-cell {
  pointer-events: auto;
  position: relative;
  aspect-ratio: 4 / 3;
  border: calc(var(--u) * 0.2) solid var(--ink);
  border-radius: var(--r-md);
  background: #fff;
  box-shadow: 0 calc(var(--u) * 0.3) 0 rgba(43,47,74,.18);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: transform .12s var(--ease-out), box-shadow .12s var(--ease-out);
  overflow: hidden;
}
.car-cell:active { transform: translateY(calc(var(--u) * .24)); box-shadow: 0 0 0 rgba(43,47,74,.18); }
.car-cell.sel { border-color: var(--lime-d); background: #f2ffe9; }
/* Portraits are rendered from the real car models at runtime (js/render/thumbs.js),
   so the grid always matches what the player will actually drive. */
.car-pic { width: 100%; height: 100%; object-fit: contain; display: block; }
.car-cell.locked .car-pic { filter: saturate(.25) brightness(1.08); }
.g-pic {
  width: calc(var(--u) * 9); height: calc(var(--u) * 5.8);
  object-fit: contain; display: block;
  margin-bottom: calc(var(--u) * -0.4);
}
.car-cell .price {
  position: absolute; bottom: calc(var(--u) * 0.18);
  background: rgba(255, 246, 232, .92); border-radius: 999px;
  padding: 0 calc(var(--u) * 0.3);
  font-size: calc(var(--u) * 0.66); font-weight: 900; color: var(--ink);
  display: flex; align-items: center; gap: calc(var(--u) * 0.16);
}
.car-cell .adtag {
  position: absolute; top: calc(var(--u) * 0.2); right: calc(var(--u) * 0.2);
  background: #ff3b52; color: #fff; border: calc(var(--u)*.12) solid var(--ink);
  border-radius: 999px; font-size: calc(var(--u) * 0.55); padding: 0 calc(var(--u)*.3);
}
.car-cell .owned {
  position: absolute; top: calc(var(--u) * 0.2); right: calc(var(--u) * 0.2);
  color: var(--lime-d); font-size: calc(var(--u) * 0.9);
}

/* --------- results --------- */

.result-card { align-items: center; text-align: center; gap: calc(var(--u) * 0.42); }
.res-title { font-size: calc(var(--u) * 1.85); color: var(--pink); }
.res-record {
  font-size: calc(var(--u) * 1.05); color: var(--sun);
  opacity: 0; height: 0; overflow: hidden;
}
.res-record.show { opacity: 1; height: auto; animation: bannerPop 1.4s var(--ease-out) backwards; }
/* Filled, not white-on-cream: as the largest number on the screen this was somehow
   the hardest thing on the card to read. */
.res-score { font-size: calc(var(--u) * 3); color: var(--sun); line-height: 1; }
.res-sub { font-size: calc(var(--u) * 0.74); letter-spacing: .18em; color: var(--ink-soft); margin-top: calc(var(--u) * -0.35); }
.res-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: calc(var(--u) * 0.45); width: 100%; }
.rg {
  background: #fff; border: calc(var(--u) * 0.18) solid var(--ink); border-radius: var(--r-md);
  padding: calc(var(--u) * 0.36) calc(var(--u) * 0.2);
  display: flex; flex-direction: column; align-items: center; gap: calc(var(--u) * 0.06);
}
.rg b { font-size: calc(var(--u) * 1.2); color: var(--sky-d); }
.rg span { font-size: calc(var(--u) * 0.6); letter-spacing: .08em; color: var(--ink-soft); }
.res-coins { display: flex; align-items: center; gap: calc(var(--u) * 0.4); font-size: calc(var(--u) * 1.6); color: var(--sun); }
.res-btns { display: flex; flex-direction: column; gap: calc(var(--u) * 0.4); width: 100%; align-items: stretch; }
.res-btns .btn { width: 100%; }
/* The two navigation actions share a row: with a repair offer on the card there are
   five buttons, and five stacked full-width rows do not fit a 720p window. */
.res-row { display: flex; gap: calc(var(--u) * 0.45); width: 100%; }
.res-row .btn { flex: 1; min-width: 0; }
.res-row #btnAgain { flex: 1.7; }

/* --------- free coins / settings --------- */

.burst {
  position: absolute; width: calc(var(--u) * 16); aspect-ratio: 1; border-radius: 50%;
  background: conic-gradient(from 0deg, rgba(255,217,61,.55) 0 8%, transparent 0 16%);
  animation: spin 14s linear infinite;
  z-index: -1;
}
@keyframes spin { to { transform: rotate(360deg); } }
.free-amount { font-size: calc(var(--u) * 2.6); display: flex; align-items: center; gap: calc(var(--u)*0.4); color: var(--sun); }
.free-sub { font-size: calc(var(--u) * 0.85); color: var(--ink-soft); font-weight: 700; }

.set-row {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  background: #fff; border: calc(var(--u) * 0.18) solid var(--ink); border-radius: var(--r-md);
  padding: calc(var(--u) * 0.5) calc(var(--u) * 0.8);
  font-size: calc(var(--u) * 1);
}
.set-row .fat { color: var(--ink); -webkit-text-stroke: 0; text-shadow: none; }
.switch {
  pointer-events: auto;
  width: calc(var(--u) * 3.4); height: calc(var(--u) * 1.8);
  border-radius: 999px; border: calc(var(--u) * 0.16) solid var(--ink);
  background: var(--grey); position: relative; cursor: pointer; padding: 0;
  transition: background .2s var(--ease-out);
}
.switch .knob {
  position: absolute; top: 50%; left: calc(var(--u) * 0.12);
  width: calc(var(--u) * 1.3); height: calc(var(--u) * 1.3);
  border-radius: 50%; background: #fff; border: calc(var(--u) * 0.14) solid var(--ink);
  transform: translateY(-50%);
  transition: left .2s var(--ease-back);
}
.switch.on { background: var(--lime); }
/* On, but YouTube's own mute is winning. The control is not broken and must not look
   disabled - it just cannot be heard yet. */
.switch.muted { background: var(--tan); }
.switch.on .knob { left: calc(100% - var(--u) * 1.42); }

.set-stats { display: flex; gap: calc(var(--u) * 0.5); width: 100%; }
.set-stats > div {
  flex: 1; background: #fff; border: calc(var(--u) * 0.18) solid var(--ink); border-radius: var(--r-md);
  padding: calc(var(--u) * 0.4); display: flex; flex-direction: column; align-items: center;
}
.set-stats b { font-size: calc(var(--u) * 1.2); color: var(--pink-d); }
.set-stats span { font-size: calc(var(--u) * 0.6); letter-spacing: .06em; color: var(--ink-soft); }

/* ------------------------------------------------------------------ floaters */

/* Layer order, stated once so nothing has to rely on document order:
     world popups 5  <  panels 20  <  toasts 30  <  ads 40  <  pause 45  <  fade 50 */
#popups { position: absolute; inset: 0; pointer-events: none; overflow: hidden; z-index: 5; }
.pop {
  position: absolute;
  font-weight: 900;
  font-size: calc(var(--u) * 1.25);
  color: #fff;
  -webkit-text-stroke: calc(var(--u) * 0.1) var(--ink);
  paint-order: stroke fill;
  transform: translate(-50%, -50%);
  animation: popFloat .95s var(--ease-out) forwards;
  white-space: nowrap;
}
.pop.big { font-size: calc(var(--u) * 1.8); color: var(--sun); }
@keyframes popFloat {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.5); }
  20% { opacity: 1; transform: translate(-50%, -60%) scale(1.15); }
  100% { opacity: 0; transform: translate(-50%, -170%) scale(.95); }
}

/* High enough to clear an open panel card, which starts around 7% of the height. */
#toasts {
  position: absolute; left: 50%; top: calc(var(--safe-t) + var(--u) * 4.2);
  z-index: 30;
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: calc(var(--u) * 0.35);
  pointer-events: none;
  width: max-content; max-width: 88%;
}
.toast {
  display: flex; align-items: center; gap: calc(var(--u) * 0.4);
  background: var(--cream);
  border: var(--line) solid var(--ink);
  border-radius: 999px;
  padding: calc(var(--u) * 0.42) calc(var(--u) * 1.1);
  font-size: calc(var(--u) * 0.98);
  font-weight: 900;
  color: var(--ink);
  box-shadow: 0 var(--drop) 0 rgba(43,47,74,.25);
  animation: toastIn .3s var(--ease-back), toastOut .3s var(--ease-out) 2.1s forwards;
  text-align: center;
}
.toast.warn { background: var(--sun); }
.toast.bad { background: var(--pink); color: #fff; -webkit-text-stroke: calc(var(--u)*.06) var(--ink); paint-order: stroke fill; }
.toast.good { background: var(--lime); color: #fff; -webkit-text-stroke: calc(var(--u)*.06) var(--ink); paint-order: stroke fill; }
.toast .coin { width: calc(var(--u) * 1); height: calc(var(--u) * 1); }
@keyframes toastIn { from { opacity: 0; transform: translateY(calc(var(--u) * -1.2)) scale(.8); } }
@keyframes toastOut { to { opacity: 0; transform: translateY(calc(var(--u) * -0.8)) scale(.92); } }

/* ------------------------------------------------------------------ overlays */

#adOverlay {
  position: absolute; inset: 0;
  display: none; align-items: center; justify-content: center;
  background: rgba(43,47,74,.72);
  pointer-events: auto;
  z-index: 40;
}
#adOverlay.on { display: flex; animation: panelIn .2s var(--ease-out); }
.ad-box {
  background: var(--cream);
  border: calc(var(--u) * 0.28) solid var(--ink);
  border-radius: calc(var(--u) * 1.4);
  padding: calc(var(--u) * 1.4) calc(var(--u) * 1.8);
  display: flex; flex-direction: column; align-items: center; gap: calc(var(--u) * 0.6);
  box-shadow: 0 calc(var(--u) * 0.6) 0 rgba(43,47,74,.4);
}
#adLabel { font-size: calc(var(--u) * 1.3); color: var(--pink); }
.ad-track { width: calc(var(--u) * 14); height: calc(var(--u) * 0.9);
  background: #fff; border: calc(var(--u) * 0.16) solid var(--ink); border-radius: 999px; overflow: hidden; }
.ad-fill { height: 100%; width: 0; background: var(--lime); animation: adFill 2.4s linear forwards; }
@keyframes adFill { to { width: 100%; } }
.ad-note { font-size: calc(var(--u) * 0.7); color: var(--ink-soft); font-weight: 700; }

#pauseOverlay {
  position: absolute; inset: 0; display: none;
  align-items: center; justify-content: center;
  background: rgba(43,47,74,.5); pointer-events: auto; z-index: 45;
}
#pauseOverlay.on { display: flex; }
.pause-card { font-size: calc(var(--u) * 2.6); color: #fff; }

#fade {
  position: absolute; inset: 0;
  background: #fff6e8;
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s var(--ease-out);
  z-index: 50;
}
#fade.on { opacity: 1; pointer-events: auto; }

#boot {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: calc(var(--u) * 1.2);
  background: linear-gradient(180deg, #8fe0ff, #fff2c9);
  z-index: 60;
  pointer-events: auto;
  transition: opacity .4s var(--ease-out);
}
#boot.gone { opacity: 0; pointer-events: none; }
.boot-logo { display: flex; flex-direction: column; align-items: center; line-height: .9; transform: rotate(-3deg); }
.boot-logo .wm-a, .boot-logo .wm-b {
  font-weight: 900; text-transform: uppercase;
  -webkit-text-stroke: calc(var(--u) * 0.24) var(--ink);
  paint-order: stroke fill;
  text-shadow: 0 calc(var(--u) * 0.28) 0 rgba(43,47,74,.35);
  animation: logoIn .6s var(--ease-back) both;
}
.boot-logo .wm-a { color: var(--sun); font-size: calc(var(--u) * 3.4); }
.boot-logo .wm-b {
  color: var(--pink); animation-delay: .1s;
  font-size: calc(var(--u) * 0.95);
  letter-spacing: .22em; margin-right: -.22em;
  -webkit-text-stroke: calc(var(--u) * 0.12) var(--ink);
  margin-top: calc(var(--u) * 0.3);
}
@keyframes logoIn { from { opacity: 0; transform: translateY(calc(var(--u) * 1.5)) scale(.8); } }
.boot-track {
  width: calc(var(--u) * 14); height: calc(var(--u) * 1);
  background: rgba(255,255,255,.7);
  border: calc(var(--u) * 0.18) solid var(--ink);
  border-radius: 999px; overflow: hidden;
}
#bootBar { height: 100%; width: 0%; background: var(--lime); transition: width .25s var(--ease-out); }

/* ------------------------------------------------------------------ short viewports */

/* A phone held sideways has plenty of width and almost no height, so the garage - the
   tallest panel in the game - is re-laid as two columns instead of being allowed to
   scroll. Every other panel already fits. */
@media (max-height: 620px) and (min-aspect-ratio: 1/1) {
  /* Five stacked actions plus a stat row do not fit 390 px of height. The card widens
     and splits: the read-out on the left, the actions on the right. */
  #resultScreen .panel-card {
    width: min(calc(var(--u) * 44), 96%);
    display: grid;
    grid-template-columns: 1.15fr 1fr;
    /* Every child needs a named cell. Two of them only had a COLUMN, which drops
       them into implicit rows underneath the whole card - the record banner and the
       "DESTRUCTION SCORE" caption ended up below the coin count. */
    grid-template-areas:
      "title  title"
      "rec    btns"
      "score  btns"
      "sub    btns"
      "grid   btns"
      "coins  btns";
    column-gap: calc(var(--u) * 1);
    align-content: start;
    justify-items: center;
  }
  #resultScreen .res-title { grid-area: title; }
  #resultScreen .res-record { grid-area: rec; }
  #resultScreen .res-score { grid-area: score; align-self: end; }
  #resultScreen .res-sub { grid-area: sub; }
  #resultScreen .res-grid { grid-area: grid; }
  #resultScreen .res-coins { grid-area: coins; }
  #resultScreen .res-btns { grid-area: btns; align-self: center; }

  #garageScreen .panel-card {
    width: min(calc(var(--u) * 46), 96%);
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    grid-template-areas: "head head" "top grid";
    column-gap: calc(var(--u) * 1);
    align-items: start;
  }
  #garageScreen .panel-head { grid-area: head; }
  #garageScreen .garage-top { grid-area: top; }
  #garageScreen .garage-grid { grid-area: grid; }
  #garageScreen .g-pic { width: calc(var(--u) * 8); height: calc(var(--u) * 5); }
}

/* Very short viewports get a flatter interface so the road stays visible. */
@media (max-height: 460px) {
  :root { --u: clamp(10px, 3.0vh + 0.3vmin, 16px); }
  #tutorial { top: 14%; }
  #speedo { bottom: calc(var(--safe-b) + var(--u) * 6.2); }
}

/* A refused tap shakes rather than doing nothing, and is always paired with a toast
   explaining the refusal (see WW.ui.deny). */
.shake { animation: shakeNo .34s var(--ease-out); }
@keyframes shakeNo {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(calc(var(--u) * -0.5)) rotate(-2deg); }
  45% { transform: translateX(calc(var(--u) * 0.45)) rotate(2deg); }
  70% { transform: translateX(calc(var(--u) * -0.25)) rotate(-1deg); }
}

/* Players who ask their OS for less motion get the same interface with the movement
   removed. Every open/closed state above is a static style, so nothing disappears. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    /* Delays as well: the HUD's visibility gate is a delayed transition, and leaving
       the delay in place would keep an invisible layer hit-testable. */
    transition-delay: 0s !important;
  }
}
