/* =========================================================================
   game.css — HUD chrome and the play frame.

   The frame is full-bleed on a phone and a portrait panel on desktop. It is
   not a fixed aspect: fairness across screen shapes is handled in render.js
   by locking horizontal FOV, so the frame is free to fill whatever it gets.
   ========================================================================= */

:root{
  --ink:#10161c;
  --paper:#eef2f4;
  --hot:#ff6a2b;
  --dim:rgba(238,242,244,.55);
  --glass:rgba(11,17,22,.34);
  --edge:rgba(238,242,244,.30);
  --font:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
}

*{box-sizing:border-box;margin:0;padding:0}
html,body{
  height:100%;overflow:hidden;background:#070b0e;
  font-family:var(--font);color:var(--paper);
  -webkit-user-select:none;user-select:none;
  -webkit-tap-highlight-color:transparent;
  touch-action:none;overscroll-behavior:none;-webkit-touch-callout:none;
}
body{display:flex;align-items:center;justify-content:center}
canvas{display:block;width:100%;height:100%}

/* ------------------------------------------------------------ the frame */
#app{
  position:relative;
  width:100vw;height:100vh;height:100dvh;
  overflow:hidden;background:#0b1116;
}
#stage{position:absolute;inset:0}

/* Desktop gets a phone-shaped panel rather than a letterboxed slab: the game
   is designed portrait, and a wide window at locked horizontal FOV would show
   almost no sky. The WIDE FRAME below is the deliberate exception, and it
   brings its own lens (render.js setWideFrame). */
@media (min-width:760px){
  body{
    background:
      radial-gradient(120% 80% at 50% 0%, #1d2735 0%, #0a0e12 60%, #06090b 100%);
  }
  #app{
    /* Fill the monitor's height, always, with a little breathing room —
       and let the width ride along (44% of the height) so a big display
       gets a bigger panel at the same phone-ish shape, never a taller
       sliver. Fairness is untouched: the horizontal FOV is locked. */
    width:min(max(470px, 44dvh), 100vw);
    height:calc(100dvh - 44px);
    border-radius:14px;
    box-shadow:0 30px 90px -30px rgba(0,0,0,.9), 0 0 0 1px rgba(238,242,244,.08);
  }
  /* WIDE FRAME (Settings, desktop only; main.js sets body.wide): the biggest
     16:9 box the window holds, square-cornered and flush, so a 16:9 window
     — fullscreen on a 16:9 monitor — is filled edge to edge and a recording
     carries no bezel. */
  body.wide #app{
    width:min(100vw, calc(100dvh * 16 / 9));
    height:min(100dvh, calc(100vw * 9 / 16));
    border-radius:0;
  }
}
/* keyboard territory: in the wide frame the thumb pedals would only be in
   the recording */
@media (min-width:760px) and (pointer:fine){
  body.wide #controls{display:none}
}

/* ---------------------------------------------------------------- HUD */
#hud{
  position:absolute;inset:0;pointer-events:none;
  text-shadow:0 1px 3px rgba(0,0,0,.45);
}
/* One dial over the whole in-game UI (settings card sets --uiscale). zoom
   scales the subtree while corner- and bottom-anchoring stay put, and it
   works whatever units the sizes below use. */
#hud, #controls{ zoom:var(--uiscale, 1); }
.readout{
  position:absolute;line-height:1;
  top:calc(14px + env(safe-area-inset-top));
  left:calc(16px + env(safe-area-inset-left));
}
.big{font-size:40px;font-weight:700;letter-spacing:-2px;font-variant-numeric:tabular-nums}
.unit{font-size:12px;letter-spacing:2px;color:var(--dim);margin-left:4px}
.sub{margin-top:6px;font-size:11px;letter-spacing:1.5px;color:var(--dim);font-variant-numeric:tabular-nums}

.chiprow{margin-top:10px;display:flex;gap:8px}
#time,#streak{
  display:inline-block;
  font-size:19px;font-weight:700;letter-spacing:1px;
  font-variant-numeric:tabular-nums;color:var(--paper);
  padding:3px 9px;border-radius:3px;
  border:1px solid rgba(238,242,244,.26);background:rgba(11,17,22,.30);
  transition:color .15s,background .15s,border-color .15s;
}
/* the clock running dry is the loudest thing on the screen */
#time.low{
  color:#fff;background:#c2311f;border-color:#c2311f;
  box-shadow:0 0 18px rgba(194,49,31,.65);
}
/* a deep streak earns the hot chip the multiplier used to wear */
#streak.max{
  color:var(--ink);background:var(--hot);border-color:var(--hot);
  box-shadow:0 0 18px rgba(255,106,43,.55);
}
/* campaign: the same chip carries the time penalty instead */
#streak.pen{
  color:#fff;background:#c2311f;border-color:#c2311f;
}

/* The dial: one instrument for the three things that move — the ring is
   the revs, the gear stands in the middle of it, and the road speed sits
   underneath. Sits below the MENU row, clear of both thumbs. */
.speedo{
  position:absolute;
  top:calc(64px + env(safe-area-inset-top));
  right:calc(12px + env(safe-area-inset-right));
  /* sized to clear the streak chip even on a 360-wide phone */
  width:98px;height:98px;
}
.speedo svg{position:absolute;inset:0;width:100%;height:100%;transform:rotate(135deg)}
.speedo circle{fill:none;stroke-linecap:round;stroke-width:8}
.speedo .track{stroke:rgba(238,242,244,.20)}
.speedo .redline{stroke:rgba(255,59,47,.55);stroke-width:3.4}
.speedo .rev{
  stroke:var(--hot);
  filter:drop-shadow(0 0 5px rgba(255,106,43,.55));
  transition:stroke-dasharray .06s linear;
}
.speedo.red .rev{stroke:#ff3b2f;filter:drop-shadow(0 0 7px rgba(255,59,47,.7))}
.speedo .face{
  position:absolute;inset:9px;border-radius:50%;
  background:rgba(11,17,22,.42);
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
}
.speedo.third .face{box-shadow:inset 0 0 16px rgba(255,106,43,.35)}
#gearnum{
  font-size:32px;font-weight:700;line-height:.92;color:var(--paper);
  font-variant-numeric:tabular-nums;
}
.speedo.third #gearnum{color:var(--hot)}
#speednum{
  font-size:15px;font-weight:700;color:var(--paper);
  font-variant-numeric:tabular-nums;line-height:1.1;
}
.speedo .unit{font-size:8px;letter-spacing:1.5px;color:var(--dim);font-style:normal}

#air{
  position:absolute;left:50%;transform:translateX(-50%);
  bottom:calc(258px + env(safe-area-inset-bottom));
  font-size:15px;letter-spacing:6px;color:var(--hot);
  opacity:0;transition:opacity .12s;
}
#air.on{opacity:1}

/* Pause sits top-centre: away from both thumbs, so reaching it is deliberate
   rather than something you do by accident mid-corner. */
#bMenu{
  position:absolute;pointer-events:auto;
  top:calc(11px + env(safe-area-inset-top));left:50%;margin-left:-26px;
  width:52px;height:32px;display:flex;align-items:center;justify-content:center;
  border:1px solid rgba(238,242,244,.28);border-radius:3px;background:var(--glass);
  color:var(--paper);font:inherit;font-size:9px;font-weight:700;letter-spacing:2px;
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
  touch-action:manipulation;cursor:pointer;
}

/* The clip recorder's arm switch, beside MENU. Armed shows a hollow dot;
   actually recording, the dot fills red and the label becomes the clock. */
#bRec{
  position:absolute;pointer-events:auto;
  top:calc(11px + env(safe-area-inset-top));left:50%;margin-left:34px;
  min-width:52px;height:32px;padding:0 8px;
  display:flex;align-items:center;justify-content:center;gap:5px;
  border:1px solid rgba(238,242,244,.28);border-radius:3px;background:var(--glass);
  color:var(--dim);font:inherit;font-size:9px;font-weight:700;letter-spacing:2px;
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
  touch-action:manipulation;cursor:pointer;
}
#bRec::before{
  content:'';width:7px;height:7px;border-radius:50%;
  border:1px solid currentColor;flex:none;
}
#bRec.armed{color:var(--paper);border-color:rgba(238,242,244,.45)}
#bRec.live{color:var(--hot);border-color:var(--hot)}
#bRec.live::before{background:var(--hot);border-color:var(--hot);
  animation:recblink 1.1s ease-in-out infinite}
@keyframes recblink{50%{opacity:.35}}

#pop{
  position:absolute;left:50%;transform:translateX(-50%);
  bottom:calc(210px + env(safe-area-inset-bottom));
  font-size:30px;font-weight:700;letter-spacing:1px;color:var(--hot);
  font-variant-numeric:tabular-nums;opacity:0;
  text-shadow:0 1px 10px rgba(11,17,22,.55);
}
/* long enough to actually read at speed: quick pop in, a full second of
   hold, then the drift away. The class is deliberately NOT `go` — that is
   the menu button style, and sharing it painted this text orange-on-orange. */
#pop.show{animation:pop 1.8s ease-out forwards}
@keyframes pop{
  0%  {opacity:0;transform:translate(-50%,12px) scale(.85)}
  7%  {opacity:1;transform:translate(-50%,0) scale(1.10)}
  13% {transform:translate(-50%,-2px) scale(1)}
  62% {opacity:1;transform:translate(-50%,-8px) scale(1)}
  100%{opacity:0;transform:translate(-50%,-40px) scale(.98)}
}

/* ----------------------------------------------------------- controls */
#controls{
  position:absolute;left:0;right:0;
  /* 30px base clears Android's transparent gesture bar, which fullscreen
     Chrome never reports as a safe-area inset; --vvgap (main.js onResize)
     adds whatever part of the layout viewport hangs below the visible one */
  bottom:calc(30px + env(safe-area-inset-bottom) + var(--vvgap, 0px));
  display:flex;flex-direction:column;align-items:center;gap:12px;
  padding:0 calc(16px + env(safe-area-inset-left));
  pointer-events:none;
  transition:bottom .35s ease;
}
/* The controls stay planted: Android's "to exit full screen…" toast briefly
   overlaps them on entry, and the player swipes it away — a dodge animation
   that slid the whole cluster up and back down cost more than it saved. */
body.paused #controls{display:none}

.ctlrow{display:flex;gap:12px;width:100%;align-items:stretch}
.steerrow{display:flex;gap:14px;flex:1;min-width:0}

/* pedal cluster: a BIG gas under the left thumb, the light brake beneath.
   The row height lives on .steer; the brake takes its fixed slice and every
   other pixel goes to the gas. */
.pedals{display:flex;flex-direction:column;gap:10px;flex:0 0 37%}
.pedal{
  pointer-events:auto;cursor:pointer;flex:1;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--edge);border-radius:10px;background:var(--glass);
  color:var(--paper);font:inherit;font-size:11px;font-weight:700;letter-spacing:2px;
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  touch-action:manipulation;
  transition:background .06s linear,border-color .06s linear,transform .06s ease-out;
}
.pedal.brake{flex:0 0 32px;color:var(--dim)}
.pedal.on{background:var(--hot);border-color:var(--hot);color:var(--ink);transform:scale(.97)}
.pedal:focus-visible{outline:2px solid var(--paper);outline-offset:3px}

/* -------------------------------------------------------------- loading */
#loading{
  position:absolute;inset:0;z-index:40;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;
  background:var(--ink);
  opacity:0;visibility:hidden;
  transition:opacity .28s ease-out,visibility 0s linear .28s;
}
#loading.on{opacity:1;visibility:visible;transition:opacity .12s ease-in}
.loadname{
  font-size:15px;font-weight:700;letter-spacing:5px;color:var(--paper);
  text-align:center;padding:0 20px;
}
.loadbar{
  width:min(190px,54vw);height:2px;background:rgba(238,242,244,.16);overflow:hidden;
}
.loadbar span{
  display:block;width:40%;height:100%;background:var(--hot);
  animation:loadslide 1.05s ease-in-out infinite;
}
@keyframes loadslide{
  0%  {transform:translateX(-110%)}
  100%{transform:translateX(360%)}
}

/* ------------------------------------------------------------ start line */
#count{
  position:absolute;left:50%;top:38%;transform:translate(-50%,-50%);
  font-size:96px;font-weight:700;letter-spacing:-4px;line-height:1;
  color:var(--paper);font-variant-numeric:tabular-nums;
  text-shadow:0 2px 30px rgba(11,17,22,.7);
  opacity:0;pointer-events:none;
}
#count.tick{animation:countPop .9s ease-out forwards}
#count.lights{color:var(--hot);letter-spacing:2px;animation:countGo .7s ease-out forwards}

/* On-screen pacenote: the co-driver's call, mirrored where the eyes are.
   Chevrons stack with severity; red is the board that means brake NOW.

   It used to sit 120px down, which put it in the top corner with the clock —
   the one place you are NOT looking while driving, so reading it cost a
   whole glance up and back. It now sits just above the car and just below
   the horizon, which is where the eyes already are: the call lands in
   peripheral vision without leaving the road. Percentage rather than pixels
   so it holds that relationship on a phone and on a desktop both.

   --pacetop is the settings slider: where the eye line falls depends on the
   screen, the camera height and frankly the player, so 48% is a default
   rather than an answer. */
/* The minimap: a faint panel under the timer's readout (it lives inside
   .readout, so it sits under the chips on an endless run and under the
   gate line on a stage), the road drawn on it by minimap.js. Taller than
   wide because it is a strip of what is ahead. Sized off the viewport,
   capped so the desktop frame does not get a poster of it. */
#minimap{
  display:block;margin-top:12px;
  width:min(28vw, 180px, 24vh);height:auto;aspect-ratio:1 / 1.15;
  border-radius:8px;background:rgba(11,17,22,.22);border:1px solid rgba(238,242,244,.10);
  -webkit-backdrop-filter:blur(1.5px);backdrop-filter:blur(1.5px);
  pointer-events:none;transition:opacity .25s;
}
#minimap.hidden{display:none}
#pace{
  position:absolute;left:50%;top:calc(var(--pacetop, 48%) + env(safe-area-inset-top));
  transform:translateX(-50%);
  display:flex;align-items:center;gap:9px;
  padding:8px 16px;border-radius:6px;
  background:rgba(11,17,22,.55);border:1px solid rgba(255,176,102,.65);
  color:#ffcf8a;font-size:17px;font-weight:700;letter-spacing:3px;
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  opacity:0;pointer-events:none;white-space:nowrap;
}
#pace .chev{font-size:20px;letter-spacing:-2px;line-height:1}
#pace.red{border-color:#ff5a3d;color:#ffb0a0;background:rgba(40,10,6,.6)}
#pace.show{animation:paceIn 2.1s ease-out forwards}
@keyframes paceIn{
  0%{opacity:0;transform:translateX(-50%) scale(.85)}
  8%{opacity:1;transform:translateX(-50%) scale(1.04)}
  14%{transform:translateX(-50%) scale(1)}
  78%{opacity:1}
  100%{opacity:0;transform:translateX(-50%) scale(.97)}
}
@keyframes countPop{
  0%  {opacity:0;transform:translate(-50%,-50%) scale(1.5)}
  14% {opacity:1;transform:translate(-50%,-50%) scale(1)}
  70% {opacity:1}
  100%{opacity:0;transform:translate(-50%,-50%) scale(.92)}
}
@keyframes countGo{
  0%  {opacity:0;transform:translate(-50%,-50%) scale(.7)}
  12% {opacity:1;transform:translate(-50%,-50%) scale(1.12)}
  30% {transform:translate(-50%,-50%) scale(1)}
  100%{opacity:0;transform:translate(-50%,-50%) scale(1.3)}
}

/* The steering strip is TWO HALVES, and the whole of the live half lights
   up — because the whole of it steers the same amount. A dot tracking the
   thumb would be a lie about a control that no longer cares where the
   thumb is. touch-action:none is load-bearing — anything else lets the
   browser steal the drag for scrolling mid-corner. */
.steer{
  pointer-events:auto;cursor:pointer;flex:1;position:relative;overflow:hidden;
  height:118px;display:flex;align-items:center;justify-content:space-between;
  padding:0 20px;
  border:1px solid var(--edge);border-radius:10px;background:var(--glass);
  color:var(--paper);font:inherit;
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  touch-action:none;
  user-select:none;-webkit-user-select:none;
  transition:border-color .06s linear;
}
.steer svg{position:relative;z-index:1;
  width:38px;height:38px;fill:none;stroke:currentColor;stroke-width:2.4;
  stroke-linecap:round;stroke-linejoin:round;opacity:.6}
/* --ax is -1 or +1, so this lands flush on one half or the other. The short
   slide on `left` is what makes crossing the middle read as a swap rather
   than a teleport. */
.steer .thumb{
  position:absolute;top:0;bottom:0;width:50%;
  left:calc(25% + var(--ax, 0)*25%);
  background:rgba(255,106,43,.24);
  opacity:0;transition:opacity .1s linear, left .07s linear;
}
.steer.on{border-color:var(--hot)}
.steer.on .thumb{opacity:1}
.steer:focus-visible{outline:2px solid var(--paper);outline-offset:3px}

/* ------------------------------------------------------------- cards */
.card{
  position:absolute;inset:0;z-index:5;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:18px;text-align:center;overflow-y:auto;
  background:rgba(11,17,22,.72);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  padding:max(24px,env(safe-area-inset-top)) max(24px,env(safe-area-inset-right))
          max(24px,env(safe-area-inset-bottom)) max(24px,env(safe-area-inset-left));
}
.card h1{font-size:clamp(34px,13vw,62px);font-weight:700;letter-spacing:-2px;line-height:.94}
.card .lede{font-size:13px;letter-spacing:1px;color:var(--dim);max-width:30ch;line-height:1.7}
.card .keys{font-size:12px;letter-spacing:1px;color:var(--dim);line-height:2}
.card kbd{
  background:rgba(238,242,244,.1);border:1px solid rgba(238,242,244,.2);
  border-radius:3px;padding:2px 7px;font:inherit;
}
.stat{font-size:52px;font-weight:700;letter-spacing:-2px;font-variant-numeric:tabular-nums;line-height:1}
.row{display:flex;gap:12px;align-items:center;justify-content:center;flex-wrap:wrap}

.tally{display:flex;gap:22px;justify-content:center;flex-wrap:wrap}
.tally dt{font-size:9px;letter-spacing:2px;color:var(--dim);margin-bottom:5px}
.tally dd{font-size:15px;font-weight:700;letter-spacing:0;font-variant-numeric:tabular-nums}

.go,.ghost{font:inherit;font-weight:700;letter-spacing:3px;border-radius:2px;
  cursor:pointer;touch-action:manipulation}
.go{border:0;background:var(--hot);color:var(--ink);font-size:14px;padding:14px 34px}
.ghost{background:transparent;border:1px solid rgba(238,242,244,.3);color:var(--paper);
  font-size:13px;padding:14px 22px}
.go:focus-visible,.ghost:focus-visible{outline:2px solid var(--paper);outline-offset:3px}
/* a button that is present but not yet live — SAVE CLIP while the file writes */
.go:disabled,.ghost:disabled{opacity:.42;cursor:default}

/* ---------------------------------------------------------- submission */
.submit{display:flex;flex-direction:column;align-items:center;gap:8px}
.submit label{font-size:9px;letter-spacing:3px;color:var(--dim)}
.submitline{display:flex;gap:8px;align-items:center}
#initials{
  pointer-events:auto;width:104px;font:inherit;font-size:22px;font-weight:700;
  letter-spacing:8px;text-align:center;text-transform:uppercase;text-indent:8px;
  padding:9px 0;border-radius:3px;color:var(--paper);
  border:1px solid rgba(238,242,244,.32);background:rgba(11,17,22,.5);
  /* The page turns selection and touch gestures off so driving never
     selects the HUD or scrolls the frame. A text field is the one place
     that has to opt back in, or the caret never lands and typing drops
     most of what it is given. */
  -webkit-user-select:text;user-select:text;
  touch-action:manipulation;
}
#initials::placeholder{color:rgba(238,242,244,.22)}
#initials:focus{outline:none;border-color:var(--hot)}
.submitnote{font-size:10px;letter-spacing:1px;color:var(--dim);min-height:1.4em}
.submitnote.good{color:var(--hot)}
.submit.done .submitline{display:none}

/* --------------------------------------------------------- leaderboard */
.boardtitle{font-size:16px;font-weight:700;letter-spacing:4px}
.board{
  list-style:none;margin:0;padding:0;width:min(340px,86vw);
  max-height:52vh;overflow-y:auto;
  border-top:1px solid rgba(238,242,244,.14);
}
.board li{
  display:grid;grid-template-columns:26px 46px 1fr auto;gap:10px;align-items:baseline;
  padding:9px 4px;border-bottom:1px solid rgba(238,242,244,.10);
  font-size:12px;font-variant-numeric:tabular-nums;text-align:left;
}
.board li.loading,.board li.empty{display:block;text-align:center;color:var(--dim);padding:18px 0}
.board .rank{color:var(--dim);font-size:10px}
.board .who{font-weight:700;letter-spacing:2px}
.board .meta{color:var(--dim);font-size:10px;letter-spacing:1px}
.board .pts{font-weight:700}
.board li.me{background:rgba(255,106,43,.14)}
.board li.me .who{color:var(--hot)}

/* ------------------------------------------------------------ campaign */
.levelist{
  list-style:none;margin:0;padding:0;width:min(360px,88vw);
  max-height:56vh;overflow-y:auto;
  border-top:1px solid rgba(238,242,244,.14);
}
.levelist li{border-bottom:1px solid rgba(238,242,244,.10)}
.levelist button{
  width:100%;display:grid;grid-template-columns:1fr auto;gap:4px 10px;
  align-items:baseline;text-align:left;
  padding:11px 6px;background:transparent;border:0;color:var(--paper);
  font:inherit;cursor:pointer;touch-action:manipulation;
}
.levelist button:hover,.levelist button:focus-visible{background:rgba(238,242,244,.07);outline:none}
/* whichever stage is loaded right now, marked the way your own row is on a
   leaderboard — the stage tile names it, and this is where you find it */
.levelist li.lcur{background:rgba(255,106,43,.14)}
.levelist li.lcur .lname{color:var(--hot)}
.levelist .lname{font-size:13px;font-weight:700;letter-spacing:2px}
.levelist .ltime{font-size:12px;font-variant-numeric:tabular-nums;color:var(--dim)}
.levelist .lblurb{grid-column:1/-1;font-size:10px;letter-spacing:.5px;color:var(--dim)}
/* the campaign-wide tally under the title */
.lsummary{
  font-size:10px;letter-spacing:1.5px;color:var(--dim);
  margin:0 0 10px;text-align:center;
}
.lsummary .medal{margin:0 3px 0 0}

/* one header per world; the swatch carries the biome's colour. Sticky, so
   halfway down a section you can still see which world you are browsing. */
.levelist li.lsec{
  display:flex;justify-content:space-between;align-items:baseline;
  padding:14px 6px 5px;
  border-bottom:1px solid rgba(238,242,244,.20);
  position:sticky;top:0;
  background:rgba(24,30,36,.94);
}
.lsecname{font-size:10px;font-weight:700;letter-spacing:3px;color:var(--paper)}
.lsecname::before{
  content:'';display:inline-block;width:8px;height:8px;border-radius:2px;
  background:var(--bc,#888);margin-right:8px;
}
.lsecprog{font-size:9px;letter-spacing:1.5px;color:var(--dim)}
.levelist .lnum{
  font-style:normal;font-size:9px;color:var(--dim);
  margin-right:9px;font-variant-numeric:tabular-nums;
}
.levelist .medal,.lsummary .medal,.board .medal,.tile .medal{
  display:inline-block;width:9px;height:9px;border-radius:50%;margin-left:7px;
  border:1px solid rgba(238,242,244,.35);vertical-align:middle;
}
.levelist .medal.m3,.lsummary .medal.m3,.board .medal.m3,.tile .medal.m3{background:#e8c33a;border-color:#e8c33a;box-shadow:0 0 9px rgba(232,195,58,.6)}
.levelist .medal.m2,.lsummary .medal.m2,.board .medal.m2,.tile .medal.m2{background:#c8ccd2;border-color:#c8ccd2}
.levelist .medal.m1,.lsummary .medal.m1,.board .medal.m1,.tile .medal.m1{background:#b0763c;border-color:#b0763c}

/* ------------------------------------------------------------ settings */
.setlist{display:flex;flex-direction:column;gap:14px;width:min(340px,86vw)}
.setrow{
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:12px 4px;border-bottom:1px solid rgba(238,242,244,.12);
}
/* display:flex above outranks the browser's own [hidden] rule, so a row
   parked with the attribute (voice, the wide frame off desktop) needs this */
.setrow[hidden]{display:none}
.setrow span{font-size:12px;font-weight:700;letter-spacing:2px;text-align:left}
.setrow i{display:block;font-style:normal;font-size:10px;letter-spacing:.5px;
  color:var(--dim);margin-top:4px;font-weight:400}
.setflip{
  pointer-events:auto;cursor:pointer;min-width:72px;
  padding:9px 0;border-radius:3px;font:inherit;font-size:11px;font-weight:700;
  letter-spacing:2px;touch-action:manipulation;
  background:var(--paper);color:var(--ink);border:1px solid var(--paper);
}
.setflip[aria-pressed="false"]{
  background:transparent;color:var(--dim);border-color:rgba(238,242,244,.3);
}
.setflip:disabled{opacity:.35;cursor:default}
.setslide{
  display:flex;flex-direction:column;gap:8px;text-align:left;
  padding:4px 4px 10px;border-bottom:1px solid rgba(238,242,244,.08);
}
.setslide label{font-size:10px;letter-spacing:1.5px;color:var(--dim);
  display:flex;justify-content:space-between}
.setslide output{color:var(--paper);font-variant-numeric:tabular-nums}
.setslide input[type=range]{
  pointer-events:auto;width:100%;accent-color:var(--hot);
  touch-action:manipulation;
}

/* ---------------------------------------------------------- front card */
/* The pit board: a full-width stage tile over a car/light pair, one bar to
   press underneath. The card stretches rather than centres — the tiles want
   the width, and DROP IN wants the bottom. */
#start{align-items:stretch;justify-content:flex-start}
.menu{
  flex:1;display:flex;flex-direction:column;gap:12px;
  width:100%;max-width:420px;margin:0 auto;text-align:left;
}
.menubar{display:flex;align-items:center;justify-content:space-between;gap:12px}
.wordmark{font-size:11px;font-weight:700;letter-spacing:3px;white-space:nowrap}
.navs{display:flex;gap:8px}
.nav{
  pointer-events:auto;cursor:pointer;font:inherit;touch-action:manipulation;
  background:var(--glass);border:1px solid rgba(238,242,244,.24);color:var(--dim);
  font-size:9px;font-weight:700;letter-spacing:2px;padding:8px 11px;border-radius:3px;
  transition:color .12s,border-color .12s;
}
.nav:hover{color:var(--paper);border-color:rgba(238,242,244,.45)}
.nav:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
/* The desktop panel is far wider than a phone, and a 9px chip beside a tile
   carrying a 26px value reads as fine print rather than as a control. Sized up
   for the pointer only: on a phone these are already a comfortable thumb
   target and growing them would crowd the wordmark off the row.

   This block sits AFTER the base .nav on purpose — a media query adds no
   specificity, so the same selector declared later in the file is what
   decides, and the desktop rule up beside #app lost to the phone rule below
   it every time. */
@media (min-width:760px){
  .nav{font-size:11px;letter-spacing:2.6px;padding:12px 18px}
  .menubar{gap:16px}
}

.tiles{display:flex;flex-direction:column;gap:11px}
/* The column layout is load-bearing, not decoration: a <button> centres its
   own content vertically, so the CAR tile's taller stack pushed its label
   down and the pair's two headings no longer sat on one line. */
.tile{
  position:relative;width:100%;text-align:left;color:var(--paper);
  display:flex;flex-direction:column;align-items:stretch;justify-content:flex-start;
  pointer-events:auto;cursor:pointer;font:inherit;touch-action:manipulation;
  background:rgba(11,17,22,.52);border:1px solid rgba(238,242,244,.20);
  border-radius:8px;padding:15px 16px;
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
  transition:background .12s,border-color .12s;
}
.tile:hover{background:rgba(11,17,22,.66);border-color:rgba(238,242,244,.42)}
.tile:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
.tile .k{
  display:flex;align-items:center;justify-content:space-between;
  font-size:9px;font-weight:700;letter-spacing:2.6px;color:var(--dim);
}
.tile .k em{font-style:normal;font-size:12px;color:rgba(238,242,244,.42)}
/* display:block is load-bearing on both: they are spans inside a <button>,
   and an inline box takes neither the margin that stacks them nor a height. */
.tile .v{
  display:block;font-size:26px;font-weight:700;letter-spacing:-.3px;
  line-height:1.08;margin-top:9px;
}
.tile .meta{
  display:block;font-size:10px;letter-spacing:1.4px;color:var(--dim);
  margin-top:8px;font-variant-numeric:tabular-nums;
}
.pair{display:grid;grid-template-columns:1fr 1fr;gap:11px}
.pair .v{font-size:21px}
/* the car's own livery colour, down the edge of its tile */
.stripe{
  position:absolute;left:0;top:14px;bottom:14px;width:3px;
  border-radius:0 2px 2px 0;background:var(--paint,var(--hot));
}
.carbars{display:flex;flex-direction:column;gap:5px;margin-top:10px}
.carbars div{display:flex;align-items:center;gap:7px;
  font-size:8px;letter-spacing:1.6px;color:var(--dim)}
.bars{display:flex;gap:3px}
.bars i{width:11px;height:4px;border-radius:1px;background:rgba(238,242,244,.20)}
.bars i.f{background:var(--hot)}
.sky{
  display:block;height:26px;border-radius:3px;margin-top:10px;
  border:1px solid rgba(238,242,244,.16);
}

/* The slack between the tiles and the action. The car stands in it: the
   tiles stay up under the wordmark, the caption sits on the action, and the
   turntable takes every pixel left over between them. */
.menu .fill{
  flex:1;min-height:0;display:flex;flex-direction:column;
  align-items:center;justify-content:flex-end;gap:14px;padding:6px 0 12px;
}
/* The canvas is taken OUT of layout and stretched over a box that is sized
   purely by the flex slack, because a canvas is not a normal element: the
   width/height ATTRIBUTES the renderer writes give it an intrinsic aspect
   ratio, and against `width:100%` that computes a height the flex box then
   honours — which is how a car preview pushes DROP IN off the bottom of a
   laptop in landscape. Positioned absolutely it cannot report a size to
   anyone, so the box alone decides, down to nothing on a short screen.
   No pointer events: the tile is what changes the car. */
.carbox{
  flex:1;min-height:0;width:100%;max-width:420px;
  position:relative;pointer-events:none;
  /* OPAQUE, and it has to be. The canvas is transparent, so with the card's
     own scrim behind it the car was standing in the middle of whatever
     hillside the menu happened to be parked on — two 3D scenes at different
     scales fighting over the same pixels. A solid bay reads as a place the
     car is being shown, not a place it is. The gradient is a floor: darker
     at the bottom, so the car has something to sit on without a shadow pass
     drawing one. */
  background:
    radial-gradient(120% 80% at 50% 22%, rgba(63,84,102,.42), transparent 70%),
    linear-gradient(#151d25, #0a0e13);
  border:1px solid rgba(238,242,244,.14);
  border-radius:10px;
  overflow:hidden;
}
.carbox canvas{position:absolute;inset:0;width:100%;height:100%;display:block}
.rules{
  font-size:10px;line-height:1.7;letter-spacing:.5px;color:var(--dim);text-align:center;
}
.acts{display:flex;flex-direction:column;gap:10px}
.acts .go,.acts .ghost{width:100%;padding:16px 0}

/* ---------------------------------------------------------- pause card */
/* Barely any scrim: the run is still there behind this, and seeing it is
   the point. The console owns the bottom third and nothing else. */
.pausecard{
  background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;
  justify-content:flex-end;align-items:stretch;padding:0;
}
/* The gradient runs the full width of the frame — capped at 420px it drew
   its own left and right edges across the mountain — while the controls
   inside it stay at the same measure as the front card's tiles. */
.console{
  width:100%;
  padding:64px calc(20px + env(safe-area-inset-left))
          calc(22px + env(safe-area-inset-bottom)) calc(20px + env(safe-area-inset-right));
  background:linear-gradient(180deg,
    rgba(11,17,22,0), rgba(11,17,22,.80) 34%, rgba(11,17,22,.94));
}
.console > *{max-width:420px;margin-left:auto;margin-right:auto}
.pline{
  font-size:10px;letter-spacing:1.6px;color:var(--dim);text-align:center;
  margin-bottom:12px;font-variant-numeric:tabular-nums;
}
/* Chips, not text links. On the front card the quiet row is a shortcut you
   can ignore; here it is the ONLY way back to the stage, the board and the
   settings — drawn at 9px in --dim over a lit mountain it read as decoration
   and the pause menu looked like it offered nothing but RESUME and RESTART. */
.pfoot{display:flex;justify-content:center;gap:8px;margin-top:14px}
.pfoot button{
  pointer-events:auto;cursor:pointer;font:inherit;touch-action:manipulation;
  flex:1;max-width:132px;padding:11px 6px;border-radius:3px;
  background:var(--glass);border:1px solid rgba(238,242,244,.32);color:var(--paper);
  font-size:10px;font-weight:700;letter-spacing:2px;
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
  transition:background .12s,border-color .12s;
}
.pfoot button:hover{background:rgba(11,17,22,.6);border-color:rgba(238,242,244,.55)}
.pfoot button:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
/* the in-game MENU and REC chips sit under the pause console's thin scrim,
   where they read as live controls they are not */
body.paused #bMenu,body.paused #bRec{display:none}

/* ------------------------------------------------------------ segments */
.seg{display:flex;border:1px solid rgba(238,242,244,.25);border-radius:3px;overflow:hidden}
.seg button{
  pointer-events:auto;cursor:pointer;background:transparent;border:0;
  color:var(--dim);font:inherit;font-size:11px;font-weight:700;letter-spacing:2px;
  padding:11px 18px;touch-action:manipulation;
  transition:background .12s,color .12s;
}
.seg button[aria-pressed="true"]{background:var(--paper);color:var(--ink)}
.seg button:focus-visible{outline:2px solid var(--hot);outline-offset:-2px}

/* keys are for keyboards */
@media (pointer:coarse){ #kbdhint{display:none} }

.hidden{display:none}

/* ------------------------------------------------------- timing panel */
/* Diagnostic, off unless ?timing=1. Deliberately plain DOM and OUTSIDE the
   canvas, so switching it on never changes what a clip records. */
#timing{
  position:absolute;z-index:30;pointer-events:none;
  left:calc(8px + env(safe-area-inset-left));
  bottom:calc(8px + env(safe-area-inset-bottom));
  padding:9px 11px;border-radius:4px;white-space:pre;
  background:rgba(0,0,0,.78);border:1px solid rgba(120,255,140,.35);
  color:#7dff9b;font:700 11px/1.6 var(--font);letter-spacing:1px;
  font-variant-numeric:tabular-nums;
}
#timing b{color:#fff;font-weight:700}
#timing i{font-style:normal;color:#ff6a2b}

/* --------------------------------------------------------- rotate nag */
#rotate{
  position:absolute;inset:0;z-index:20;display:none;
  align-items:center;justify-content:center;background:#0b1116;
  font-size:12px;letter-spacing:3px;color:var(--dim);text-align:center;
}
/* Only nag on a short landscape viewport — a laptop is landscape too, and it
   gets the portrait panel instead. */
@media (orientation:landscape) and (max-height:520px){
  #rotate{display:flex}
}

@media (prefers-reduced-motion:reduce){
  #speedbar,.steer{transition:none}
}

/* Steering readout. Tabular figures so the digits do not jitter as they
   change, and the two peaks side by side because the whole question is
   whether one of them stops short of the other. */
#steerNum{
  margin-top:7px;font-size:10px;line-height:1.5;letter-spacing:1px;
  color:var(--dim);font-variant-numeric:tabular-nums;white-space:nowrap;
}
#steerNum b{color:var(--paper);font-weight:700}
#steerNum .pk{color:var(--hot)}
#steerNum.hide{display:none}
