:root {
  --pink: #1ff0c8;
  --cyan: #4f8cff;
  --purple: #7a2bff;

  /* slanted-button chrome — one source of truth for every primary CTA
     (.btn, .auth-main-btn, .auth-submit-btn) and every
     secondary button (.btn.alt, .bet-opt, .auth-secondary-btn). */
  --btn-slant: polygon(12px 0, 100% 0, calc(100% - 12px) 100%, 0 100%);
  /* the same silhouette as a 1.5px ring — an evenodd polygon with the inner
     parallelogram punched out. The outline CANNOT be an `inset` box-shadow:
     that is painted on the un-clipped rectangle, so --btn-slant keeps only
     its top and bottom edges and the two slanted ends come out open. */
  --btn-slant-ring: polygon(
    evenodd,
    12px 0,
    100% 0,
    calc(100% - 12px) 100%,
    0 100%,
    13.9px 1.5px,
    calc(100% - 1.5px) 1.5px,
    calc(100% - 13.9px) calc(100% - 1.5px),
    1.5px calc(100% - 1.5px)
  );
  /* the violet end stop is held at #7d55ff, not the old #6a3bff: --btn-ink
     on the darkest visible point of the gradient measured 3.96:1, so the
     tail of a long label ("PLAY MULTIPLAYER") fell under the 4.5 floor.
     #7d55ff puts that same point at 4.77:1 and keeps the hue. */
  --btn-fill: linear-gradient(100deg, #8ff8ff 0%, #4f8cff 52%, #7d55ff 115%);
  --btn-ink: #04040e;
  /* disabled CTAs: a flat muted plate with its own ink, never `opacity` on
     the button box -- fading the box fades plate and label together, which
     collapses the contrast between them instead of just dimming it. */
  --btn-off-fill: #2a2f4a;
  --btn-off-ink: #aab3d0;
  --btn-alt-fill: rgba(16, 18, 40, 0.55);
  --btn-alt-line: rgba(150, 170, 255, 0.35);
  --btn-alt-line-hi: rgba(150, 170, 255, 0.8);
  --btn-alt-fill-hi: rgba(26, 30, 60, 0.7);
  --btn-alt-ink: #e9edff;
  /* CREATE POT's plate. Same slant, same sheen, same dark ink as every
     other primary CTA — only the hue changes, so a private pot reads as a
     different ACTION rather than a different design. The violet end stop is
     shared with --btn-fill for exactly the contrast reason noted above. */
  --btn-sheen: linear-gradient(
    100deg,
    transparent 35%,
    rgba(255, 255, 255, 0.55) 50%,
    transparent 65%
  );
}
:root {
  /* the first-screen shot (#login, #loading): firstScreen.jpg is a night
     road, so the colour under it while it loads and the veil over it are
     both dark — top-heavy so the white wordmark sits on the darkest band,
     a touch at the foot to anchor the footer strip. */
  --first-screen-fallback: #0b1226;
  --first-screen-scrim: linear-gradient(
    180deg,
    rgba(4, 8, 24, 0.55) 0%,
    rgba(4, 8, 24, 0.22) 38%,
    rgba(4, 8, 24, 0) 60%,
    rgba(4, 8, 24, 0.3) 100%
  );

  /* one source of truth for the screen inset AND the hero offset: #login
     (a .screen) and #loading (not one) must land their logo identically,
     so both vars live here where both can inherit them. */
  --screen-pad-t: calc(24px + env(safe-area-inset-top));
  --screen-pad-r: max(16px, env(safe-area-inset-right));
  --screen-pad-b: calc(24px + env(safe-area-inset-bottom));
  --screen-pad-l: max(16px, env(safe-area-inset-left));
  /* The login/loading hero is TOP-anchored, not centred — see the note on
     #login-main: centring re-centres the logo every time the card resizes,
     and the auth card swings from 258px (default) to 503px (sign-up, with
     the info block), so there is no height to reserve either.

     This solves it arithmetically instead. `50vh - 264px` is the offset
     that puts the DEFAULT state's group (wordmark + gap + card ≈ 442px,
     inside a column that loses ~61px to the footer and its gap) on the
     optical centre — derived from the viewport alone, never from the card,
     so a taller state grows DOWNWARD and the wordmark still cannot move.
     A flat vh factor could not do this: it overshot on a short, wide
     desktop window and undershot on a tall tablet. */
  --hero-top: clamp(28px, calc(50vh - 264px), 340px);

  /* CENTRED HUD STACK — #milestone, #race-timer and #combo are all
     absolutely centred and can be on screen at the same moment (hit nitro
     mid-combo during a timed race and all three fire). One row each, from
     one source of truth, so they can never print on top of each other. */
  --hud-row-1: calc(96px + env(safe-area-inset-top)); /* #milestone */
  --hud-row-2: calc(134px + env(safe-area-inset-top)); /* #race-timer */
  --hud-row-3: calc(172px + env(safe-area-inset-top)); /* #combo     */

  /* dark outline under every HUD string -- see .corner */
  --hud-halo: 0 0 8px #000, 0 0 4px #000, 0 1px 2px rgba(0, 0, 0, 0.9);
  /* softer version for menu sub-text. .screen's scrim is deliberately thin
     so the live scene reads through it, which means the muted greys below
     have no guaranteed ground -- on the daylight maps they measured ~1.3:1.
     This edges them without darkening the backdrop. */
  --menu-halo: 0 1px 3px rgba(0, 0, 0, 0.9), 0 0 10px rgba(0, 0, 0, 0.55);
}

/* =========================================================
   DESIGN TOKENS
   One source of truth for type, tracking, spacing, radius and
   control height. A rule that needs a size reaches for a token
   here; it does not invent an 11.5px. Roles are semantic — pick
   the one that matches what the text IS, not the pixel count you
   happen to want.
   ========================================================= */
:root {
  /* ---- type scale, by role ---- */
  --fs-hero: clamp(46px, 7.4vw, 84px); /* brand wordmark (menu)     */
  --fs-page: clamp(24px, 5vw, 40px); /* screen title — every page heading shares this */
  --fs-section: clamp(16px, 3vw, 22px); /* block heading             */
  --fs-btn: 14px; /* primary CTA label         */
  --fs-btn-sm: 12px; /* utility / secondary label */
  --fs-body: 13px; /* running copy              */
  --fs-label: clamp(10px, 1.15vw, 11px); /* micro caps label      */
  --fs-meta: clamp(10px, 0.9vw, 11px); /* footer, build stamp */

  /* credit-strip width, named once. The login/loading footers are
     shrink-to-fit, so without a floor the hairline is as wide as
     whichever label that screen happens to carry and the two strips
     don't match. */
  --footer-strip-w: 430px;

  /* ---- letter-spacing, by role. em so tracking tracks size. ---- */
  --ls-display: 0.05em;
  --ls-title: 0.08em;
  --ls-btn: 0.08em;
  --ls-btn-sm: 0.06em;
  --ls-body: 0.02em;
  --ls-label: 0.12em;
  --ls-meta: 0.14em;

  /* ---- spacing ---- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-7: 32px;
  --sp-8: 40px;

  /* ---- radius ---- */
  --r-sm: 8px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-pill: 999px;

  /* ---- control heights. --h-md is the touch-target floor for any
     control a player is expected to hit on a tablet or phone. ---- */
  --h-sm: 36px;
  --h-md: 44px;
  --h-lg: 52px;

  /* ---- the top-right corner. ONE source of truth for #top-right-chips
     and for anything that hangs off it (#wallet-menu): the dropdown's
     top used to be a hardcoded 48px copy that didn't move when the row
     did, so the panel opened 10-16px INSIDE the chip. ---- */
  --chips-top: calc(14px + env(safe-area-inset-top));
  --chips-right: calc(16px + env(safe-area-inset-right));
  --chips-h: var(--h-md);
}

@media (max-width: 640px) {
  :root {
    /* clearance for #top-right-chips, derived from the chip tokens (set
       further down for this breakpoint) rather than a copied number: the
       row ends at --chips-top + --chips-h = 60px, and the old flat 52px
       put the first line of any screen tall enough to top-anchor (the
       title with a greeting, CASH BATCH, CREATE ROOM) under the wallet
       pill on a 320px-wide iPhone SE. */
    --screen-pad-t: calc(var(--chips-top) + var(--chips-h) + 6px);
    --hero-top: 70px;
  }

  /* the login / loading screens have nothing in the top-right corner, so
     the 52px chip reservation is dead space there, and a flat 70px hero
     offset on top of it pushed the card (and ENTER GARAGE) below the fold
     on a 454px iPhone SE. Keep a plain inset and let the offset follow the
     viewport height instead. Both screens share the values so the logo
     lands in the same place on each. */
  #login,
  #loading {
    --screen-pad-t: calc(16px + env(safe-area-inset-top));
    --hero-top: clamp(12px, 6vh, 70px);
  }
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
  /* svh is the SMALL viewport — the box with the mobile browser's toolbar
     showing. Every .screen is `position: absolute; inset: 0`, so with the
     large viewport (toolbar assumed hidden) each screen's last row sat
     under the browser chrome: on the garage that was the car strip, and
     the bottom few pixels of every card — its MPH line — were cut off.
     It is deliberately NOT dvh: dvh tracks the toolbar live, and Chrome
     for Android collapses its toolbar when you scroll a tall screen
     (SETTINGS). The menu underneath then re-centred into a viewport 56px
     taller and stayed there — body can't scroll, so the toolbar never
     comes back — which read as dead space appearing after BACK. svh is
     the same box in both toolbar states, so nothing moves.
     `height: 100%` stays first as the fallback for anything without svh.
     Keep this literal, not a custom property: an unsupported unit inside
     var() is invalid at computed-value time and kills the fallback. */
  height: 100svh;
  overflow: hidden;
  overscroll-behavior: none;
  background: #05010f;
}

body {
  /* the containing block for every `position: absolute` screen, so they
     inherit the svh box above instead of the initial containing block */
  position: relative;
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
  color: #fff;
  -webkit-user-select: none;
  user-select: none;
  touch-action: none;
  /* nothing in this UI is allowed to push the page sideways */
  overflow-x: hidden;
}

#app {
  position: fixed;
  inset: 0;
}

canvas {
  display: block;
}

/* ---------- HUD ---------- */
body.menu #hud {
  display: none;
}

#hud {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 10;
}

/* HUD ink sits straight on the canvas, and the realistic maps (day, cloudy,
   hills -- see world.js) put a near-white sky behind it, where the accent
   colours measured 1.1-1.9:1. The glow below is currentColor, so it spreads
   the fill rather than edging it; --hud-halo is the dark outline that gives
   every HUD string a surface on a bright sky. One source of truth: .corner,
   #combo, #milestone and #race-timer all pull from it. */
.corner {
  position: absolute;
  top: calc(22px + env(safe-area-inset-top));
  padding: 0 24px;
  text-shadow: var(--hud-halo), 0 0 12px currentColor;
}

#score-wrap {
  left: 0;
  padding-left: calc(24px + env(safe-area-inset-left));
  color: var(--cyan);
}

#speed-wrap {
  right: 0;
  padding-right: calc(24px + env(safe-area-inset-right));
  text-align: right;
  color: var(--pink);
}

.label {
  font-size: 12px;
  letter-spacing: 4px;
  opacity: 0.85;
  font-weight: 600;
}

/* the nitro key hint: was an inline 9px, which with .label's tracking and
   fade was the smallest HUD string in the game */
.nitro-label {
  font-size: 11px;
  letter-spacing: 2px;
  /* clears the bar below it — at 11px the descenders were landing on the
     track, so the two read as one smudged block */
  margin-bottom: 6px;
}

.value {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: 38px;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

#score-wrap .value::after {
  content: " m";
  font-size: 18px;
  opacity: 0.6;
}

#best-wrap {
  left: 0;
  padding-left: calc(24px + env(safe-area-inset-left));
  top: calc(110px + env(safe-area-inset-top));
  color: #c9a4ff;
}

#best-wrap .label {
  opacity: 0.85;
}

#best-wrap .value {
  text-shadow:
    0 0 10px var(--purple),
    0 1px 3px rgba(0, 0, 0, 0.9);
}

/* the corner as TARGET during a challenge attempt (hud.setTarget): the
   prize colour, so the number a player is chasing reads as the stake */
#best-wrap.target {
  color: #14f195;
}

#best-wrap.target .value {
  text-shadow:
    0 0 10px rgba(20, 241, 149, 0.7),
    0 1px 3px rgba(0, 0, 0, 0.9);
}

#best-wrap .value::after {
  content: " m";
  font-size: 18px;
  opacity: 0.6;
}

#nitro-wrap {
  margin-top: 8px;
}

#nitro-bar {
  width: 130px;
  height: 7px;
  margin-left: auto;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.14);
  overflow: hidden;
}

#nitro-bar i {
  display: block;
  height: 100%;
  width: 0%;
  border-radius: 5px;
  background: linear-gradient(90deg, #13f1ff, #7a2bff);
  transition: width 0.15s;
}

#nitro-bar.burn i {
  background: linear-gradient(90deg, #ffe600, #ff2e88);
}

/* points at the TOP, fixed in place — only fades, never moves.
   Sits one line BELOW #milestone so a combo and a milestone flash
   (e.g. "⚡ NITRO") that overlap in time never stack on each other. */
#combo {
  position: absolute;
  top: var(--hud-row-3);
  left: 50%;
  transform: translateX(-50%);
  font-size: clamp(15px, 3.2vw, 22px);
  font-weight: 800;
  color: #fff;
  opacity: 0;
  text-shadow: var(--hud-halo), 0 0 14px var(--pink);
  transition: opacity 0.2s;
  letter-spacing: 2px;
  white-space: nowrap;
}

#milestone {
  position: absolute;
  top: var(--hud-row-1);
  left: 50%;
  transform: translateX(-50%);
  /* longest string is "MANUAL — ↑ GAS · ↓ BRAKE"; scale it down rather
     than let it run off the sides of a phone */
  font-size: clamp(15px, 4.2vw, 30px);
  max-width: 92vw;
  font-weight: 900;
  color: #fff;
  opacity: 0;
  letter-spacing: 3px;
  text-shadow: var(--hud-halo), 0 0 22px var(--cyan);
  transition: opacity 0.25s;
  white-space: nowrap;
}

/* Phones and short landscape: the top-centre band is only ~a finger wide
   between #best-wrap (left) and #leaderboard (right), so the two flash
   texts move to their own band at the bottom — clear of both columns and
   of the horn/nitro row. #race-timer stays up top; it is never wide. */
@media (max-width: 640px), (orientation: landscape) and (max-height: 560px) {
  #milestone {
    top: auto;
    bottom: calc(126px + env(safe-area-inset-bottom));
  }

  #combo {
    top: auto;
    bottom: calc(92px + env(safe-area-inset-bottom));
  }
}

/* ---------- live leaderboard (multiplayer) ---------- */
#leaderboard {
  position: absolute;
  top: calc(120px + env(safe-area-inset-top));
  right: calc(18px + env(safe-area-inset-right));
  width: 210px;
  pointer-events: none;
  display: none;
  flex-direction: column;
  gap: 5px;
  z-index: 11;
}

#leaderboard.show {
  display: flex;
}

.lb-title {
  font-size: 11px;
  letter-spacing: 3px;
  color: var(--cyan);
  /* no plate behind this one (the rows below have .lb-row's fill), so it
     carries the HUD halo and full opacity instead of fading to 0.7 */
  text-shadow: var(--hud-halo);
  margin-bottom: 2px;
}

.lb-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 9px;
  border-radius: var(--r-sm);
  background: rgba(20, 4, 40, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 13px;
}

.lb-row.me {
  border-color: var(--pink);
  box-shadow: 0 0 14px rgba(31, 240, 200, 0.35);
}

.lb-row.dead {
  /* muted ink rather than `opacity` on the row: .lb-gap inside carries its
     own 0.65, and the two multiplied to 26% -- about 2.1:1 */
  color: #8e87a4;
  border-color: rgba(255, 255, 255, 0.05);
}

.lb-row.dead .lb-dist {
  color: #8e87a4;
}

.lb-rank {
  width: 16px;
  opacity: 0.6;
  font-weight: 700;
}

.lb-name {
  flex: 1;
  font-weight: 700;
  letter-spacing: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.lb-dist {
  font-variant-numeric: tabular-nums;
  color: var(--cyan);
  font-weight: 700;
}

.lb-gap {
  font-size: 11px;
  color: #c3bcd6;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* mid-race presence: only rendered for a non-'playing' racer (left/
   disconnected) — see hud.js renderLeaderboard(). */
.lb-status {
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
}

.lb-status.disconnected {
  color: #ffb84d;
}

.lb-status.left {
  color: #9a8fb5;
}

/* ---------- theme bar (top center) ---------- */
#theme-bar {
  position: fixed;
  top: calc(16px + env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  z-index: 30;
  display: flex;
  gap: 10px;
  align-items: center;
  padding: 7px 12px;
  border-radius: 30px;
  background: rgba(12, 2, 28, 0.55);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

#theme-bar .tlabel {
  font-size: 10px;
  letter-spacing: 3px;
  opacity: 0.5;
  margin-right: 2px;
}

.sw {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  cursor: pointer;
  pointer-events: auto;
  border: 2px solid transparent;
  transition:
    transform 0.12s,
    border-color 0.15s;
}

.sw:hover {
  transform: scale(1.18);
}

.sw.active {
  border-color: #fff;
  box-shadow: 0 0 12px currentColor;
}

/* ---------- screens ---------- */
.screen {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: safe center;
  gap: 20px;
  text-align: center;
  pointer-events: auto;
  overflow-y: auto;
  touch-action: pan-y;
  overscroll-behavior: contain;
  /* the screen inset lives at :root: #loading is not a .screen but carries
     the same credit footer, and that footer bleeds edge-to-edge by
     cancelling exactly these values, so a breakpoint that retunes the
     padding must not leave the footer's margins behind. */
  padding: var(--screen-pad-t) var(--screen-pad-r) var(--screen-pad-b)
    var(--screen-pad-l);
  scrollbar-width: none;
  background:
    repeating-linear-gradient(
      115deg,
      rgba(255, 255, 255, 0.014) 0 2px,
      transparent 2px 9px
    ),
    radial-gradient(
      130% 110% at 50% 0%,
      rgba(10, 6, 30, 0.38) 0%,
      rgba(3, 2, 12, 0.78) 82%
    );
  transition: opacity 0.5s ease;
  z-index: 20;
}

/* keep buttons from compressing when a screen's content overflows
   (e.g. the title screen with the settings panel open) */
.screen > * {
  flex-shrink: 0;
}

.screen::-webkit-scrollbar {
  display: none;
}

/* =========================================================
   FOOTER — .app-footer (+ --light / --transparent)
   Not every screen has a footer, and the two that do sit on very
   different grounds (a daylight photo, a night menu). What they must
   NOT do is change typography between screens: the credit strip used
   to be 13px/1.4px tracking on login and 11px/3px on the menu, which
   read as two different products. Type, spacing and safe-area handling
   are shared here; the ground each one sits on is the variant's job.
   --hidden is the third state, for screens (garage) that deliberately
   have none — it is a real state, not an oversight.
   ========================================================= */
.app-footer {
  font-family: "Inter", sans-serif;
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: var(--ls-meta);
  line-height: 1.3;

  /* Safe area, named once. It is NOT applied blanket here: the two
     footers have different positioning models, and blanket padding
     would double-count for the absolutely-positioned one (.bet-foot
     already rides on --screen-pad-b, which contains the inset). Each
     variant composes this into whichever edge it actually owns. */
  --footer-safe-b: env(safe-area-inset-bottom);
}

/* over a bright photo: white ink on its own upward-fading shade */
.app-footer--light {
  color: #ffffff;
}

/* over the night menus: muted ink straight on the scrim, no plate */
.app-footer--transparent {
  color: #8c95b8;
  text-shadow: var(--menu-halo);
}

.app-footer--hidden {
  display: none;
}

.screen.hidden {
  opacity: 0;
  /* Hidden screens used to keep opacity:0 only, so all ~15 of them stayed
     full-viewport painted layers — gradients, backdrop-filter cards and
     running keyframes — stacked over the live WebGL canvas forever. That is
     the rasterisation load that made the login -> title crossfade blow the
     frame budget. visibility takes them out of painting entirely; the 0.5s
     delay means it only flips once the fade-out has finished, so the fade
     itself is unchanged, and layout still resolves (unlike display:none) so
     anything measuring a hidden screen keeps working. */
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity 0.5s ease,
    visibility 0s linear 0.5s;
}

.screen.hidden,
.screen.hidden * {
  pointer-events: none !important;
}

/* NOTE: the old bare `.title` wordmark rule lived here. Nothing in the
   app rendered it any more — the two lockups are .rfs-brand (below) —
   but it was still matching `<div class="title">` inside the challenge
   UI (challengeUI.js), stamping a 112px Orbitron gradient and an orange
   ::after bar onto rows that challenge.css only ever restyled the font
   of. Removed; .chal-step .title / .chal-row .title now stand alone. */

/* =========================================================
   MICRO LABEL — .ui-label
   The small all-caps caption that names the control under it:
   DRIVER NAME, 4-DIGIT PIN, PRACTICE MODE, CARS & CUSTOMIZE,
   TOP SPEED, ACCEL, PAINT. Same role on every screen, so one size
   and one tracking. Colour/opacity stay with each screen, because
   the ground under them is what actually differs.

   Anything that reads as a caption joins this selector group. It
   does NOT get its own 10px / 11px / 11.5px / 12px.

   (The in-race HUD's `.label` is deliberately NOT here: SCORE / SPEED
   are a live telemetry readout sized to be glanced at at speed, not
   UI chrome.)
   ========================================================= */
.ui-label,
.tile-sub,
.gstat .gk,
#garage-paints .gp-label,
#login #auth-form label {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: var(--ls-label);
  line-height: 1.25;
  text-transform: uppercase;
}

.name-in {
  pointer-events: auto;
  background: rgba(255, 255, 255, 0.06);
  border: 1.5px solid rgba(160, 180, 255, 0.3);
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 3px;
  text-align: center;
  padding: 12px 20px;
  border-radius: var(--r-md);
  width: 240px;
  text-transform: uppercase;
  backdrop-filter: blur(8px);
  outline: none;
  transition:
    border-color 0.2s,
    box-shadow 0.2s;
}

.name-in:focus {
  border-color: #7ef7ff;
  box-shadow: 0 0 0 3px rgba(126, 247, 255, 0.15);
}

.name-in::placeholder {
  color: #9a8fb5;
  letter-spacing: 2px;
}

.btn-row {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  justify-content: center;
}

/* primary+BACK pair that closes a screen (SOLO RACING, CREATE CHALLENGE):
   sits a little lower than the settings above it, side by side on wide
   screens and stacked full-width below the breakpoint. */
.screen-actions {
  margin-top: 18px;
  width: 100%;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.screen-actions > .btn {
  width: min(340px, 100%);
}

@media (min-width: 700px) {
  .screen-actions {
    flex-direction: row;
    justify-content: center;
    gap: 16px;
  }

  .screen-actions > .btn {
    width: auto;
  }
}

/* =========================================================
   BUTTON — .btn (+ .alt secondary, .btn--sm / .btn--lg sizes)
   The slanted parallelogram is the identity and stays. What is
   standardised is everything around it: one type role, one tracking,
   one height ladder, one transition. A screen that needs a different
   button reaches for a size modifier, not a fresh padding pair.

   --btn-h is the box's minimum height, so a one-word label and a
   five-word label come out the same height on the same row.
   ========================================================= */
.btn {
  pointer-events: auto;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* the touch-target floor: every CTA clears 44px on a tablet/phone */
  --btn-h: var(--h-md);
  min-height: var(--btn-h);
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: var(--fs-btn);
  font-weight: 800;
  letter-spacing: var(--ls-btn);
  padding: 0 var(--sp-8);
  color: #04040e;
  border: none;
  outline: none;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: none;
  /* NOTE: the slant lives on ::before, not on .btn itself.
     clip-path also clips hit-testing, so clipping the button box
     made its angled corners unclickable. Default focus outlines
     trace this unclipped box too, showing as a stray square around
     the slanted button — suppressed here and replaced below. */
  transition:
    filter 0.18s,
    transform 0.14s;
}

/* ---- interaction states, in one place ----
   These used to be spread over three separate rules ~600 lines apart:
   :focus-visible here, a `filter` :hover next to the sheen keyframes, and
   a `transform` :hover + :active down by #payout. Two of those shared the
   same selector, so the button's behaviour could only be read by finding
   all three. */
.btn:hover,
.btn:focus-visible {
  filter: brightness(1.12);
  transform: scale(1.06);
}

.btn:active {
  transform: scale(0.97);
}

.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  clip-path: var(--btn-slant);
  background: var(--btn-fill);
}

/* sheen: a second layer on the SAME clipped element, so it stays
   inside the slanted silhouette without clipping .btn itself */
.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  clip-path: var(--btn-slant);
  background-image: var(--btn-sheen);
  background-repeat: no-repeat;
  background-size: 220% 100%;
  animation: sheen 3.4s ease-in-out infinite;
}

@keyframes sheen {
  0%,
  55% {
    background-position: 130% 0;
  }

  78%,
  100% {
    background-position: -130% 0;
  }
}

/* the CHALLENGE banner: gold, but the ink needs a ground. Its inline style
   used to paint #ffe9b0 straight onto --btn-fill's cyan end (1.03:1) and set
   a border-color that .btn's `border: none` threw away. */
#chal-banner {
  color: #2a1c00;
}

#chal-banner::before {
  background: linear-gradient(100deg, #ffd166 0%, #ffb02e 60%, #ff9d2e 115%);
}

/* ---- size modifiers ---- */
.btn--sm {
  --btn-h: var(--h-sm);
  font-size: var(--fs-btn-sm);
  letter-spacing: var(--ls-btn-sm);
  padding: 0 var(--sp-5);
}

.btn--lg {
  --btn-h: var(--h-lg);
  font-size: calc(var(--fs-btn) + 4px);
  padding: 0 var(--sp-8);
}

.btn.alt {
  color: #e9edff;
  background: none;
  gap: var(--sp-2);
}

/* fill rides on the clipped layer, not on .btn */
.btn.alt::before {
  background: var(--btn-alt-fill);
  backdrop-filter: blur(10px);
}

/* the sheen layer becomes the outline: a ring in the SAME silhouette, so the
   line follows the two slanted ends instead of stopping at them */
.btn.alt::after {
  clip-path: var(--btn-slant-ring);
  background: var(--btn-alt-line);
  animation: none;
  transition: background 0.18s;
}

.btn.alt .ico {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.btn.alt:hover::before {
  background: var(--btn-alt-fill-hi);
}

.btn.alt:hover::after {
  background: var(--btn-alt-line-hi);
}

/* ---------- home menu tiles (secondary actions) ---------- */
/* icon-in-a-box + label + sublabel, divided by hairlines instead of
   the slanted .btn chrome (which is suppressed on .tile) */
.menu-tiles {
  gap: 0;
}

.btn.tile {
  flex-direction: column;
  gap: var(--sp-2);
  padding: 10px 34px;
}

.btn.tile::before,
.btn.tile::after {
  display: none;
}

.menu-tiles .tile + .tile::after {
  display: block;
  content: "";
  position: absolute;
  left: 0;
  top: 10px;
  bottom: 10px;
  width: 1px;
  clip-path: none;
  background: linear-gradient(
    180deg,
    transparent,
    rgba(150, 170, 255, 0.35),
    transparent
  );
  animation: none;
}

.tile-ico {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: var(--r-md);
  color: #8ff8ff;
  background: var(--btn-alt-fill);
  backdrop-filter: blur(10px);
  box-shadow: inset 0 0 0 1.5px var(--btn-alt-line);
  transition:
    background 0.18s,
    box-shadow 0.18s,
    transform 0.14s;
}

.btn.tile .ico {
  width: 22px;
  height: 22px;
}

.tile-label {
  font-size: 13px;
  letter-spacing: 2px;
  color: #e9edff;
}

/* size/tracking/weight come from the .ui-label group */
.tile-sub {
  font-style: normal;
  color: rgba(180, 195, 245, 0.92);
  text-shadow: var(--menu-halo);
}

.btn.tile:hover .tile-ico {
  background: rgba(26, 30, 60, 0.7);
  box-shadow: inset 0 0 0 1.5px rgba(150, 170, 255, 0.8);
  transform: translateY(-2px);
}

/* ---------- modal ---------- */
#modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(3, 2, 12, 0.72);
  backdrop-filter: blur(4px);
  pointer-events: auto;
  transition:
    opacity 0.18s ease,
    visibility 0s linear 0s;
}

/* NOTE: pointer-events:none on the overlay is NOT enough on its own.
   .btn / inputs inside it declare `pointer-events: auto`, which
   re-enables hit-testing on those descendants even while the dialog is
   invisible — so the faded-out CONFIRM/CANCEL pair kept sitting in the
   middle of the screen swallowing clicks on whatever real button was
   underneath. That's why buttons all over the app were only clickable
   on the parts that stuck out past the invisible dialog. Force the
   whole subtree inert, and drop it out of hit-testing/tab order once
   the fade finishes. */
#modal-overlay.hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity 0.18s ease,
    visibility 0s linear 0.18s;
}

#modal-overlay.hidden * {
  pointer-events: none !important;
}

.modal-box {
  width: min(340px, 88vw);
  /* never taller than the viewport: a deposit modal with an address and a
     paragraph of instructions overflowed a 320px-tall landscape phone with
     no way to reach CONFIRM. The box scrolls inside instead. */
  max-height: calc(100svh - 24px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 28px 26px;
  border-radius: var(--r-lg);
  text-align: center;
  background: rgba(16, 18, 40, 0.9);
  backdrop-filter: blur(14px);
  box-shadow:
    inset 0 0 0 1.5px rgba(150, 170, 255, 0.35),
    0 20px 60px rgba(0, 0, 0, 0.6);
}

/* phone, upright: the dialog is a bottom sheet — full width, pinned to the
   bottom edge above the home indicator, rounded on top only. It sits where
   the thumb is and the keyboard (amount input) pushes it up whole. */
@media (max-width: 640px) and (orientation: portrait) {
  #modal-overlay {
    align-items: flex-end;
  }

  .modal-box {
    width: 100%;
    max-height: calc(100svh - 48px - env(safe-area-inset-top));
    padding: 22px 20px calc(22px + env(safe-area-inset-bottom));
    border-radius: var(--r-lg) var(--r-lg) 0 0;
  }

  .modal-btn-row {
    flex-direction: column-reverse;
    gap: 10px;
  }

  .modal-btn-row .btn {
    width: 100%;
  }

  .modal-confirm .modal-box {
    width: 100%;
  }
}

.modal-title {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: 18px;
  font-weight: 800;
  letter-spacing: 1px;
  color: #e9edff;
  margin-bottom: 18px;
}

/* Explanatory line under the title, for modals that ask a question instead
   of taking a number (the "already signed in somewhere else" takeover). The
   title font is Orbitron italic 800 — unreadable for a full sentence — so
   prose lives here and the title stays a short label. */
.modal-body {
  margin: -6px 0 16px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.55;
  letter-spacing: 0.5px;
  color: rgba(233, 237, 255, 0.75);
  /* a 42-character address or a long URL has no break opportunity — let it
     wrap anywhere rather than widen the box past the screen */
  overflow-wrap: anywhere;
}

.modal-in {
  background: rgba(255, 255, 255, 0.06);
  border: 1.5px solid rgba(160, 180, 255, 0.3);
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 1px;
  text-align: center;
  padding: 12px 16px;
  border-radius: var(--r-md);
  width: 100%;
  outline: none;
  transition:
    border-color 0.2s,
    box-shadow 0.2s;
}

.modal-in:focus {
  border-color: #7ef7ff;
  box-shadow: 0 0 0 3px rgba(126, 247, 255, 0.15);
}

.modal-btn-row {
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-top: 20px;
}

/* Confirm dialogs only (promptModal's CONFIRM/CANCEL are left exactly as they
   were). Their buttons carry a real sentence of a label — "LOG OUT &
   CONTINUE" — and .btn is 14px Orbitron with 2px letter-spacing and 40px side
   padding, so that one label alone is ~310px against 288px of content width:
   it broke across three lines.

   The label never wraps; the ROW does. Tighter padding and letter-spacing get
   a long label onto one line inside the box, and the pair drops to two
   centred lines when it cannot share one. */
.modal-confirm .modal-box {
  width: min(430px, 92vw);
}

.modal-confirm .modal-btn-row {
  flex-wrap: wrap;
}

.modal-confirm .modal-btn-row .btn {
  white-space: nowrap;
  padding: 15px 24px;
  letter-spacing: 1px;
  flex: 1 1 auto;
}

.bet-line {
  font-size: 14px;
  letter-spacing: 2px;
  color: #14f195;
  text-shadow: 0 0 12px rgba(20, 241, 149, 0.5);
}

/* ---------- CASH BATCH (bet) screen ---------- */
/* one source of truth for the screen's content column. The 100% leg is the
   screen's own content box: on a phone the screen pads 12px a side (24px,
   more than 94vw leaves below 400px wide), so a 94vw rule centred in it
   spilled past both edges and the screen measured 322px wide at 320. */
#bet {
  --bet-col: min(660px, 94vw, 100%);
  gap: 0;
}

.bet-eyebrow {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  color: #6f7899;
}

.bet-title.mp-heading {
  font-size: var(--fs-page);
  letter-spacing: var(--ls-title);
  background: none;
  -webkit-text-fill-color: currentColor;
  color: #e9edff;
  margin-top: 10px;
}

.bet-title .bet-title-alt {
  background: linear-gradient(100deg, #8ff8ff 0%, #4f8cff 52%, #6a3bff 115%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.bet-rule {
  display: flex;
  align-items: center;
  gap: 18px;
  width: var(--bet-col);
  margin-top: 16px;
}

.bet-rule-line {
  flex: 1;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(150, 170, 255, 0.35) 60%
  );
}

.bet-rule-line:last-child {
  background: linear-gradient(
    270deg,
    transparent,
    rgba(150, 170, 255, 0.35) 60%
  );
}

.bet-rule-text {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  color: #8b93b5;
  white-space: nowrap;
}

.bet-rule-sm {
  margin-top: 26px;
}

.bet-rule-sm .bet-rule-text {
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-meta);
  color: #5d6684;
}

.bet-tiers {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  width: var(--bet-col);
  margin-top: 18px;
}

/* the coin row is empty (all three buttons display:none) until the bank
   enables COIN_MINT — collapse its margin so it leaves no gap when hidden */
.bet-tiers-coin {
  display: none;
}

.bet-tiers-coin:has(.tier-btn:not([style*="none"])) {
  display: grid;
}

.tier-btn {
  pointer-events: auto;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 11px 8px 10px;
  border-radius: var(--r-md);
  background: rgba(14, 17, 38, 0.55);
  border: 1px solid rgba(150, 170, 255, 0.18);
  backdrop-filter: blur(10px);
  transition:
    border-color 0.18s,
    background 0.18s,
    box-shadow 0.18s;
}

.tier-btn:hover {
  border-color: rgba(150, 170, 255, 0.45);
  background: rgba(24, 28, 58, 0.65);
}

.tier-amt {
  font-family: "Orbitron", sans-serif;
  font-weight: 800;
  font-size: clamp(13px, 1.4vw, 18px);
  letter-spacing: 1px;
  color: #dfe6ff;
}

.tier-sub {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  color: #9aa4c6;
  text-shadow: var(--menu-halo);
}

/* .tier-btn.on takes the shared blue selected look (see .cr-chips .dur-chip.active) */

.bet-status {
  font-size: 13px;
  letter-spacing: 1px;
  color: #8b93b5;
  margin-top: 24px;
  max-width: var(--bet-col);
}

/* an empty status line must not hold its flex slot + margin open between
   the panel and the action row */
.bet-status:empty {
  display: none;
}

.bet-status b {
  color: #e9edff;
  font-weight: 700;
}

/* Deposit lifecycle line. One rule set, three screens: #bet-status,
   #pb-status and #cp-status all carry .bet-status, and the markup comes
   from depositStatusHtml() in main.js — the dep-* tone class is the only
   thing that changes between states. */
.bet-status .dep-status {
  display: inline-flex;
  align-items: flex-start;
  gap: 10px;
  max-width: 100%;
  padding: 11px 15px;
  border: 1px solid rgba(120, 140, 200, 0.28);
  border-left: 3px solid #6f8cff;
  border-radius: var(--r-sm);
  background: rgba(18, 24, 46, 0.82);
  font-size: 14px;
  text-align: left;
  line-height: 1.5;
  letter-spacing: 0.4px;
}

.bet-status .dep-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  margin-top: 7px;
  border-radius: 50%;
  background: #6f8cff;
}

.bet-status .dep-head {
  color: #e9edff;
  font-weight: 700;
}

.bet-status .dep-sub {
  color: #a9b1d1;
}

/* Anything still in flight pulses; a finished state must not, or the player
   keeps waiting for a step that already happened. */
.dep-work .dep-dot,
.dep-wait .dep-dot {
  animation: dep-pulse 1.1s ease-in-out infinite;
}

.dep-wait {
  border-left-color: #f0b429;
}

.dep-wait .dep-dot {
  background: #f0b429;
}

.dep-ok {
  border-left-color: #39d98a;
}

.dep-ok .dep-dot {
  background: #39d98a;
}

.dep-warn {
  border-left-color: #f0b429;
}

.dep-warn .dep-dot {
  background: #f0b429;
}

.dep-bad {
  border-left-color: #ff6b6b;
}

.dep-bad .dep-dot {
  background: #ff6b6b;
}

@keyframes dep-pulse {
  0%,
  100% {
    opacity: 0.25;
    transform: scale(0.75);
  }
  50% {
    opacity: 1;
    transform: scale(1);
  }
}

/* Resuming a paid seat after a reload is a full page load, so #login paints
   before the automatic sign-in that follows can hide it. The player asked
   to connect a wallet, not to sign in again — so hold the card back for
   that gap rather than flashing it. Cleared again if the sign-in fails. */
#login.resuming {
  visibility: hidden;
}

/* ---------- YOUR POTS (open pots this wallet is in) ----------
   Sits above the two cards on CASH BATCH, because after signing back in it
   is the first thing a pot's creator is looking for. Same dark glass plate
   as the other cards on this screen. */
.my-pots {
  /* same 100% cap as --bet-col above: this block is start-aligned by its
     auto margins, so at 94vw it ran 5px past a 320px phone's right edge */
  width: min(560px, 94vw, 100%);
  margin: 4px auto 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: auto;
}

.my-pots-label {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 2px;
  color: #9a8fb5;
  text-align: left;
}

.my-pot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  padding: 10px 14px;
  text-align: left;
  border: 1px solid rgba(150, 170, 255, 0.25);
  border-radius: var(--r-md);
  background: rgba(12, 14, 32, 0.6);
}

.my-pot-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.my-pot-code {
  font-size: 15px;
  font-weight: 900;
  letter-spacing: 3px;
  color: #e9edff;
}

.my-pot-meta {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.6px;
  color: #9a8fb5;
}

/* the CREATED badge — this is YOUR pot, not one you were invited to */
.my-pot-badge {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 6px;
  border-radius: var(--r-pill);
  font-size: 10px;
  letter-spacing: 1.4px;
  color: #04040e;
  background: var(--pink);
}

.my-pot-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.my-pot-remove {
  opacity: 0.6;
}

.my-pot-remove:hover {
  opacity: 1;
}

@media (max-width: 640px) {
  .my-pot-actions {
    flex: 1 1 100%;
  }

  .my-pot-actions .invite-card-btn {
    flex: 1 1 0;
    justify-content: center;
  }
}

/* ---------- the three primary CASH BATCH actions ----------
   JOIN A RACE, HOST A RACE and PLAY & CREATE CHALLENGE are the MULTIPLAYER
   screen's own .mp-card picker, so they inherit its size and hover
   treatment rather than carrying a second card style. Only the width cap
   is local: three 220px cards plus gaps on one row. */
.bet-cards {
  margin-top: 22px;
  width: min(760px, 94vw);
}

.bet-cards .mp-card {
  width: 240px;
  flex: 1 1 220px;
  min-width: 0;
  padding: 16px 18px;
  text-align: center;
}

@media (max-width: 640px) {
  /* the list-tile layout of the MOBILE block applies here too — only the
     centring and the roomier padding of the upright card are undone */
  .bet-cards .mp-card {
    width: 100%;
    flex: 1 1 100%;
    text-align: left;
    padding: 10px 14px;
  }
}

/* JOIN CHALLENGE paste row: link box + GO. A fluid box (it used to carry
   an inline 220px width, wider than a 320px phone's content column) that
   shares the row with GO where it fits and stacks above it where not. */
.join-chal-row {
  width: min(620px, 100%);
  gap: 10px;
}

/* #bet runs with gap: 0, so the row would sit flush against the option
   buttons' slanted plates above it */
#bet .join-chal-row {
  margin-top: 14px;
}

.join-chal-in {
  flex: 1 1 200px;
  min-width: 0;
  width: auto;
  padding: 10px 12px;
  font-size: 13px;
  letter-spacing: 1px;
}

/* the placeholders are whole phrases; .name-in's 2px tracking clipped
   their last letter inside the box */
.join-chal-in::placeholder {
  letter-spacing: 1px;
}

.join-chal-go {
  flex: 0 0 auto;
}

@media (max-width: 640px) {
  .join-chal-row {
    flex-direction: column;
    align-items: stretch;
  }

  /* flex-basis is HEIGHT in a column — the 200px basis above is not.
     Scoped under the row: the phone block further down sets
     `.name-in { width: 200px }` at the same specificity and later in the
     file, which left the box narrower than its GO button. */
  .join-chal-row .join-chal-in,
  .join-chal-row .join-chal-go {
    flex: 0 0 auto;
    width: 100%;
    min-height: var(--h-md);
  }
}

.bet-opts {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 22px;
}

/* the three options on one row, BACK on its own line under them (the
   phone grid below does the same with its full-row last cell) */
@media (min-width: 641px) {
  .bet-opts {
    display: grid;
    grid-template-columns: repeat(3, max-content);
    justify-content: center;
  }

  #bet-back {
    grid-column: 1 / -1;
    justify-self: center;
  }
}

/* secondary actions = the .btn.alt look: same slant, dark glass fill,
   inset hairline instead of a gradient */
.bet-opt {
  pointer-events: auto;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 26px;
  border: none;
  outline: none;
  position: relative;
  isolation: isolate;
  background: none;
  color: #e9edff;
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 2px;
  transition:
    filter 0.18s,
    transform 0.14s;
}

.bet-opt::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  clip-path: var(--btn-slant);
  background: var(--btn-alt-fill);
  backdrop-filter: blur(10px);
  transition: background 0.18s;
}

/* outline as a ring in the same silhouette — see --btn-slant-ring */
.bet-opt::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  clip-path: var(--btn-slant-ring);
  background: var(--btn-alt-line);
  transition: background 0.18s;
}

.bet-opt:hover::before,
.bet-opt:focus-visible::before {
  background: var(--btn-alt-fill-hi);
}

.bet-opt:hover::after,
.bet-opt:focus-visible::after {
  background: var(--btn-alt-line-hi);
}

.bet-opt:active {
  transform: scale(0.97);
}

.bet-opt-ico {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
}

/* the menu/bet credit strip. Type, tracking and safe-area padding come
   from .app-footer / .app-footer--transparent; only the split-to-the-
   corners layout is this footer's own. */
.bet-foot {
  position: absolute;
  left: var(--screen-pad-l);
  right: var(--screen-pad-r);
  bottom: calc(var(--screen-pad-b) - var(--sp-2));
  display: flex;
  justify-content: space-between;
  gap: var(--sp-4);
  /* #mute is a 40px chip pinned to this same bottom-right corner, so the
     right-hand half of the strip has to stop short of it — "RACE.
     CHALLENGE. EARN." was running under the speaker glyph */
  padding-right: 52px;
  pointer-events: none;
}

/* the 52px reserve above only holds while the row fits: space-between lets
   an over-long strip overflow its own end edge, straight through that
   padding and under #mute. The version/network half is the one that gives
   (it truncates), so the tagline always stops short of the chip. */
.bet-foot > :first-child {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.bet-foot > :last-child {
  flex: 0 0 auto;
  white-space: nowrap;
}

@media (max-width: 600px) {
  .bet-tiers {
    grid-template-columns: repeat(2, 1fr);
  }

  /* the split strip needs two corners to split between; a phone has one
     line's worth of room, so this screen takes the --hidden footer state */
  .bet-foot {
    display: none;
  }
}


.hint {
  font-size: 13px;
  letter-spacing: 2px;
  color: #9a8fb5;
  text-shadow: var(--menu-halo);
}

.hint b {
  color: #fff;
}

/* keycap pill under the menu: [←][→] STEER | [SHIFT] NITRO */
.hint-keys {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 20px;
  border-radius: var(--r-pill);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  color: #b9b2cf;
  background: rgba(12, 14, 30, 0.5);
  border: 1px solid rgba(150, 170, 255, 0.22);
  /* no backdrop blur here: this pill sits ON the menu car, and a backdrop
     filter re-samples the live 3D scene behind it every frame — on a GPU
     browser that showed as a black block flickering on the car until a
     race hid the pill. The 50% dark fill reads the same without it. */
}

.hint-keys kbd {
  display: grid;
  place-items: center;
  min-width: 26px;
  height: 22px;
  padding: 0 6px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 1px;
  color: #e9edff;
  background: rgba(20, 22, 46, 0.7);
  border: 1px solid rgba(150, 170, 255, 0.4);
}

/* the arrow pair reads as one control */
.hint-keys kbd + kbd {
  margin-left: -3px;
}

.hint-keys .sep {
  color: rgba(150, 170, 255, 0.35);
}

/* title screen: the key pill is pinned to the bottom of the screen, out of
   the centred button column's flow */
#title .hint-keys {
  position: absolute;
  left: 50%;
  bottom: calc(var(--screen-pad-b) + 24px);
  transform: translateX(-50%);
  white-space: nowrap;
}

/* ...but on touch there are no arrow keys and no SHIFT to hint at, and the
   pill's right end runs under the 40px #mute chip pinned to the same bottom
   band (mute spans 18-58px up, the pill 36-69px). Nothing to keep. */
body.touch #title .hint-keys {
  display: none;
}

/* same verdict from CSS alone: a coarse pointer (or a phone-width viewport)
   has no arrow keys either, and input.js's body.touch only lands once the
   script runs */
@media (pointer: coarse), (max-width: 640px) {
  #title .hint-keys {
    display: none;
  }
}

/* =========================================================
   MENU RHYTHM (#title)
   The screen used to inherit .screen's flat 20px gap, so the wordmark,
   the tagline, the greeting, the CTA, the three tiles and EXIT were all
   equally far apart — six separate objects floating in a lot of air.
   Two bands instead: IDENTITY (wordmark + tagline + greeting) and
   ACTIONS (CTA + tiles + EXIT), tight inside, with the one deliberate
   gap between them. Same elements, same hero, less drift.
   ========================================================= */
#title {
  gap: var(--sp-2);
}

/* the greeting sits midway: the same break above it (from SPEED) as below
   it (to the CTA), so it reads as its own line rather than leaning either way */
#title #hello {
  margin-top: var(--sp-3);
  margin-bottom: var(--sp-3);
}

/* no name yet (first visit, signed out): the empty line must not keep
   its two margins open between the wordmark and the CTA */
#title #hello:empty {
  display: none;
}

/* the tiles read as one control group hanging off the primary CTA */
#title .menu-tiles {
  margin-top: var(--sp-1);
}

/* EXIT drops a little below the mode tiles instead of hugging them */
#title .btn-row:has(#exit-btn) {
  margin-top: var(--sp-5);
}

/* ---------- clearance for the fixed top-right chip row ----------
   #top-right-chips (wallet + SETTINGS) is absolutely positioned over the
   screen, and .screen centres its content with `justify-content: safe
   center` — which top-anchors at padding-top the moment the content is
   taller than the viewport. A tall screen therefore puts its heading
   exactly where the chips are: the pot lobby's "POT 6HRQ84" was running
   underneath the wallet pill.

   Reserved on the screens that actually grow that tall, rather than by
   raising --screen-pad-t, which would push every menu down by half the
   difference. The mobile breakpoint already reserves the same room
   globally; this keeps the desktop honest about it too. */
#lobby,
#solo-lobby,
#results,
#crash,
#rankings {
  padding-top: calc(var(--chips-top) + var(--chips-h) + var(--sp-3));
}

/* lobby — MULTIPLAYER shares the SOLO RACING heading size/treatment */
#lobby .big,
#solo-lobby .big,
#mp-menu .mp-heading {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: var(--fs-page);
  font-weight: 900;
  letter-spacing: var(--ls-title);
  text-transform: uppercase;
  /* italic slant + background-clip:text clips to the padding box — without
     this the last glyph loses its right edge */
  padding-right: 0.14em;
  background: linear-gradient(100deg, #8ff8ff 0%, #4f8cff 52%, #6a3bff 115%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

#car-bar,
#map-bar,
#dur-bar,
#solo-dur-bar,
#acc-bar,
#solo-acc,
#gfx-bar {
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}

#solo-acc,
#gfx-bar {
  flex-direction: row;
  gap: 8px;
}

/* label sits centered on its own line, options wrap to the next line */
#solo-acc .tlabel,
#gfx-bar .tlabel,
#map-bar .tlabel,
#dur-bar .tlabel,
#solo-dur-bar .tlabel,
#acc-bar .tlabel {
  width: 100%;
  text-align: center;
  order: -1;
  margin-bottom: 2px;
}

.tlabel {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  opacity: 0.5;
}

/* solo pre-race screen: MAP label stacked over the shared weather dropdown */
.solo-lobby-map-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

/* ---- neon HUD pills ----
   Title screen: DRIVE ASSIST + GRAPHICS (fixed widths below).
   Lobby: MAP / RACE TIME / SPEED (widths hug their labels). */
#solo-acc .dur-chip,
#gfx-bar .dur-chip,
#map-bar .dur-chip,
#dur-bar .dur-chip,
#solo-dur-bar .dur-chip,
#acc-bar .dur-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;

  height: 35px;
  padding: 0 14px;

  border: 1px solid rgba(25, 232, 255, 0.32);
  border-radius: var(--r-pill);

  background: rgba(5, 12, 22, 0.9);

  color: #fff;
  font-size: var(--fs-btn-sm);
  font-weight: 700;
  letter-spacing: var(--ls-btn-sm);
  text-transform: uppercase;
  white-space: nowrap;

  cursor: pointer;
  transition:
    box-shadow 0.18s ease,
    border-color 0.18s ease;
}

/* widths per the reference proportions */
#solo-acc .dur-chip[data-mode="auto"] {
  width: 136px;
}

#solo-acc .dur-chip[data-mode="manual"] {
  width: 125px;
}

#gfx-bar .dur-chip {
  width: 120px;
}

/* lobby bars: let each pill size to its own label */
#map-bar .dur-chip,
#dur-bar .dur-chip,
#solo-dur-bar .dur-chip,
#acc-bar .dur-chip {
  padding: 0 18px;
}

#solo-acc .dur-chip:hover,
#gfx-bar .dur-chip:hover,
#solo-dur-bar .dur-chip:hover,
#acc-bar .dur-chip:hover {
  border-color: rgba(25, 232, 255, 0.7);
  box-shadow:
    0 0 6px rgba(25, 232, 255, 0.35),
    inset 0 0 8px rgba(25, 232, 255, 0.1);
}

/* the lobby's MAP / RACE TIME chips: blue-grey at rest, blue on hover —
   no teal on that screen */
#map-bar .dur-chip,
#dur-bar .dur-chip {
  border-color: var(--lobby-line-hi);
}

#map-bar .dur-chip:hover,
#dur-bar .dur-chip:hover {
  border-color: var(--cyan);
  box-shadow: 0 0 8px rgba(79, 140, 255, 0.35);
}

#solo-acc .dur-chip.active,
#gfx-bar .dur-chip.active,
#solo-dur-bar .dur-chip.active,
#acc-bar .dur-chip.active {
  /* same selected look as .env-chip.active (the MAP chips) */
  border-color: var(--pink);
  box-shadow: 0 0 12px rgba(31, 240, 200, 0.4);
}

/* keep both rows on one line and inside the viewport on phones */
@media (max-width: 560px) {
  #solo-acc,
  #gfx-bar {
    gap: 6px;
    flex-wrap: wrap;
    width: 100%;
    padding: 0 8px;
  }

  #solo-acc .dur-chip,
  #gfx-bar .dur-chip {
    height: 32px;
    padding: 0 8px;
    font-size: 10px;
    letter-spacing: 0.6px;
  }

  #solo-acc .dur-chip[data-mode="auto"],
  #solo-acc .dur-chip[data-mode="manual"] {
    width: auto;
    flex: 0 1 auto;
    min-width: 0;
    max-width: 48%;
    padding: 0 14px;
  }

  #gfx-bar .dur-chip {
    width: auto;
    flex: 1 1 0;
    min-width: 0;
    max-width: 96px;
  }
}

#env-bar {
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  padding: 2px 0;
}

#env-bar .tlabel {
  font-size: 10px;
  letter-spacing: 3px;
  opacity: 0.5;
  margin-right: 2px;
  padding: 6px;
}

.env-chip {
  pointer-events: auto;
  cursor: pointer;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 2px;
  padding: 8px 18px;
  color: #fff;
  background: rgba(20, 4, 40, 0.55);
  border: 2px solid rgba(255, 255, 255, 0.15);
  border-radius: 24px;
  transition: border-color 0.15s;
}

.env-chip.active {
  border-color: var(--pink);
  box-shadow: 0 0 12px rgba(31, 240, 200, 0.4);
}

/* ---------- weather dropdown (title + multiplayer menu) ---------- */
.dd {
  position: relative;
  pointer-events: auto;
}

.dd-btn {
  pointer-events: auto;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: "Inter", sans-serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 1px;
  color: #fff;
  background: rgba(255, 255, 255, 0.06);
  border: 1.5px solid rgba(160, 180, 255, 0.3);
  border-radius: var(--r-lg);
  padding: 9px 16px;
  transition: border-color 0.15s;
}

.dd-btn:hover {
  border-color: rgba(160, 180, 255, 0.6);
}

.dd-chev {
  opacity: 0.6;
  font-size: 11px;
  transition: transform 0.15s;
}

.dd.open .dd-chev {
  transform: rotate(180deg);
}

#env-bar {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  min-width: 220px;
  padding: 10px;
  border-radius: var(--r-md);
  background: rgba(10, 8, 24, 0.92);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(160, 180, 255, 0.25);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45);
  display: none;
}

.dd.open #env-bar {
  display: flex;
}

#env-bar .tlabel {
  display: none;
}

/* multiplayer race-settings panel, settings screen + solo pre-race MAP:
   show every map chip inline instead of behind the collapsed dropdown button */
#weather-slot-mp .dd-btn,
#weather-slot-settings .dd-btn,
#weather-slot-solo .dd-btn {
  display: none;
}

#weather-slot-mp #env-bar,
#weather-slot-settings #env-bar,
#weather-slot-solo #env-bar {
  display: flex;
  position: static;
  transform: none;
  flex-wrap: wrap;
  justify-content: center;
  min-width: 0;
  background: none;
  backdrop-filter: none;
  border: none;
  box-shadow: none;
  padding: 0;
}

/* ---------- lobby MAP / RACE TIME / SPEED dropdowns (mobile only —
   see the @media block below for the collapsed/expandable look;
   on desktop this wrapper is invisible and the chip row shows as
   it always has) ---------- */
.chip-dd {
  position: relative;
}

.chip-dd-btn {
  display: none;
}

/* desktop default for markup shared with the mobile lobby cards
   (invite-code row) — inline, so it still reads as one sentence
   until the mobile media query turns it into a stacked card */
.chip-dd-icon {
  display: none;
}

/* leading ← on a BACK button. Upright on purpose: the arrow glyph
   sheared by .btn's italic reads as a broken chevron. */
.btn-arrow {
  font-style: normal;
  margin-right: var(--sp-2);
  line-height: 1;
}

.chip-dd-text {
  display: inline;
}

.chip-dd-caption {
  display: none;
}

.chip-dd-cur {
  display: inline;
}

/* ---------- invite card: copyable/shareable room-code card shown in
   the battle lobby, same size at every viewport ---------- */
.invite-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  max-width: 380px;
  margin: 0 auto;
  text-align: left;
  background: rgba(18, 16, 34, 0.6);
  border: 1px solid rgba(160, 180, 255, 0.2);
  border-radius: var(--r-md);
  padding: 12px 16px;
}

.invite-card-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.invite-card-label {
  font-size: 10px;
  letter-spacing: 2px;
  opacity: 0.55;
  font-weight: 700;
}

.invite-card-code {
  font-family: "Inter", sans-serif;
  font-size: 24px;
  font-weight: 800;
  letter-spacing: 6px;
  color: #fff;
  text-shadow: 0 0 14px rgba(79, 140, 255, 0.5);
}

.invite-card-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.invite-card-btn {
  pointer-events: auto;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: "Inter", sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  color: #fff;
  background: rgba(255, 255, 255, 0.06);
  border: 1.5px solid rgba(160, 180, 255, 0.3);
  border-radius: var(--r-sm);
  padding: 8px 12px;
  transition:
    border-color 0.15s,
    background 0.15s;
}

.invite-card-btn:hover {
  border-color: rgba(160, 180, 255, 0.6);
  background: rgba(255, 255, 255, 0.1);
}

.invite-card-btn.copied {
  border-color: var(--cyan, #4f8cff);
  color: var(--cyan, #4f8cff);
}

.invite-card-icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  color: #fff;
  opacity: 0.95;
}

/* ---------- pot variant: the shareable LINK, spelled out ----------
   A battle room is shared by reading four characters out loud; a pot is
   shared by sending a link, so the link is on the card rather than only
   behind the button. The code stays because it is what the lobby and the
   server call this pot. */
.invite-card--pot {
  flex-wrap: wrap;
  max-width: 420px;
}

.invite-card-link {
  flex: 1 1 100%;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  padding-top: 10px;
  border-top: 1px solid rgba(160, 180, 255, 0.18);
}

.invite-card-link-label {
  font-size: 10px;
  letter-spacing: 2px;
  font-weight: 700;
  opacity: 0.55;
}

/* one line, ellipsised — a long origin must not widen the card or push the
   lobby into a sideways scroll */
.invite-card-url {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: "Inter", sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2px;
  color: #9fc4ff;
  cursor: pointer;
  pointer-events: auto;
}

.invite-card-url:hover,
.invite-card-url:focus-visible {
  color: #cfe0ff;
  text-decoration: underline;
}

/* CREATED BY <name> — the server's record of who made the pot */
.invite-card-meta {
  margin-top: 3px;
  font-size: 10px;
  letter-spacing: 1.6px;
  font-weight: 700;
  opacity: 0.6;
}

/* ---------- back button (top-left, matches wallet-chip's top-right corner) ---------- */
.corner-back {
  position: absolute;
  top: calc(14px + env(safe-area-inset-top));
  left: calc(16px + env(safe-area-inset-left));
  z-index: 40;
  pointer-events: auto;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: "Inter", sans-serif;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1px;
  color: #eafff6;
  background: rgba(10, 8, 20, 0.72);
  border: 1px solid rgba(160, 180, 255, 0.35);
  border-radius: var(--r-lg);
  padding: 8px 16px 8px 12px;
  /* the same 44px every other tappable control gets (--h-md): the pill
     rendered 33px tall, under the touch-target floor on every phone */
  min-height: var(--h-md);
  transition: border-color 0.15s;
}

.corner-back:hover {
  border-color: #14f195;
}

/* ---------- multiplayer mode-select menu ---------- */
.mp-heading {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 900;
  letter-spacing: var(--ls-title);
  text-transform: uppercase;
  font-size: var(--fs-page);
  background: linear-gradient(100deg, #8ff8ff 0%, #4f8cff 52%, #6a3bff 115%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* the -12px margin was pulling this back up under the heading to undo a
   gap it should never have inherited — half that is enough now that the
   tracking no longer widens the line into its neighbour. */
.mp-sub {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  color: #9a8fb5;
  margin-top: calc(-1 * var(--sp-2));
  text-shadow: var(--menu-halo);
}

.mp-net-status {
  font-size: 11px;
  letter-spacing: 2px;
  color: #9a8fb5;
  display: flex;
  align-items: center;
  gap: 6px;
  text-shadow: var(--menu-halo);
}

.mp-net-status .dot {
  color: #ff5c5c;
}

.mp-net-status.is-online .dot {
  color: #39ff8f;
}

.mp-cards {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  justify-content: center;
  pointer-events: auto;
}

.mp-card {
  cursor: pointer;
  width: 180px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: rgba(16, 18, 40, 0.55);
  backdrop-filter: blur(10px);
  border: 1.5px solid rgba(255, 255, 255, 0.14);
  transition:
    border-color 0.15s,
    transform 0.12s,
    box-shadow 0.15s;
}

.mp-card:hover {
  transform: translateY(-2px);
  border-color: rgba(255, 255, 255, 0.4);
  background: rgba(26, 30, 60, 0.7);
}

.mp-card .mp-icon {
  font-size: 28px;
}

.mp-card .mp-card-title {
  font-family: "Orbitron", sans-serif;
  font-weight: 800;
  font-size: 14px;
  letter-spacing: 1px;
}

.mp-card .mp-card-desc {
  font-size: 11px;
  line-height: 1.5;
  color: #9a8fb5;
  text-shadow: var(--menu-halo);
}

.mp-card[data-mode="create"].active {
  border-color: var(--cyan);
  box-shadow: 0 0 20px rgba(79, 140, 255, 0.35);
}

.mp-card[data-mode="join"].active {
  border-color: #a78bfa;
  box-shadow: 0 0 20px rgba(122, 43, 255, 0.35);
}

.mp-wide-btn {
  width: auto;
  text-align: center;
}

/* same shape as the bet screen's OTHER OPTIONS row: content-sized buttons
   that wrap and stay centred, no fixed-width two-column grid */
.mp-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  align-items: center;
}

/* phone: two buttons per row. The desktop plate (15px/26px padding, 2px
   tracking) put DEPOSIT + WITHDRAW at ~380px, wider than a 375px phone,
   so the "row" fell into one button per line. A two-column grid of
   smaller plates instead: equal widths, and a lone trailing button
   (HISTORY here, BACK on the multiplayer screen) takes the whole row.
   Sits below BOTH base rules on purpose: same specificity, so file order
   decides, and above them the flex rows won. */
@media (max-width: 640px) {
  .bet-opts,
  .mp-actions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    width: 100%;
  }

  /* the cell before the full-row BACK, when it would sit alone next to an
     empty one (JOIN CHALLENGE, 3rd of 4), takes the whole row too */
  .bet-opts > .bet-opt:last-child:nth-child(odd),
  .bet-opts > .bet-opt:nth-last-child(2):nth-child(odd),
  #bet-back,
  #mp-back {
    grid-column: 1 / -1;
  }

  .bet-opt {
    gap: 8px;
    padding: 12px 10px;
    min-height: 44px;
    font-size: 11px;
    letter-spacing: 1.2px;
    text-align: center;
  }

  .mp-actions .btn {
    padding: 0 8px;
    font-size: 11px;
    letter-spacing: 1px;
  }
}

/* FORCE START below the server's floor (5 racers): shown, but plainly not
   available. Flat-plate treatment — never `opacity` on the box, which dims
   plate and label together. */
#force-start:disabled {
  color: var(--btn-off-ink);
  cursor: not-allowed;
  pointer-events: none;
}

#force-start:disabled::before {
  background: var(--btn-off-fill);
}

#force-start:disabled::after {
  display: none;
}

/* ---------- race settings (full-screen) ---------- */
/* =========================================================
   CREATE ROOM (#create-room)
   One glass panel holding every room setting, so the host reads
   it as a single form instead of four floating controls. The
   chips inside are the shared .dur-chip, restyled to the squarer
   option-tile look this panel uses.
   ========================================================= */
#create-room {
  gap: var(--sp-5);
}

.cr-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
}

.cr-panel {
  width: 100%;
  max-width: 720px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  padding: var(--sp-6);
  text-align: left;
  border-radius: var(--r-lg);
  background: rgba(16, 18, 40, 0.55);
  backdrop-filter: blur(10px);
  border: 1.5px solid rgba(255, 255, 255, 0.14);
}

/* ROOM NAME takes the slack; TOTAL RACERS keeps its stepper width */
.cr-row {
  display: flex;
  gap: var(--sp-5);
  align-items: flex-start;
  flex-wrap: wrap;
}

.cr-field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 0;
}

.cr-field--name {
  flex: 1 1 260px;
}

.cr-field--racers {
  flex: 0 0 auto;
  align-items: center;
}

.cr-label {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: #9a8fb5;
  display: flex;
  align-items: center;
  gap: 6px;
  text-shadow: var(--menu-halo);
}

.cr-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid rgba(154, 143, 181, 0.7);
  font-size: 10px;
  font-style: italic;
  letter-spacing: 0;
  cursor: help;
}

.cr-input-wrap {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  height: var(--h-lg);
  padding: 0 var(--sp-4);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.06);
  border: 1.5px solid rgba(160, 180, 255, 0.3);
  transition:
    border-color 0.2s,
    box-shadow 0.2s;
}

.cr-input-wrap:focus-within {
  border-color: #7ef7ff;
  box-shadow: 0 0 0 3px rgba(126, 247, 255, 0.15);
}

.cr-input-ico {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  color: #9a8fb5;
}

.cr-input {
  pointer-events: auto;
  flex: 1 1 auto;
  min-width: 0;
  background: none;
  border: 0;
  outline: none;
  color: #fff;
  font: inherit;
  font-size: var(--fs-btn);
  font-weight: 700;
  letter-spacing: var(--ls-btn-sm);
}

.cr-input::placeholder {
  color: #6f668a;
}

.cr-stepper {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  height: var(--h-lg);
  padding: 0 var(--sp-2);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.06);
  border: 1.5px solid rgba(160, 180, 255, 0.3);
}

.cr-step {
  pointer-events: auto;
  cursor: pointer;
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-sm);
  border: 0;
  background: rgba(255, 255, 255, 0.08);
  color: #e9edff;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  transition:
    background 0.15s,
    color 0.15s;
}

.cr-step:hover:not(:disabled) {
  background: rgba(126, 247, 255, 0.18);
  color: #fff;
}

.cr-step:disabled {
  opacity: 0.35;
  cursor: default;
}

.cr-step-val {
  pointer-events: auto;
  width: 56px;
  background: none;
  border: 0;
  outline: none;
  text-align: center;
  color: #fff;
  font: inherit;
  font-size: 18px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.cr-hint {
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-body);
  color: #6f668a;
}

.cr-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  pointer-events: auto;
}

/* the shared chip, squared off for this panel */
.cr-chips .dur-chip {
  border-radius: var(--r-sm);
  border-width: 1.5px;
  border-color: rgba(160, 180, 255, 0.22);
  background: rgba(255, 255, 255, 0.05);
  padding: 11px 18px;
  font-size: var(--fs-btn-sm);
  letter-spacing: var(--ls-btn-sm);
}

/* the solo pre-race screen's MAP / RACE TIME / SPEED chips, the lobby's
   MAP / RACE TIME chips and the BET AMOUNT tiles take the same selected look,
   not the teal HUD glow */
.cr-chips .dur-chip.active,
.tier-btn.on,
#solo-lobby .env-chip.active,
#solo-lobby .dur-chip.active,
#map-bar .dur-chip.active,
#dur-bar .dur-chip.active {
  border-color: var(--cyan);
  background: rgba(79, 140, 255, 0.16);
  box-shadow: 0 0 14px rgba(79, 140, 255, 0.35);
}

.cr-actions {
  margin-top: var(--sp-1);
}

/* YOUR ROOM — the live room this player hosts, in place of the form */
.cr-existing {
  gap: var(--sp-3);
}

.cr-existing-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-3);
  flex-wrap: wrap;
}

.cr-existing-name {
  font-size: var(--fs-h2, 1.6rem);
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: var(--menu-halo);
  overflow-wrap: anywhere;
}

.cr-existing-code {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}

.cr-existing-code b {
  font-size: 1.5rem;
  letter-spacing: 0.3em;
  color: #7ef0ff;
  text-shadow: 0 0 12px rgba(126, 240, 255, 0.5);
}

.cr-existing .cr-actions {
  flex-wrap: wrap;
}

@media (max-width: 640px) {
  .cr-panel {
    padding: var(--sp-5) var(--sp-4);
    gap: var(--sp-4);
  }

  .cr-field--racers {
    flex: 1 1 100%;
    align-items: flex-start;
  }
}

/* =========================================================
   CREATE POT — the private-pot setup screen.
   Deliberately built out of the CREATE ROOM panel's parts (.cr-panel,
   .cr-chips, .cr-stepper) rather than a second set of controls: the two
   screens ask the same KIND of question, so they should not look like two
   different products. Only the pieces a pot has and a room does not — the
   stake tiles, the mode hint and the summary line — are new here.
   ========================================================= */
/* OPEN RACES (the STAKE & RACE browse list) is the same panel holding a list
   instead of questions, so it shares the .cp-* rules below rather than owning
   a near-identical copy of them. */
#create-pot,
#pot-browse,
#room-browse {
  gap: var(--sp-4);
}

/* ---------- OPEN RACES list ----------
   One row per public pot, painted from the server's directory. Everything a
   player needs to choose between two races is on the row itself, because the
   next tap after this one costs real money. */
.pb-panel {
  width: 100%;
  max-width: 760px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-6);
  text-align: left;
  border-radius: var(--r-lg);
  background: rgba(16, 18, 40, 0.55);
  backdrop-filter: blur(10px);
  border: 1.5px solid rgba(255, 255, 255, 0.14);
  pointer-events: auto;
}

.pb-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}

.pb-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-height: 46vh;
  overflow-y: auto;
}

.pb-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  border: 1.5px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.04);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition:
    border-color 0.15s ease,
    background 0.15s ease,
    transform 0.15s ease;
}

.pb-row:hover {
  border-color: rgba(120, 200, 255, 0.55);
  background: rgba(120, 200, 255, 0.08);
  transform: translateY(-1px);
}

.pb-id {
  font-weight: 800;
  letter-spacing: 1.4px;
  color: #e9edff;
  flex: 0 0 auto;
}

.pb-amt {
  font-weight: 800;
  letter-spacing: 1px;
  color: #1ff0c8;
  flex: 0 0 auto;
}

.pb-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  flex: 1 1 auto;
  min-width: 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1.2px;
  color: #9a8fb5;
}

.pb-seats {
  font-weight: 800;
  letter-spacing: 1px;
  color: #e9edff;
  flex: 0 0 auto;
}

.pb-state {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.4px;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  color: #05210f;
  background: #1ff0c8;
}

.pb-empty {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.2px;
  line-height: 1.7;
  color: #9a8fb5;
}

@media (max-width: 640px) {
  .pb-panel {
    padding: var(--sp-4);
  }

  .pb-row {
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-3);
  }
}

.cp-panel {
  width: 100%;
  max-width: 760px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-5);
  text-align: left;
  border-radius: var(--r-lg);
  background: rgba(16, 18, 40, 0.55);
  backdrop-filter: blur(10px);
  border: 1.5px solid rgba(255, 255, 255, 0.14);
  pointer-events: auto;
}

.cp-row {
  display: flex;
  gap: var(--sp-4);
  align-items: flex-start;
  flex-wrap: wrap;
}

.cp-row > .cp-field {
  flex: 1 1 260px;
}

.cp-field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 0;
}

.cp-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 2px;
  color: #9a8fb5;
}

.cp-label--mode {
  margin-top: var(--sp-3);
}

/* the stake tiles are the bet screen's own .tier-btn, only left-aligned and
   allowed to wrap inside the panel — and trimmed here, where seven settings
   share one panel, rather than on the bet screen where they are the screen */
.cp-tiers {
  /* .bet-tiers is sized for the bet SCREEN (width: var(--bet-col)), which is
     wider than this panel's column on a phone — inside the panel the grid
     takes the panel's width instead. */
  width: 100%;
  justify-content: flex-start;
  margin: 0;
}

.cp-tiers .tier-btn {
  gap: 2px;
  padding: 7px 8px 6px;
}

.cp-panel .dur-chip {
  padding: 6px 14px;
}

.cp-panel .cr-stepper {
  height: 40px;
}

.cp-panel .cr-step {
  width: 28px;
  height: 28px;
}

.cp-stepper {
  align-self: flex-start;
}

/* RACERS REQUIRED: presets and the stepper on one row instead of stacked */
.cp-cap-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
}

/* the whole pot in one line, rebuilt on every change — the last check
   before real money is staked */
.cp-summary {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.4px;
  line-height: 1.55;
  color: #9a8fb5;
  padding-top: var(--sp-3);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.cp-summary b {
  color: #e9edff;
  font-weight: 800;
}

@media (max-width: 640px) {
  .cp-panel {
    padding: var(--sp-5) var(--sp-4);
    gap: var(--sp-4);
  }

  /* two stake tiles per row. .bet-tiers is a GRID, so this has to be a
     column count — the flex basis that used to be here did nothing. */
  .cp-tiers {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ---------- pot lobby strip (BET / RACE TIME / MODE) ----------
   Painted from the `pot` block of the server's lobby broadcast, so what it
   shows is the pot's real settings and not what the creating tab remembers
   choosing. */
.pot-info {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  width: min(520px, 100%);
  margin: 0 auto;
}

.pot-info-cell {
  flex: 1 1 auto;
  min-width: 84px;
  padding: 7px 10px;
  border: 1px solid rgba(150, 170, 255, 0.25);
  border-radius: var(--r-sm);
  background: rgba(12, 14, 32, 0.6);
  text-align: center;
}

.pot-info-label {
  display: block;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.6px;
  color: #9a8fb5;
}

.pot-info-val {
  display: block;
  margin-top: 2px;
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 1.2px;
  color: #e9edff;
}

@media (max-width: 560px) {
  .pot-info {
    width: 100%;
  }
}

/* ============================================================
   Multiplayer lobby — the card layout
   ------------------------------------------------------------
   One layout for every room that lands on #lobby: QUICK RACE, a private
   CREATE ROOM, a bet batch and a pot. Desktop: the lobby card
   (#lobby-main) beside the YOUR VEHICLE card; tablet: one card with the
   vehicle beside the roster; phone: a single scrolling column.

   The pieces inside the card differ per room (a pot has the BET strip
   and an invite link, QUICK RACE has the MAP / RACE TIME chip rows and
   FORCE START, a bet batch has neither), so the grid is auto-placed:
   each piece carries an `order` and a column span, and whatever a room
   hides simply leaves no row behind. Each breakpoint only decides WHICH
   wrapper is the grid — #lobby-main on desktop, #lobby-body below that
   (with #lobby-main as display:contents so the vehicle card can join
   the same grid).
   ============================================================ */
#lobby {
  --lobby-line: rgba(120, 150, 255, 0.22);
  --lobby-line-hi: rgba(120, 150, 255, 0.45);
  --lobby-card: linear-gradient(180deg, rgba(10, 12, 30, 0.86), rgba(6, 8, 22, 0.9));
  --lobby-cell: rgba(8, 10, 26, 0.72);
  --lobby-ink-dim: #8a93b8;
  --lobby-ink: #e9edff;
  --lobby-w: 1180px;
  /* the cards on top, then BACK / FORCE START and the hint on one row — a
     grid, so the footer row needs no wrapper of its own. The side padding
     grows past the screen inset to centre everything at --lobby-w. */
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "body    body"
    "actions hint";
  /* vertically centred when it fits; `safe` keeps the top reachable when it
     doesn't (phones), and the plain `start` is the fallback for engines
     that don't know `safe` */
  align-content: start;
  align-content: safe center;
  align-items: center;
  gap: var(--sp-4);
  padding-left: max(var(--screen-pad-l), calc((100% - var(--lobby-w)) / 2));
  padding-right: max(var(--screen-pad-r), calc((100% - var(--lobby-w)) / 2));
  text-align: left;
}

#lobby-body {
  grid-area: body;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 310px);
  gap: var(--sp-4);
  min-width: 0;
  /* below the wallet chip on the widest screens too */
  margin-top: 8px;
}

#lobby-main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-content: start;
  /* the lobby card is as tall as its content; the vehicle card stretches
     to meet it (its stage grows), never the other way round */
  align-self: start;
  gap: var(--sp-4);
  padding: var(--sp-5);
  border: 1px solid var(--lobby-line);
  border-radius: var(--r-lg);
  background: var(--lobby-card);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
  min-width: 0;
}

/* placement: the order the pieces read in, top to bottom */
#lobby-head {
  order: 1;
  grid-column: 1;
}

#lobby .cap-card {
  order: 2;
  grid-column: 2;
}

#lobby .pot-info {
  order: 3;
  grid-column: 1 / -1;
}

/* MAP and RACE TIME (QUICK RACE / private rooms), one row each */
#lobby .chip-dd {
  order: 4;
  grid-column: 1 / -1;
}

#lobby .veh-card {
  order: 5;
}

#lobby #lobby-list {
  order: 6;
  grid-column: 1 / -1;
}

#lobby .invite-card {
  order: 7;
  grid-column: 1 / -1;
}

/* ---- head: eyebrow, room name, status line ---- */
#lobby-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  min-width: 0;
}

#lobby-title {
  flex: 1 1 100%;
  margin: 0;
  text-align: left;
  /* a notch under the page size: the capacity card shares this row */
  font-size: clamp(22px, 2.6vw, 34px);
}

#lobby-title::before {
  content: "RACE LOBBY";
  display: block;
  margin-bottom: 4px;
  font-family: "Inter", sans-serif;
  font-style: normal;
  font-size: var(--fs-label);
  font-weight: 800;
  letter-spacing: var(--ls-label);
  color: var(--lobby-ink-dim);
  /* the title's own gradient is clipped to its text — give the eyebrow
     its own solid ink */
  -webkit-text-fill-color: var(--lobby-ink-dim);
}

/* The clock, once the room has its racers: "STARTS IN 12s" — the number
   big, the words small, all on the status line under the title. */
#lobby #countdown {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-size: 34px;
  font-weight: 900;
  letter-spacing: 1px;
  line-height: 1;
  color: #fff;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 18px rgba(79, 140, 255, 0.55);
}

#lobby #countdown:not(.waiting-text)::before {
  content: "STARTS IN";
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 2px;
  color: var(--cyan);
  text-shadow: none;
}

#lobby #countdown:not(.waiting-text)::after {
  content: "s";
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 1px;
  color: var(--lobby-ink-dim);
  text-shadow: none;
  margin-left: -6px;
}

#lobby #countdown.waiting-text {
  display: inline;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 1.5px;
  line-height: inherit;
  text-shadow: none;
  color: #cfd6ff;
}

#lobby #lobby-sub {
  font-size: 13px;
  letter-spacing: 0.6px;
  text-shadow: none;
  color: var(--lobby-ink-dim);
}

/* ---- capacity card, top-right ---- */
#lobby .cap-card {
  justify-self: end;
  align-self: start;
  width: min(250px, 100%);
  margin: 0;
  padding: 10px 12px;
  gap: 6px;
  border-color: var(--lobby-line);
  background: var(--lobby-cell);
}

#lobby .cap-top {
  order: 2;
}

/* "● 9 SPOTS REMAINING" leads on the card, the count trails the bar */
#lobby .cap-spots {
  order: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  color: var(--lobby-ink);
}

#lobby .cap-spots::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: 0 0 8px var(--cyan);
}

#lobby .cap-bar {
  order: 3;
  height: 8px;
}

#lobby .cap-count {
  font-size: 11px;
  letter-spacing: 1.5px;
  white-space: nowrap;
}

#lobby .cap-state {
  font-size: 10px;
  letter-spacing: 1.5px;
  padding: 3px 6px;
}

/* ---- QUICK RACE: the MAP / RACE TIME chip rows, as labelled cells ---- */
#lobby .chip-dd {
  min-width: 0;
  padding: 10px 14px;
  border: 1px solid var(--lobby-line);
  border-radius: var(--r-md);
  background: var(--lobby-cell);
}

#lobby #map-bar,
#lobby #dur-bar {
  justify-content: flex-start;
  gap: 8px;
}

#lobby #map-bar .tlabel,
#lobby #dur-bar .tlabel {
  width: auto;
  margin: 0 6px 0 0;
  text-align: left;
  font-weight: 800;
  opacity: 1;
  color: var(--lobby-ink-dim);
}

/* ---- BET / MAP / RACE TIME / SPEED / START (pots) ---- */
#lobby .pot-info {
  display: grid;
  /* five across when they fit, else they wrap — never a clipped value */
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 10px;
  width: 100%;
  margin: 0;
}

#lobby .pot-info-cell {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  padding: 12px;
  border-radius: var(--r-md);
  border-color: var(--lobby-line);
  background: var(--lobby-cell);
  text-align: left;
}

#lobby .pot-info-label {
  font-size: 10px;
  letter-spacing: 1.6px;
  color: var(--lobby-ink-dim);
}

.pot-info-body {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.pot-info-body > span {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

#lobby .pot-info-val {
  margin: 0;
  font-size: 12.5px;
  letter-spacing: 0.2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pot-info-sub {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--lobby-ink-dim);
}

/* the cell icons: one SVG each, masked so they take the accent colour */
.pot-info-icon {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  background: linear-gradient(135deg, #8ff8ff, #4f8cff);
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}

.pot-info-icon[data-icon="bet"] {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5l7 10.2-7 4.1-7-4.1z'/%3E%3Cpath d='M12 22.5l7-9.4-7 4.1-7-4.1z' opacity='.6'/%3E%3C/svg%3E");
}

.pot-info-icon[data-icon="map"] {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 22.5s7.5-7 7.5-12.5a7.5 7.5 0 1 0-15 0c0 5.5 7.5 12.5 7.5 12.5zm0-9.7a2.8 2.8 0 1 1 0-5.6 2.8 2.8 0 0 1 0 5.6z'/%3E%3C/svg%3E");
}

.pot-info-icon[data-icon="time"] {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3.5 2.2'/%3E%3C/svg%3E");
}

.pot-info-icon[data-icon="speed"] {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M3.5 17.5a8.5 8.5 0 1 1 17 0'/%3E%3Cpath d='M12 17.5l4.2-6'/%3E%3Ccircle cx='12' cy='17.5' r='1.4' fill='%23000'/%3E%3C/svg%3E");
}

.pot-info-icon[data-icon="start"] {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.5 3.5l13.5 8.5-13.5 8.5z'/%3E%3C/svg%3E");
}

/* ---- roster: one tile per seat ---- */
#lobby #lobby-list {
  min-width: 0;
  max-height: none;
  mask-image: none;
  gap: 10px;
  padding: 12px 14px 14px;
  border: 1px solid var(--lobby-line);
  border-radius: var(--r-md);
  background: var(--lobby-cell);
}

.pl-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.6px;
  color: var(--lobby-ink-dim, #8a93b8);
}

.pl-head b {
  color: #fff;
}

.pl-head > span:first-child {
  font-size: 11px;
  color: var(--lobby-ink, #e9edff);
}

.pl-slots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 8px;
}

.pl-slot {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-width: 0;
  min-height: 52px;
  padding: 8px 6px;
  border: 1px solid rgba(120, 150, 255, 0.25);
  border-radius: var(--r-sm);
  background: rgba(14, 18, 44, 0.7);
  font-weight: 700;
  letter-spacing: 0.6px;
  overflow: hidden;
}

.pl-slot.empty {
  border-style: dashed;
  background: rgba(10, 12, 30, 0.45);
}

.pl-slot.me {
  border-color: var(--cyan);
  box-shadow:
    0 0 0 1px rgba(79, 140, 255, 0.25),
    0 0 18px rgba(79, 140, 255, 0.25);
}

.pl-slot.gone {
  opacity: 0.55;
}

.pl-plus {
  font-size: 22px;
  font-weight: 300;
  color: rgba(170, 185, 255, 0.5);
}

.pl-slot-name {
  max-width: 100%;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.2px;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pl-slot-sub {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--lobby-ink-dim, #8a93b8);
  font-variant-numeric: tabular-nums;
}

.pl-slot.me .pl-slot-sub::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: 0 0 6px var(--cyan);
}

/* ---- invite card, full width of the lobby card ---- */
#lobby .invite-card {
  max-width: none;
  width: 100%;
  margin: 0;
  border-color: var(--lobby-line);
  background: var(--lobby-cell);
}

#lobby .invite-card-label {
  opacity: 1;
  color: var(--lobby-ink-dim);
  font-size: 10px;
  letter-spacing: 1.6px;
}

/* ---- YOUR VEHICLE ---- */
.veh-card {
  --veh-tint: #4f8cff;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  padding: var(--sp-5);
  border: 1px solid rgba(79, 140, 255, 0.45);
  border-radius: var(--r-lg);
  background:
    radial-gradient(120% 70% at 50% 100%, color-mix(in srgb, var(--veh-tint) 22%, transparent), transparent 60%),
    linear-gradient(180deg, rgba(12, 14, 36, 0.9), rgba(6, 8, 24, 0.95));
  box-shadow:
    0 0 0 1px rgba(79, 140, 255, 0.12),
    0 0 40px rgba(79, 140, 255, 0.18),
    0 20px 60px rgba(0, 0, 0, 0.45);
  text-align: left;
}

.veh-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.veh-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.8px;
  color: #9fc4ff;
}

.veh-eyebrow svg,
.veh-btn svg {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
}

.veh-selected {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(79, 140, 255, 0.6);
  background: rgba(79, 140, 255, 0.12);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.6px;
  color: var(--cyan);
}

.veh-selected svg {
  width: 14px;
  height: 14px;
}

.veh-name {
  margin-top: 4px;
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  /* sized so the longest name (BUGATTI CHIRON) stays on one line */
  font-size: clamp(20px, 1.8vw, 24px);
  font-weight: 900;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.1;
  color: #fff;
  /* italic + clipped gradient: same guard as the page titles */
  padding-right: 0.14em;
}

.veh-name em {
  font-style: inherit;
  background: linear-gradient(100deg, #8ff8ff 0%, #4f8cff 52%, #a06bff 115%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

.veh-class {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 2px;
  color: #b58cff;
}

.veh-stage {
  position: relative;
  flex: 1 1 auto;
  /* at this minimum the vehicle card matches a QUICK RACE lobby card */
  min-height: 140px;
  margin: 2px 0;
  overflow: hidden;
  border-radius: var(--r-md);
  /* a showroom plate rather than bare card: the panel is what fills the
     card's spare height, the car sits in the middle of it */
  border: 1px solid rgba(120, 150, 255, 0.14);
  background:
    radial-gradient(80% 60% at 50% 100%, color-mix(in srgb, var(--veh-tint) 18%, transparent), transparent 70%),
    linear-gradient(180deg, rgba(14, 18, 44, 0.35), rgba(6, 8, 24, 0.6));
}

.veh-stage::before {
  content: "";
  position: absolute;
  left: 12%;
  right: 12%;
  bottom: 8%;
  height: 22%;
  border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--veh-tint) 55%, #4f8cff), transparent);
  filter: blur(14px);
  opacity: 0.8;
}

/* the thumbnails carry ~25% clear margin on every side (see
   _gen_thumbs2.mjs) — drawn oversize and clipped by the stage, so the car
   fills the frame instead of floating in it */
.veh-stage img {
  position: absolute;
  left: 50%;
  top: 50%;
  /* the box is oversize in both axes; object-fit keeps the picture's
     2:1 shape inside it, so the car scales with whichever axis is tighter */
  width: 165%;
  height: 100%;
  max-width: none;
  object-fit: contain;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 18px 24px rgba(0, 0, 0, 0.6));
}

.veh-stats {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.veh-stat {
  display: grid;
  grid-template-columns: 78px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.4px;
}

.veh-k {
  color: #9fa8cc;
}

.veh-bar {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 3px;
  height: 9px;
}

.veh-bar i {
  border-radius: 2px;
  background: rgba(120, 150, 255, 0.16);
}

.veh-bar i.on {
  background: linear-gradient(90deg, #7fe9ff, #6aa8ff 55%, #a06bff);
  box-shadow: 0 0 6px rgba(111, 168, 255, 0.5);
}

.veh-v {
  color: #fff;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.veh-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 4px;
  padding: 11px 16px;
  border: 1px solid var(--btn-alt-line);
  border-radius: var(--r-sm);
  background: var(--btn-alt-fill);
  color: var(--btn-alt-ink);
  font-family: "Inter", sans-serif;
  font-size: var(--fs-btn-sm);
  font-weight: 800;
  letter-spacing: var(--ls-btn-sm);
  cursor: pointer;
  pointer-events: auto;
  transition:
    border-color 0.15s,
    background 0.15s;
}

.veh-btn:hover {
  border-color: var(--btn-alt-line-hi);
  background: var(--btn-alt-fill-hi);
}

/* ---- footer: BACK (and FORCE START / START POT) left, the hint beside ---- */
#lobby .screen-actions {
  grid-area: actions;
  margin-top: 0;
  width: auto;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
}

#lobby .screen-actions > .btn {
  width: auto;
  min-width: 150px;
}

#lobby .hint {
  grid-area: hint;
  min-width: 0;
  text-align: right;
  font-size: 12px;
  letter-spacing: 0.4px;
  text-shadow: none;
}

/* ---- tablet: one card, the vehicle beside the roster ---- */
@media (max-width: 1100px) {
  #lobby-main {
    display: contents;
  }

  #lobby-body {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-content: start;
    padding: var(--sp-5);
    border: 1px solid var(--lobby-line);
    border-radius: var(--r-lg);
    background: var(--lobby-card);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
  }

  /* the vehicle takes the left column beside the roster and the invite card */
  #lobby .veh-card {
    grid-column: 1;
    grid-row: span 2;
  }

  #lobby #lobby-list,
  #lobby .invite-card {
    grid-column: 2;
  }

  #lobby .pot-info {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  }

  /* stats on the left, the car on the right, button at the bottom */
  .veh-card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 46%);
    grid-template-rows: auto auto auto auto minmax(0, 1fr) auto;
    grid-template-areas:
      "vhead  vhead"
      "vname  vstage"
      "vclass vstage"
      "vstats vstage"
      ".      vstage"
      "vbtn   vbtn";
    gap: 8px 12px;
    align-self: stretch;
  }

  .veh-head {
    grid-area: vhead;
  }

  .veh-name {
    grid-area: vname;
  }

  .veh-class {
    grid-area: vclass;
  }

  .veh-stage {
    grid-area: vstage;
    min-height: 120px;
    margin: 0;
    align-self: stretch;
  }

  .veh-stage img {
    width: 175%;
  }

  .pl-slots {
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  }

  .veh-stats {
    grid-area: vstats;
    margin-top: 6px;
  }

  .veh-btn {
    grid-area: vbtn;
    justify-self: start;
  }

  .veh-stat {
    grid-template-columns: 72px minmax(0, 1fr) auto;
  }
}

/* ---- phone: one column, compact & scrollable ---- */
@media (max-width: 640px) {
  #lobby {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "body"
      "actions"
      "hint";
    gap: var(--sp-3);
  }

  #lobby-body {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--sp-3);
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    margin-top: 0;
  }

  /* everything but the head + capacity row spans the column */
  #lobby .veh-card,
  #lobby #lobby-list,
  #lobby .invite-card {
    grid-column: 1 / -1;
    grid-row: auto;
  }

  #lobby .cap-card {
    width: 120px;
    padding: 8px 10px;
  }

  #lobby #countdown {
    font-size: 28px;
  }

  #lobby .cap-spots {
    font-size: 10px;
    letter-spacing: 1px;
  }

  #lobby .cap-count {
    font-size: 10px;
  }

  #lobby .cap-count b {
    font-size: 14px;
  }

  #lobby .cap-state {
    display: none;
  }

  /* the MAP / RACE TIME rows are the collapsible dropdown buttons here
     (see the .chip-dd block in the phone rules) — no cell around them */
  #lobby .chip-dd {
    max-width: none;
    padding: 0;
    border: 0;
    background: none;
  }

  #lobby .pot-info {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
  }

  #lobby .pot-info-cell {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 6px 6px;
    padding: 9px 10px;
  }

  .pot-info-body {
    display: contents;
  }

  #lobby .pot-info-label {
    grid-area: 1 / 2;
    font-size: 10px;
    letter-spacing: 1.2px;
  }

  .pot-info-icon {
    grid-area: 1 / 1;
    width: 15px;
    height: 15px;
  }

  .pot-info-body > span {
    grid-area: 2 / 1 / 3 / 3;
  }

  #lobby .pot-info-val {
    font-size: 12px;
    letter-spacing: 0.2px;
  }

  .veh-card {
    grid-template-columns: minmax(0, 1fr) minmax(0, 44%);
    padding: var(--sp-4);
    border-radius: var(--r-md);
  }

  .veh-name {
    font-size: 20px;
  }

  .veh-stat {
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: 6px;
    font-size: 10px;
    letter-spacing: 1px;
  }

  .veh-k {
    white-space: nowrap;
  }

  .veh-stage img {
    width: 190%;
  }

  .veh-bar {
    gap: 2px;
    height: 8px;
  }

  .veh-v {
    font-size: 11px;
  }

  .veh-btn {
    width: 100%;
  }

  .pl-slots {
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 6px;
  }

  .pl-slot {
    min-height: 46px;
    padding: 6px 4px;
  }

  .pl-slot-name {
    font-size: 10px;
    letter-spacing: 0.8px;
  }

  #lobby .screen-actions {
    width: 100%;
    justify-content: stretch;
  }

  #lobby .screen-actions > .btn {
    min-width: 0;
    flex: 1 1 0;
  }

  #lobby .hint {
    text-align: center;
  }
}
#race-settings {
  gap: 26px;
}

.rs-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
}

.rs-title {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 900;
  letter-spacing: 3px;
  font-size: clamp(26px, 5vw, 40px);
  background: linear-gradient(100deg, #8ff8ff 0%, #4f8cff 52%, #6a3bff 115%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.rs-sub {
  font-size: 11px;
  letter-spacing: 4px;
  color: #9a8fb5;
  text-shadow: var(--menu-halo);
}

.rs-body {
  width: 100%;
  max-width: 900px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 18px;
  pointer-events: auto;
}

.rs-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 26px 22px;
  border-radius: var(--r-lg);
  background: rgba(16, 18, 40, 0.55);
  backdrop-filter: blur(10px);
  border: 1.5px solid rgba(255, 255, 255, 0.14);
}

.rs-card-label {
  font-size: 11px;
  letter-spacing: 3px;
  color: #9a8fb5;
  font-weight: 700;
  text-shadow: var(--menu-halo);
}

/* upsize the shared weather chips into full option cards on this page */
#race-settings #weather-slot-mp #env-bar {
  gap: 12px;
}

#race-settings #weather-slot-mp .env-chip {
  padding: 14px 22px;
  font-size: 13px;
  border-radius: var(--r-md);
}

#race-settings #weather-slot-mp .env-chip.active {
  border-color: var(--cyan);
  box-shadow: 0 0 16px rgba(79, 140, 255, 0.45);
}

.rs-confirm:focus-visible,
#mp-back:focus-visible,
#rs-open-btn:focus-visible,
#rs-back:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
}

.car-card {
  pointer-events: auto;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 5px;
  align-items: center;
  flex: 0 0 auto;
  padding: 10px 14px;
  border-radius: var(--r-md);
  border: 2px solid rgba(255, 255, 255, 0.12);
  background: rgba(20, 4, 40, 0.55);
  transition:
    transform 0.12s,
    border-color 0.15s;
}

.car-card:hover {
  transform: scale(1.08);
}

.car-card.active {
  border-color: #fff;
  box-shadow: 0 0 14px rgba(255, 255, 255, 0.35);
}

.cc-body {
  width: 46px;
  height: 12px;
  border-radius: 5px;
}

.cc-trim {
  width: 30px;
  height: 4px;
  border-radius: 2px;
}

.cc-name {
  font-size: 11px;
  letter-spacing: 2px;
  opacity: 0.7;
  font-weight: 700;
}

.cc-stat {
  font-size: 11px;
  letter-spacing: 1px;
  color: #b4aecb;
  font-variant-numeric: tabular-nums;
}

.dur-chip {
  pointer-events: auto;
  cursor: pointer;
  font-size: var(--fs-body);
  font-weight: 700;
  letter-spacing: var(--ls-btn-sm);
  padding: 8px 18px;
  color: #fff;
  background: rgba(20, 4, 40, 0.55);
  border: 2px solid rgba(255, 255, 255, 0.15);
  border-radius: 24px;
  transition: border-color 0.15s;
}

.dur-chip.active {
  border-color: var(--pink);
}

.pl-num {
  color: var(--cyan);
}


#race-timer {
  position: absolute;
  top: var(--hud-row-2);
  left: 50%;
  transform: translateX(-50%);
  /* above #leaderboard (z-index 11): on a <=360px phone the centred timer
     and the right-hand board overlap by a few px, and the board was
     painting over the countdown */
  z-index: 12;
  display: none;
  font-size: 26px;
  font-weight: 900;
  letter-spacing: 2px;
  color: #fff;
  text-shadow: var(--hud-halo), 0 0 16px var(--cyan);
  font-variant-numeric: tabular-nums;
}

#race-timer.urgent {
  color: #ff5e5e;
  text-shadow: 0 0 18px #ff5e5e;
}

#countdown {
  font-size: 80px;
  font-weight: 900;
  color: #fff;
  text-shadow: 0 0 30px var(--pink);
  font-variant-numeric: tabular-nums;
}

#countdown.waiting-text {
  font-size: 22px;
  letter-spacing: 3px;
  text-shadow: 0 0 16px var(--cyan);
}

#lobby-sub {
  font-size: 14px;
  letter-spacing: 3px;
  color: #9a8fb5;
  text-shadow: var(--menu-halo);
}

/* ---- QUICK RACE capacity card ----
   Compact by design: a count line, a capacity bar and the spots left. Every
   value is written by hud.setCapacity() from the server's lobby broadcast.
   --cap-pct is the only thing that moves; the bar fill reads it directly so
   a join/leave repaints in one property write. */
.cap-card {
  --cap-pct: 0%;
  width: min(320px, 100%);
  margin: 2px auto 0;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  border: 1px solid rgba(150, 170, 255, 0.25);
  border-radius: var(--r-sm);
  background: rgba(12, 14, 32, 0.6);
}

.cap-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.cap-count {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 2px;
  color: #e9edff;
}

.cap-count b {
  font-size: 18px;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

/* WAITING / COUNTDOWN / RUNNING / FULL — the server's state, verbatim. */
.cap-state {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 2px;
  padding: 3px 7px;
  border-radius: var(--r-pill);
  color: #aab3d0;
  background: rgba(150, 170, 255, 0.12);
}

.cap-state.is-countdown {
  color: #04040e;
  background: var(--pink);
}

.cap-state.is-full {
  color: #04040e;
  background: #ffc95e;
}

.cap-bar {
  height: 10px;
  border-radius: var(--r-pill);
  overflow: hidden;
  /* the unfilled remainder: a dotted plate, so empty capacity reads as
     "space left" rather than as an unlit part of the same bar */
  background-color: rgba(150, 170, 255, 0.14);
  background-image: radial-gradient(
    rgba(233, 237, 255, 0.35) 1px,
    transparent 1px
  );
  background-size: 4px 4px;
}

.cap-fill {
  height: 100%;
  width: var(--cap-pct);
  border-radius: var(--r-pill);
  background: var(--btn-fill);
  transition: width 0.25s ease;
}

.cap-spots {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 2px;
  color: #9a8fb5;
}

@media (prefers-reduced-motion: reduce) {
  .cap-fill {
    transition: none;
  }
}

@media (max-width: 560px) {
  .cap-card {
    width: 100%;
    padding: 9px 10px;
  }

  .cap-count {
    letter-spacing: 1px;
  }

  .cap-count b {
    font-size: 16px;
  }
}

#lobby-list {
  /* THREE rows visible, the rest scrolled — a 20-racer grid is far too tall
     to sit on the lobby screen, and the capacity card above already says how
     many are in. The cap is derived from the row metrics rather than a flat
     pixel height, so the mobile block below only has to restate --pl-row-h
     when it changes .pl-row's padding/font-size. */
  --pl-row-h: 36px;
  --pl-gap: 6px;
  --pl-rows: 3;
  display: flex;
  flex-direction: column;
  gap: var(--pl-gap);
  min-width: 260px;
  max-height: calc(
    var(--pl-rows) * var(--pl-row-h) + (var(--pl-rows) - 1) * var(--pl-gap)
  );
  overflow: auto;
  touch-action: pan-y;
  /* Fades the last visible row out at the bottom edge while there is more
     below it, so a cut-off list reads as "scroll" instead of "that's
     everyone". Ends once the list is scrolled to the bottom is not
     expressible in CSS alone — a static fade is the honest cheap version. */
  mask-image: linear-gradient(to bottom, #000 78%, rgba(0, 0, 0, 0.15) 100%);
}

.pl-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 16px;
  border-radius: var(--r-sm);
  background: rgba(20, 4, 40, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.08);
  font-weight: 700;
  letter-spacing: 1px;
}

.pl-row.me {
  border-color: var(--pink);
}

.pl-row-top {
  display: flex;
  justify-content: space-between;
}

/* player status + bet status — a bet room's second line under each racer's
   name, kept visible for a player who left/disconnected instead of
   removing their row (see realtime/src/index.js's playerStatus()). */
.pl-status-line {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.5px;
  opacity: 0.9;
}

.pl-status-line.playing {
  color: #3ddc84;
}

.pl-status-line.left {
  color: #9a8fb5;
}

.pl-status-line.disconnected {
  color: #ffb84d;
}

/* =========================================================
   MULTIPLAYER RESULTS — .results-head + .results-card
   The crest/title stand on the road; the card under them holds the
   winner strip (#payout), the ranked rows (#results-list) and the three
   YOUR tiles. Palette: the mint (--pink) title glow, gold for #1 and a
   won pot, --cyan distances, --purple best, the game's payout green for
   points. Five rows fit unscrolled; a bigger room scrolls the list.
   ========================================================= */
#results {
  gap: 14px;
}

.results-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.results-crest {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 10px;
  line-height: 1;
  filter: drop-shadow(0 0 18px rgba(31, 240, 200, 0.45));
  animation: crash-crest-in 0.6s cubic-bezier(0.2, 1.4, 0.4, 1) both;
}

.results-crest .clock {
  width: 84px;
  height: 84px;
  color: var(--pink);
}

.results-crest .flag {
  width: 58px;
  height: 58px;
  margin-bottom: 12px;
  color: #ddd;
  transform-origin: 10% 90%;
  transform: rotate(-18deg);
}

.results-crest .flag.r {
  transform: scaleX(-1) rotate(-18deg);
}

#results.pot-win .results-crest {
  filter: drop-shadow(0 0 18px rgba(255, 230, 0, 0.5));
}

#results.pot-win .results-crest .clock {
  color: #ffe600;
}

#results .big {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 900;
  font-size: clamp(34px, 6vw, 60px);
  line-height: 1;
  letter-spacing: var(--ls-title);
  text-transform: uppercase;
  padding-right: 0.14em; /* italic overhang, see #lobby .big */
  color: #fff;
  text-shadow:
    0 0 28px var(--pink),
    0 4px 24px rgba(0, 0, 0, 0.6);
}

/* pot win/lose (hud.showResults with pot: true) — the winner's title and
   prize share #new-best's gold */
#results.pot-win .big {
  text-shadow:
    0 0 28px #ffe600,
    0 4px 24px rgba(0, 0, 0, 0.6);
}

.results-sub {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: clamp(11px, 1.5vw, 14px);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #d9d4ee;
}

.results-card {
  width: min(860px, 100%);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
  padding: 16px;
  border-radius: var(--r-lg);
  background:
    linear-gradient(115deg, rgba(31, 240, 200, 0.08) 0%, transparent 38%),
    linear-gradient(295deg, rgba(122, 43, 255, 0.14) 0%, transparent 40%),
    rgba(10, 12, 30, 0.72);
  backdrop-filter: blur(14px);
  border: 1.5px solid rgba(150, 170, 255, 0.28);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.04) inset,
    0 30px 80px rgba(0, 0, 0, 0.55),
    0 0 50px rgba(79, 140, 255, 0.14);
}

.results-card > * {
  flex-shrink: 0;
}

/* winner strip */
#payout {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px 14px;
  padding: 10px 14px 12px;
  font-size: 18px;
  font-weight: 700;
  color: #e9edff;
  text-shadow: none;
}

#payout > svg {
  width: 30px;
  height: 30px;
  color: #ffe600;
  filter: drop-shadow(0 0 10px rgba(255, 230, 0, 0.5));
}

#payout .who b {
  color: #ffe600;
  letter-spacing: 0.04em;
}

#payout .gain {
  padding: 5px 14px;
  border-radius: var(--r-pill);
  background: rgba(20, 241, 149, 0.14);
  border: 1px solid rgba(20, 241, 149, 0.4);
  font-size: 14px;
  font-weight: 800;
  color: #14f195;
  font-variant-numeric: tabular-nums;
}

#payout a {
  color: #9fffe0;
}

#results .pot-prize {
  width: 100%;
  text-align: center;
  font-family: "Orbitron", sans-serif;
  font-size: var(--fs-page);
  font-weight: 900;
  color: #ffe600;
  text-shadow: 0 0 22px rgba(255, 230, 0, 0.6);
  letter-spacing: 2px;
  font-variant-numeric: tabular-nums;
}

#results .pot-sub {
  width: 100%;
  text-align: center;
  margin-top: -4px;
  font-size: 13px;
  letter-spacing: 2px;
  color: #9a8fb5;
}

/* YOUR DISTANCE · YOUR BEST · POINTS EARNED */
.results-tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}

.results-tiles .tile {
  display: grid;
  grid-template-columns: 40px 1fr;
  grid-template-rows: auto auto;
  column-gap: 12px;
  align-items: center;
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(150, 170, 255, 0.2);
  text-align: left;
}

.results-tiles .ico {
  grid-row: 1 / span 2;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(150, 170, 255, 0.22);
}

.results-tiles .ico svg {
  width: 20px;
  height: 20px;
}

.results-tiles .k {
  font-size: var(--fs-label);
  font-weight: 800;
  letter-spacing: var(--ls-label);
  color: #c9c3de;
}

.results-tiles .v {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 900;
  font-size: clamp(18px, 2.2vw, 24px);
  line-height: 1;
  padding-right: 0.1em;
  white-space: nowrap;
}

.results-tiles .v small {
  font-size: 0.55em;
  font-weight: 800;
}

.results-tiles .dist .ico,
.results-tiles .dist .v {
  color: var(--cyan);
}

.results-tiles .best .ico,
.results-tiles .best .v {
  color: var(--purple);
  filter: brightness(1.25);
}

.results-tiles .pts .ico {
  color: #ffe600;
}

.results-tiles .pts .v {
  color: #c9c3de;
}

.results-tiles .pts.up .v {
  color: #14f195;
}

.results-tiles .pts.down .v {
  color: #ff8a9c;
}

/* NEXT BATCH + BACK, label over sub-label like the WIPEOUT card */
.results-actions {
  width: min(760px, 100%);
  display: flex;
  justify-content: center;
  gap: 12px;
}

.results-actions > .btn {
  flex: 1 1 0;
  min-width: 0;
  max-width: 380px; /* a pot hides NEXT BATCH: BACK alone stays a button, not a bar */
  --btn-h: 60px;
  gap: 10px;
}

.results-actions .ico {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

.results-actions .stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  line-height: 1;
}

.results-actions .stack small {
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
  font-style: normal;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.14em;
  opacity: 0.7;
}

#results .results-tip {
  width: min(760px, 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 14px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(150, 170, 255, 0.18);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-shadow: none;
}

#results .results-tip svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: #ffe600;
}

@media (max-width: 640px) {
  .results-card {
    padding: 12px;
  }

  .results-tiles {
    grid-template-columns: minmax(0, 1fr);
  }

  .results-actions {
    flex-direction: column;
  }

  .results-actions > .btn {
    --btn-h: 52px;
  }

  .results-crest .clock {
    width: 64px;
    height: 64px;
  }

  .results-crest .flag {
    width: 42px;
    height: 42px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .results-crest {
    animation: none;
  }
}

#new-best {
  color: #ffe600;
  text-shadow: 0 0 18px #ffe600;
  font-weight: 800;
  letter-spacing: 3px;
  font-size: 15px;
  opacity: 0;
}

.stat-row {
  display: flex;
  gap: 48px;
}

.stat {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.stat .k {
  font-size: 12px;
  letter-spacing: 3px;
  opacity: 0.6;
}

.stat .v {
  font-size: 36px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

/* =========================================================
   WIPEOUT / TIME UP — .crash-card
   One glass card over the frozen road, in the game's own palette: the
   mint (--pink) title glow the screen has always had, --cyan for the
   run, --purple for the best, the primary gradient on RETRY. #crash.timeup
   swaps the wheel crest for the clock. Rows keep their ids — main.js and
   hud.js paint them — only the frame around them is new.
   ========================================================= */
.crash-card {
  position: relative;
  width: min(680px, 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin-top: 34px; /* the crest hangs above the card's top edge */
  padding: 22px 26px 18px;
  border-radius: var(--r-lg);
  background:
    linear-gradient(115deg, rgba(31, 240, 200, 0.1) 0%, transparent 38%),
    linear-gradient(295deg, rgba(122, 43, 255, 0.16) 0%, transparent 40%),
    rgba(10, 12, 30, 0.72);
  backdrop-filter: blur(14px);
  border: 1.5px solid rgba(150, 170, 255, 0.28);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.04) inset,
    0 30px 80px rgba(0, 0, 0, 0.55),
    0 0 50px rgba(79, 140, 255, 0.14);
}

.crash-card > * {
  flex-shrink: 0;
}

/* crest: the wheel (wipeout) or the clock (time up), on the top edge */
.crash-crest {
  width: 92px;
  height: 92px;
  margin: -68px 0 -6px;
  color: var(--pink);
  filter: drop-shadow(0 0 18px rgba(31, 240, 200, 0.55));
  animation: crash-crest-in 0.6s cubic-bezier(0.2, 1.4, 0.4, 1) both;
}

.crash-crest svg {
  width: 100%;
  height: 100%;
}

.crash-crest .spark {
  color: #ffe600;
}

.crash-crest-clock,
#crash.timeup .crash-crest-wheel {
  display: none;
}

#crash.timeup .crash-crest-clock {
  display: block;
}

#crash.timeup .crash-crest {
  color: var(--cyan);
  filter: drop-shadow(0 0 18px rgba(79, 140, 255, 0.6));
}

@keyframes crash-crest-in {
  from {
    transform: scale(0.4) rotate(-40deg);
    opacity: 0;
  }
}

#crash .big {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 900;
  font-size: clamp(34px, 6vw, 60px);
  line-height: 1;
  letter-spacing: var(--ls-title);
  text-transform: uppercase;
  padding-right: 0.14em; /* italic overhang, see #lobby .big */
  color: #fff;
  text-shadow:
    0 0 28px var(--pink),
    0 4px 24px rgba(0, 0, 0, 0.6);
}

.crash-sub {
  margin-top: -6px;
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: clamp(11px, 1.5vw, 14px);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #d9d4ee;
}

/* #new-best keeps its gold flash; it only takes up room while shown */
#crash #new-best {
  margin: -6px 0;
  line-height: 1;
  transition: opacity 0.3s;
}

#crash #new-best[style*="opacity: 0"] {
  display: none;
}

/* YOUR DISTANCE | BEST — one plate, split by a hairline */
#crash .stat-row {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  padding: 14px 8px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(150, 170, 255, 0.22);
}

#crash .stat {
  align-items: center;
  gap: 8px;
}

#crash .stat + .stat {
  border-left: 1px solid rgba(150, 170, 255, 0.22);
}

#crash .stat .k {
  font-size: var(--fs-label);
  font-weight: 800;
  letter-spacing: var(--ls-label);
  opacity: 1;
  color: #c9c3de;
}

#crash .stat .v {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 900;
  font-size: clamp(26px, 4.6vw, 40px);
  line-height: 1;
  padding-right: 0.1em;
}

#crash .stat .v::after {
  content: "m";
  margin-left: 0.15em;
  font-size: 0.5em;
  font-weight: 800;
}

#crash .stat:nth-child(1) .v {
  color: var(--cyan);
  text-shadow: 0 0 18px rgba(79, 140, 255, 0.55);
}

#crash .stat:nth-child(2) .v {
  color: var(--purple);
  text-shadow: 0 0 18px rgba(122, 43, 255, 0.6);
}

/* the gap pill: N m short of the best, or gold past it */
.crash-gap {
  padding: 9px 18px;
  border-radius: var(--r-pill);
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(150, 170, 255, 0.22);
  font-size: 14px;
  color: #e9edff;
}

.crash-gap b {
  color: var(--pink);
}

.crash-gap.best {
  border-color: rgba(255, 230, 0, 0.45);
  color: #ffe600;
}

.crash-gap.best b {
  color: #fff;
}

.crash-encourage {
  margin-top: -4px;
  font-size: 13px;
  letter-spacing: 0.12em;
  color: #9a8fb5;
}

/* buttons: CREATE CHALLENGE on top, RETRY + BACK sharing one row of the
   same width beneath it, each a label with a small sub-label under it */
#crash-create-chal-btn,
#crash-actions {
  width: min(420px, 100%);
}

#crash-actions {
  display: flex;
  gap: 12px;
}

#crash-actions > .btn {
  flex: 1 1 0;
  min-width: 0;
  --btn-h: 60px;
  gap: 10px;
}

#crash-actions .ico {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

#crash-actions .stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  line-height: 1;
}

#crash-actions .stack small {
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
  font-style: normal;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.14em;
  opacity: 0.7;
}

#crash .crash-tip {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 14px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(150, 170, 255, 0.18);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-shadow: none;
}

#crash .crash-tip svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: #ffe600;
}

#crash #chal-result {
  width: 100%;
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(150, 170, 255, 0.18);
  letter-spacing: 0.04em;
  text-shadow: none;
}

#crash #spectate[style*="opacity: 0"] {
  display: none;
}

@media (max-width: 480px) {
  .crash-card {
    padding: 20px 14px 14px;
    gap: 12px;
  }

  #crash-actions {
    flex-direction: column;
  }

  #crash-actions > .btn {
    --btn-h: 52px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .crash-crest {
    animation: none;
  }
}

#spectate {
  font-size: 13px;
  letter-spacing: 2px;
  color: var(--cyan);
  opacity: 0;
}

/* the ranked rows: rank chip · crown · name · pts · metres */
#results-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  /* five rows (48px + gap) before the list scrolls */
  max-height: min(272px, 42svh);
  overflow: auto;
  touch-action: pan-y;
  scrollbar-width: thin;
}

.res-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  padding: 6px 14px 6px 8px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(150, 170, 255, 0.2);
  font-weight: 700;
  min-width: 0;
}

.res-row.me {
  border-color: rgba(31, 240, 200, 0.7);
  box-shadow: 0 0 14px rgba(31, 240, 200, 0.22);
}

.res-row.win {
  background: rgba(255, 230, 0, 0.06);
  border-color: rgba(255, 230, 0, 0.75);
  box-shadow: 0 0 16px rgba(255, 230, 0, 0.25);
}

.res-rank {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.08);
  font-family: "Orbitron", sans-serif;
  font-weight: 900;
  font-size: 14px;
  color: #e9edff;
}

.res-row.win .res-rank {
  background: rgba(255, 230, 0, 0.18);
  color: #ffe600;
}

.res-crown {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  color: #ffe600;
}

.res-crown svg {
  width: 100%;
  height: 100%;
}

.res-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left; /* the screen centres everything; a table column must not */
  letter-spacing: 0.08em;
  font-size: 15px;
  text-transform: uppercase;
}

.res-name small {
  margin-left: 8px;
  padding: 2px 7px;
  border-radius: var(--r-pill);
  background: rgba(31, 240, 200, 0.16);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: var(--pink);
  vertical-align: 2px;
}

.res-bal {
  font-size: 14px;
  font-weight: 800;
  color: #14f195;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.res-dist {
  min-width: 84px;
  text-align: right;
  font-size: 15px;
  color: #fff;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.res-bet {
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
  color: #14f195;
}

@media (max-width: 640px) {
  .res-row {
    gap: 8px;
    padding: 6px 10px 6px 6px;
  }

  .res-name {
    font-size: 13px;
  }

  .res-dist {
    min-width: 0;
    font-size: 13px;
  }

  .res-bal {
    font-size: 12px;
  }
}

/* the top-right chip row owns the corner; the gear and the wallet chip
   are flow items inside it, so the gear always sits directly left of the
   wallet chip whatever its width (and slides right when it's hidden) */
#top-right-chips {
  position: absolute;
  top: var(--chips-top);
  right: var(--chips-right);
  z-index: 45;
  display: flex;
  align-items: center;
  gap: 10px;
  pointer-events: none;
}

#top-right-chips > * {
  pointer-events: auto;
}

/* both chips stand on one height — #wallet-menu measures its offset from
   it, so it must not be hardcoded anywhere else */
#top-right-chips > .btn {
  --btn-h: var(--chips-h);
}

/* =========================================================
   WALLET CONNECT — .wallet-connect
   ONE component with two ink variants, not two components.
   #wallet-chip (the global top-right pill, every menu screen) and
   #login-wallet-btn (the stand-in the login screen shows in that same
   corner before the real chip is allowed to appear) used to be
   independently written: 12px vs 10px, 1px vs 1.5px border, italic vs
   not, 7/14 vs 8/18 padding. They are the same control to a player, so
   geometry lives here once and the variants only carry colour.

     .wallet-connect--dark   night screens (menu, bet, garage...)
     .wallet-connect--light  the daylight login/loading photo

   The SETTINGS gear (#settings-btn) is a SEPARATE control that happens
   to sit next to this one — it keeps its own round geometry below and
   must not be folded into the wallet's box.
   ========================================================= */
.wallet-connect {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);

  /* one height for both variants, so the pill does not resize when the
     player crosses from #login into the menu. It is --btn-h, not a value
     of its own: #wallet-chip carries .btn, whose min-height: var(--btn-h)
     silently won over the 36px this used to declare — so the pill really
     stood 44px while the gear next to it obeyed the 36. One token now
     drives both chips. */
  height: var(--btn-h);
  padding: 0 var(--sp-4);
  border-radius: var(--r-pill);
  border: 1.5px solid transparent;

  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: var(--fs-btn-sm);
  font-weight: 800;
  letter-spacing: var(--ls-btn-sm);
  line-height: 1;
  white-space: nowrap;

  cursor: pointer;
  user-select: none;

  /* colour is the ONLY thing a variant is allowed to change, and it does
     it through these four props — so a contextual override (see the
     #loading rule below) is the same component, not a fourth skin. */
  color: var(--wallet-ink);
  background: var(--wallet-fill);
  border-color: var(--wallet-line);
  box-shadow: var(--wallet-shadow, none);

  transition:
    border-color 0.15s ease,
    box-shadow 0.15s ease,
    transform 0.15s ease;
}

/* (the mark itself is sized by `.wallet-ico .wallet-svg` further down —
   1.25em off whichever pill holds it, so it tracks this font-size) */

.wallet-connect--dark {
  --wallet-ink: #e9edff;
  --wallet-fill: rgba(15, 17, 38, 0.8);
  --wallet-line: rgba(120, 140, 220, 0.35);
}

.wallet-connect--dark:hover {
  --wallet-line: var(--cyan);
  --wallet-shadow: 0 0 14px rgba(79, 140, 255, 0.3);
}

.wallet-connect--light {
  --wallet-ink: #315cff;
  --wallet-fill: rgba(255, 255, 255, 0.9);
  --wallet-line: rgba(70, 100, 220, 0.28);
  --wallet-shadow: 0 5px 18px rgba(20, 30, 80, 0.13);
}

.wallet-connect--light:hover {
  --wallet-line: #3355ff;
  --wallet-shadow: 0 7px 22px rgba(51, 85, 255, 0.25);
  transform: translateY(-1px);
}

/* the connected chip's balance rides inside the pill */
.wallet-connect b {
  color: var(--wallet-ink); /* the balance reads in the chip's ink, not green */
}

/* the dollar figure that follows an SOL amount (chip + dropdown) */
.wusd {
  color: #9a8fb5;
  font-weight: 400;
}

.wusd::before {
  content: " · ";
  opacity: 0.6;
}

/* #wallet-chip also carries .btn (for its hover/active transforms) —
   drop the slanted clipped layer and its sheen so the whole pill stays
   clickable and reads as a pill, not a parallelogram */
#wallet-chip::before,
#wallet-chip::after {
  display: none;
}

/* SETTINGS chip — round gear pill sitting immediately left of
   #wallet-chip inside #top-right-chips. Shown on every menu screen
   (body.menu, set in main.js alongside the wallet chip) and hidden
   wherever the wallet chip is hidden. */
#settings-btn {
  position: relative;
  display: none;
  align-items: center;
  justify-content: center;
  /* square on the wallet pill's height so the two chips sit on one
     baseline in #top-right-chips — the gear used to come out ~33px
     against the pill's ~31px and the row read as slightly crooked */
  /* square on --btn-h, the same token #wallet-chip stands on: .btn floors
     every CTA at min-height: var(--btn-h), so anything smaller declared
     here lost on the vertical axis and the "circle" came out an oval. */
  width: var(--btn-h);
  height: var(--btn-h);
  padding: 0;
  font-size: var(--fs-btn-sm);
  color: #e9edff;
  background: rgba(15, 17, 38, 0.8);
  border: 1.5px solid rgba(120, 140, 220, 0.35);
  border-radius: 50%;
  box-shadow: none;
  cursor: pointer;
  user-select: none;
}

body.menu #settings-btn {
  display: inline-flex;
}

body:has(#login:not(.hidden)) #settings-btn,
body:has(#garage:not(.hidden)) #settings-btn,
body:has(#settings-screen:not(.hidden)) #settings-btn,
body:has(#help-screen:not(.hidden)) #settings-btn,
body:has(#support-screen:not(.hidden)) #settings-btn,
body:has(#wallet-screen:not(.hidden)) #settings-btn,
body:has(#chal-mine:not(.hidden)) #settings-btn,
body:has(.screen:not(.hidden) .corner-back) #settings-btn {
  display: none;
}

#settings-btn:hover {
  border-color: var(--cyan);
  box-shadow: 0 0 14px rgba(79, 140, 255, 0.3);
}

#settings-btn::before,
#settings-btn::after {
  display: none;
}

/* matches #wallet-chip .wallet-svg — sized off the chip's font-size */
#settings-btn .ico {
  display: block;
  width: 1.25em;
  height: 1.25em;
}

#login-back-btn {
  min-width: 120px;
  padding: 11px 28px;

  font-size: 13px;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;

  color: #eafff6;

  background: none;
  border: none;
  border-radius: 0;

  position: relative;
  isolation: isolate;

  cursor: pointer;
  user-select: none;

  /* slant on ::before so the button box stays fully clickable */

  transition:
    transform 0.2s ease,
    box-shadow 0.2s ease,
    background 0.2s ease;
}
/* Default: hidden on login */
#login .auth-info {
  display: none;
}

/* Show information when signup form is active */
#login.signup-active .auth-info {
  display: block;
}
#login-back-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;

  clip-path: polygon(8px 0, 100% 0, calc(100% - 8px) 100%, 0 100%);

  background: linear-gradient(
    135deg,
    rgba(25, 18, 45, 0.95),
    rgba(20, 15, 38, 0.95)
  );

  box-shadow:
    inset 0 0 0 1px #14f195,
    0 0 8px rgba(20, 241, 149, 0.25),
    inset 0 0 12px rgba(20, 241, 149, 0.08);

  transition:
    box-shadow 0.2s ease,
    background 0.2s ease;
}

#login-back-btn:hover::before {
  box-shadow:
    inset 0 0 0 1px #14f195,
    0 0 14px rgba(20, 241, 149, 0.45),
    inset 0 0 14px rgba(20, 241, 149, 0.12);

  background: linear-gradient(
    135deg,
    rgba(30, 22, 55, 0.98),
    rgba(24, 18, 45, 0.98)
  );
}

#login-back-btn:active {
  transform: translateY(1px);
}

/* The white login/loading skin that used to sit here was a THIRD wallet
   implementation (11px, 1.5px border, its own blue). Two notes:

   - the `body:has(#login...)` half was already unreachable: main.js only
     un-hides #wallet-chip on a menu state with #login hidden, and the
     login screen puts its own #login-wallet-btn in that same corner.
   - the #loading half is kept, but as the SAME component: it just
     re-points the four --wallet-* props at the light variant's values.

   .wallet-connect / --light / --dark live in the WALLET CONNECT block
   above; hover for both variants is defined there too. */
body:has(#loading:not(.hidden)) #wallet-chip {
  --wallet-ink: #315cff;
  --wallet-fill: rgba(255, 255, 255, 0.9);
  --wallet-line: rgba(70, 100, 220, 0.28);
  --wallet-shadow: 0 5px 18px rgba(20, 30, 80, 0.13);
}

/* colour comes from .wallet-connect b above; only the weight is
   the chip's own */
#wallet-chip b {
  font-weight: 600;
}

#toast-stack {
  position: fixed;
  top: calc(16px + env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background: rgba(10, 8, 20, 0.92);
  border: 1px solid #ffb02e55;
  border-radius: var(--r-sm);
  color: #eafff6;
  /* the same body face as every other notice; monospace was the one
     stray typeface on an error state */
  font-family: "Inter", sans-serif;
  font-size: var(--fs-body);
  letter-spacing: var(--ls-body);
  line-height: 1.4;
  /* a toast is centred with translateX(-50%), so an unwrapped 90-character
     wallet/session message ran off BOTH edges of a phone with nothing to
     scroll to. Wrap inside the viewport instead. */
  max-width: calc(100vw - var(--screen-pad-l) - var(--screen-pad-r));
  white-space: normal;
  text-align: left;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35);
  opacity: 0;
  transform: translateY(-6px);
  transition:
    opacity 0.18s ease,
    transform 0.18s ease;
}

.toast.show {
  opacity: 1;
  transform: translateY(0);
}

.toast-ico {
  color: #ffb02e;
  font-size: 13px;
  line-height: 1;
}

/* a positioned child of #top-right-chips, so 100% IS the chip row: the
   panel hangs 8px under the row, off its RIGHT edge (the gear), at a
   fixed readable width. It used to be pinned to BOTH edges and take the
   row's width — fine while the chip carried the address, but the chip is
   balance-only now (~150px) and the panel shrank with it until its rows
   overlapped.
   z-index sits above the row's chips so the pill can't paint over it. */
#wallet-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: min(320px, calc(100vw - 28px));
  z-index: 46;
  max-height: calc(100dvh - var(--chips-top) - var(--chips-h) - 24px);
  overflow-y: auto;
  box-sizing: border-box;
  font-size: 12px;
  letter-spacing: 0.5px;
  color: #e9edff;
  background: rgba(15, 17, 38, 0.94);
  border: 1px solid rgba(120, 140, 220, 0.35);
  border-radius: var(--r-md);
  padding: 10px;
}

#wallet-tokens {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 8px;
  max-height: 200px;
  overflow-y: auto;
  touch-action: pan-y;
}

.wt-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 4px 6px;
  border-radius: 6px;
  background: rgba(79, 140, 255, 0.08);
}

.wt-row.wt-max {
  background: rgba(79, 140, 255, 0.16);
  border: 1px solid rgba(79, 140, 255, 0.4);
}

.wt-label {
  color: #9a8fb5;
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
}

.wt-mint {
  font-family: monospace;
  color: #e9edff;
}

.wt-amt {
  color: #e9edff;
  font-weight: 600;
  white-space: nowrap;
}

.wt-addr {
  font-family: monospace;
  font-weight: 400;
  color: #e9edff;
  white-space: nowrap;
  text-align: right;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

/* copy icon next to the abbreviated address — .wallet-act's glass, square */
.wt-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  color: #e9edff;
  background: rgba(79, 140, 255, 0.08);
  border: 1px solid rgba(79, 140, 255, 0.3);
  border-radius: 6px;
  cursor: pointer;
}

.wt-copy.copied {
  color: #5aa0ff; /* the ✓ flash */
}

.wt-copy svg {
  width: 14px;
  height: 14px;
}

.wt-copy:hover,
.wt-copy:focus-visible {
  border-color: var(--cyan);
  background: rgba(79, 140, 255, 0.18);
}

/* after a copy the check replaces the copy glyph for a beat */
.wt-copy .wt-copy-ok,
.wt-copy.copied .wt-copy-ico {
  display: none;
}

.wt-copy.copied .wt-copy-ok {
  display: block;
}

/* DEPOSIT / WITHDRAW / LOGOUT: three icon buttons on one row, in the
   dropdown's own glass look (same recipe as .wallet-pick below). */
#wallet-actions {
  display: flex;
  gap: 6px;
}

.wallet-act {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 9px 4px 8px;
  font: inherit;
  font-size: 10px;
  letter-spacing: 1px;
  color: #e9edff;
  background: rgba(79, 140, 255, 0.08);
  border: 1px solid rgba(79, 140, 255, 0.25);
  border-radius: 9px;
  cursor: pointer;
}

.wallet-act svg {
  width: 20px;
  height: 20px;
}

.wallet-act:hover,
.wallet-act:focus-visible {
  background: rgba(79, 140, 255, 0.18);
  border-color: rgba(79, 140, 255, 0.6);
}

.wallet-act-out:hover,
.wallet-act-out:focus-visible {
  background: rgba(255, 107, 138, 0.12);
  border-color: #ff6b8a88;
}

body:has(#garage:not(.hidden)) #mute,
body:has(#garage:not(.hidden)) #wallet-chip,
body:has(#garage:not(.hidden)) #wallet-menu {
  display: none !important;
}

/* same chip treatment as #wallet-chip: dark translucent fill with a
   green-tinted hairline border, sized square around the glyph */
#mute {
  position: absolute;
  bottom: calc(18px + env(safe-area-inset-bottom));
  right: calc(20px + env(safe-area-inset-right));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: rgba(10, 8, 20, 0.72);
  border: 1px solid #14f19555;
  border-radius: 20px;
  color: #eafff6;
  pointer-events: auto;
  cursor: pointer;
  user-select: none;
  opacity: 0.75;
  font-size: 16px;
  line-height: 1;
  transition: opacity 0.2s;
  z-index: 30;
}

/* both action buttons wear the HUD score face (.value: Orbitron italic) so
   the on-screen controls read as the same family as DISTANCE / BEST */
#horn-btn,
#nitro-btn {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
}

#horn-btn {
  display: none;
  position: absolute;
  bottom: calc(16px + env(safe-area-inset-bottom));
  left: calc(50% - 12px);
  transform: translateX(-100%);
  pointer-events: auto;
  cursor: pointer;
  z-index: 30;
  user-select: none;
  -webkit-user-select: none;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 2px;
  color: #fff;
  padding: 12px 26px;
  border-radius: 40px;
  border: 2px solid #ffcf33;
  background: rgba(30, 20, 0, 0.35);
  text-shadow: 0 0 10px #ffcf33;
  box-shadow: 0 0 18px rgba(255, 207, 51, 0.4);
  transition:
    transform 0.08s,
    box-shadow 0.1s;
}

#horn-btn:active {
  transform: translateX(-100%) scale(0.94);
  box-shadow: 0 0 28px rgba(255, 207, 51, 0.9);
}

#nitro-btn {
  display: none;
  position: absolute;
  bottom: calc(16px + env(safe-area-inset-bottom));
  left: calc(50% + 12px);
  pointer-events: auto;
  cursor: pointer;
  z-index: 30;
  user-select: none;
  -webkit-user-select: none;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 2px;
  color: #fff;
  padding: 12px 22px;
  border-radius: 40px;
  border: 2px solid #13f1ff;
  background: rgba(0, 20, 30, 0.35);
  text-shadow: 0 0 10px #13f1ff;
  box-shadow: 0 0 18px rgba(19, 241, 255, 0.4);
  transition: transform 0.08s;
}

#nitro-btn:active {
  transform: scale(0.94);
}

/* EXIT the run: the bottom-left twin of #mute — same 40px face, same weight,
   so the two corner controls read as a pair and neither crowds the centred
   HORN / NITRO pair between them. Shown only while racing (main.js). */
#race-exit-btn {
  display: none;
  position: absolute;
  bottom: calc(18px + env(safe-area-inset-bottom));
  left: calc(20px + env(safe-area-inset-left));
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: rgba(10, 8, 20, 0.72);
  border: 1px solid #14f19555;
  border-radius: 20px;
  color: #eafff6;
  pointer-events: auto;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  opacity: 0.75;
  transition:
    opacity 0.2s,
    transform 0.08s;
  z-index: 30;
}

#race-exit-btn svg {
  width: 18px;
  height: 18px;
}

#race-exit-btn:hover {
  opacity: 1;
}

#race-exit-btn:active {
  transform: scale(0.94);
}

/* ---------- rankings board ---------- */
#rankings {
  gap: 14px;
}

/* the header rule: label centred between two fading cyan lines */
.rk-head {
  display: flex;
  align-items: center;
  gap: 12px;
  width: min(440px, 92vw);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 3px;
  color: #7fb2ff;
}

.rk-head::before,
.rk-head::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(79, 140, 255, 0.55));
}

.rk-head::after {
  background: linear-gradient(90deg, rgba(79, 140, 255, 0.55), transparent);
}

.rk-card {
  width: min(440px, 92vw);
  padding: 14px;
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, #0d1a3c 0%, #0a1430 100%);
  border: 1px solid rgba(79, 140, 255, 0.28);
  box-shadow:
    0 12px 34px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

.rk-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 0 4px 11px;
  margin-bottom: 11px;
  border-bottom: 1px solid rgba(79, 140, 255, 0.2);
}

.rk-card-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 2.4px;
  color: #dbe8ff;
}

.rk-ico {
  width: 15px;
  height: 15px;
  color: #4f8cff;
}

.rk-ico.gold {
  color: #f0b73f;
}

.rk-card-meta {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1.4px;
  color: #7fa6e0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rk-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 30vh;
  overflow: auto;
  touch-action: pan-y;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.rk-list::-webkit-scrollbar {
  display: none;
}

.rk-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 14px;
  border-radius: 11px;
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid transparent;
  font-weight: 700;
}

/* leader of either board — cyan ring in YOUR RANK, gold in ALL TIME */
.rk-row.lead {
  background: rgba(79, 140, 255, 0.1);
  border-color: rgba(79, 140, 255, 0.85);
  box-shadow: 0 0 16px rgba(79, 140, 255, 0.28);
}

.rk-row.lead.gold {
  background: rgba(240, 183, 63, 0.09);
  border-color: rgba(240, 183, 63, 0.75);
  box-shadow: 0 0 16px rgba(240, 183, 63, 0.22);
}

.rk-row.lead.gold .rk-rank,
.rk-row.lead.gold .rk-name {
  color: #f0b73f;
}

.rk-row.me .rk-name {
  color: var(--pink);
}

.rk-rank {
  width: 22px;
  font-size: 13px;
  color: #93a9d4;
  text-align: left;
}

.rk-crown {
  font-size: 12px;
  line-height: 1;
}

.rk-name {
  flex: 1;
  text-align: left;
  font-size: 13px;
  letter-spacing: 1.6px;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rk-dist {
  font-size: 13px;
  font-weight: 800;
  color: #4f8cff;
  font-variant-numeric: tabular-nums;
}

.rk-empty {
  opacity: 0.5;
  font-size: 13px;
  padding: 8px;
}

/* ---------- transaction history (inflow / outflow) ----------
   TRANSACTIONS sits in the settings shell like WALLET and reuses its card
   surface (rgba(15,17,38,.9) + rgba(120,140,220,.2) border) so VIEW ALL
   lands on the same panel the player just left. Inflow is app blue, not
   green — the only green on the wallet screen is the focus ring. */
#history .settings-content {
  gap: 16px;
}

/* USD | SOL switch + live rate (same pill as the wallet's unit toggle) */
#tx-unit {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 4px;
}

.tx-unit-btn {
  min-width: 56px;
  padding: 7px 12px;
  border: 1px solid rgba(120, 170, 255, 0.3);
  background: rgba(8, 8, 22, 0.8);
  color: #9a8fb5;
  border-radius: var(--r-sm);
  cursor: pointer;
  font-family: "Inter", sans-serif;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.5px;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}

.tx-unit-btn.on {
  color: #e9edff;
  border-color: var(--cyan);
  background: rgba(79, 140, 255, 0.18);
}

.tx-unit-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

#tx-rate {
  margin-left: auto;
  font-family: "Inter", sans-serif;
  font-size: 12px;
  color: #aab3d0;
  font-variant-numeric: tabular-nums;
}

/* INFLOW / OUTFLOW / NET — the wallet balance cards, three up */
#tx-totals {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

.tx-total {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 12px;
  border-radius: var(--r-md);
  background: rgba(15, 17, 38, 0.9);
  border: 1px solid rgba(120, 140, 220, 0.2);
  text-align: center;
  min-width: 0;
}

.tx-total-label {
  font-family: "Inter", sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 2px;
  color: #9a8fb5;
  text-transform: uppercase;
}

.tx-total-amt {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 800;
  font-size: clamp(14px, 2.4vw, 18px);
  color: #e9edff;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tx-total-amt.in {
  color: #5aa0ff;
}

.tx-total-amt.out {
  color: #ff6b8b;
}

/* the list is one card; rows are hairline-divided like the wallet's
   RECENT ACTIVITY */
#tx-list {
  display: flex;
  flex-direction: column;
  max-height: 44vh;
  overflow: auto;
  touch-action: pan-y;
  scrollbar-width: none;
  -ms-overflow-style: none;
  border-radius: var(--r-md);
  background: rgba(15, 17, 38, 0.9);
  border: 1px solid rgba(120, 140, 220, 0.2);
}

#tx-list::-webkit-scrollbar {
  display: none;
}

.tx-row {
  display: grid;
  /* TYPE | game id / explorer link | when | status | amount — every cell
     is pinned to its column because CONFIRMED badges are display:none,
     which would otherwise slide the amount into the badge's column */
  grid-template-columns: auto minmax(0, 1fr) auto 78px 96px;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid rgba(120, 140, 220, 0.12);
  font-family: "Inter", sans-serif;
  font-size: 12px;
  color: #e9edff;
}

.tx-row:last-child {
  border-bottom: none;
}

.tx-row.pending {
  opacity: 0.75;
}

.tx-row.failed,
.tx-row.cancelled {
  /* muted ink rather than `opacity` on the row: .tx-sub carries its own
     muted colour inside, and the two would multiply on the line that holds
     the failure reason and the signature */
  color: #9a93ab;
}

.tx-type {
  grid-column: 1;
  text-align: left;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
}

.tx-sub {
  grid-column: 2;
  min-width: 0;
  text-align: left;
  font-size: 11px;
  color: #7f86a6;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tx-sub a {
  color: #8ff8ff;
}

.tx-when {
  grid-column: 3;
  color: #7f86a6;
  white-space: nowrap;
  text-align: right;
}

.tx-row .tx-status {
  grid-column: 4;
  justify-self: end;
}

.tx-amt {
  grid-column: 5;
  font-family: "Orbitron", sans-serif;
  font-weight: 800;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-align: right;
}

.tx-amt.in {
  color: #5aa0ff;
}

.tx-amt.out {
  color: #ff6b8b;
}

.tx-status {
  font-size: 11px;
  letter-spacing: 1px;
  padding: 2px 6px;
  border-radius: 5px;
  border: 1px solid rgba(255, 255, 255, 0.15);
  opacity: 0.8;
}

.tx-status.confirmed {
  display: none;
}

/* shared with the wallet's RECENT ACTIVITY card */
.tx-empty {
  padding: 16px;
  text-align: center;
  font-family: "Inter", sans-serif;
  font-size: 12px;
  color: #7f86a6;
}

/* the note under the list — same voice as the wallet card notes */
#history .tx-foot {
  padding: 0 4px;
  font-family: "Inter", sans-serif;
  font-size: 11px;
  line-height: 1.4;
  color: #7f86a6;
  text-align: center;
}

/* REFRESH and BACK share one row; BACK keeps the shell's button but not
   its stand-alone top margin */
#history .tx-actions {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

#history .tx-actions .settings-back-btn {
  margin-top: 0;
}

@media (max-width: 560px) {
  #tx-totals {
    gap: 8px;
  }

  .tx-total {
    padding: 12px 8px;
  }

  /* two columns: TYPE / amount, then when / status, then the link */
  .tx-row {
    grid-template-columns: 1fr auto;
    row-gap: 2px;
  }

  .tx-type {
    grid-row: 1;
  }

  .tx-amt {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
  }

  .tx-when {
    grid-column: 1;
    grid-row: 2;
    text-align: left;
  }

  .tx-row .tx-status {
    grid-column: 2;
    grid-row: 2;
  }

  .tx-sub {
    grid-column: 1 / -1;
    grid-row: 3;
  }

  .tx-sub:empty {
    display: none;
  }
}

#mute:hover {
  opacity: 1;
}

/* matches .wallet-ico .wallet-svg — sized off the chip's font-size */
#mute .mute-svg {
  display: block;
  width: 1.25em;
  height: 1.25em;
}

#mute .mute-off,
#mute.is-muted .mute-on {
  display: none;
}

#mute.is-muted .mute-off {
  display: block;
}

.touch-zone {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;
  z-index: 15;
  display: none;
  touch-action: none;
}

#touch-left {
  left: 0;
}

#touch-right {
  right: 0;
}

body.touch .touch-zone {
  display: block;
}

#loading {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding: calc(var(--screen-pad-t) + var(--hero-top)) var(--screen-pad-r)
    var(--screen-pad-b) var(--screen-pad-l);
  z-index: 40;
  overflow: hidden;
  color: #ffffff;
  background:
    var(--first-screen-scrim),
    url("firstScreen.jpg") center bottom / cover no-repeat,
    var(--first-screen-fallback);
  transition: opacity 0.4s ease;
}

#loading.hidden {
  display: none;
}
#loading > * {
  /* position: relative; */
  z-index: 1;
}

#loading-tagline {
  /* clear of SPEED's italic descent — at 10px it read as a fourth line of
     the wordmark */
  margin-top: clamp(16px, 2.4vh, 24px);
  font-size: clamp(10px, 1.6vw, 13px);
  font-weight: 700;
  letter-spacing: 3px;
  color: rgba(255, 255, 255, 0.82);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.8);
  text-transform: uppercase;
}

#loading-ring {
  position: relative;
  width: clamp(140px, 22vw, 190px);
  height: clamp(140px, 22vw, 190px);
  margin: clamp(20px, 4vh, 36px) 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

#loading-ring svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

#loading-ring .ring-track {
  fill: none;
  /* faint on the night photo so the gradient fill is the only loud arc —
     at .75 the empty track read as 100% */
  stroke: rgba(255, 255, 255, 0.18);
  stroke-width: 6;
}

#loading-ring .ring-fill {
  fill: none;
  stroke: url(#loading-ring-grad);
  stroke-width: 6;
  stroke-linecap: round;
  /* no CSS transition: main.js eases the ring and the % label together */
  filter: drop-shadow(0 2px 6px rgba(64, 86, 226, 0.45));
}

#loading-pct {
  font-size: clamp(24px, 4vw, 32px);
  font-weight: 800;
  color: #ffffff;
  letter-spacing: 1px;
  line-height: 1;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.85);
}

#loading-steps {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: clamp(8px, 2.6vw, 22px);
  margin-top: clamp(16px, 3vh, 28px);
  width: min(92vw, 620px);
}

#loading-steps::before {
  content: "";
  position: absolute;
  left: 12%;
  right: 12%;
  top: 20px;
  height: 1px;
  background: rgba(20, 32, 84, 0.18);
  z-index: -1;
}

#loading-steps .step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 84px;
  flex: none;
  text-align: center;
}

#loading-steps .step .label {
  min-height: 22px;
  display: flex;
  align-items: flex-start;
  justify-content: center;
}

#loading-steps .step .dot {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  border: 1.5px solid rgba(20, 32, 84, 0.14);
  background: rgba(255, 255, 255, 0.85);
  color: rgba(16, 26, 58, 0.7);
  transition:
    border-color 0.25s ease,
    color 0.25s ease,
    box-shadow 0.25s ease,
    background 0.25s ease;
}

#loading-steps .step .label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  /* full-strength ink plus the same white halo #loading-tagline uses: these
     sit directly on the photo with no plate, and at 45% they measured ~2.6:1
     against the band of firstScreen.jpg they land on */
  color: #33405e;
  text-shadow: 0 1px 10px rgba(255, 255, 255, 0.75);
  transition: color 0.25s ease;
}

#loading-steps .step.done .dot {
  border-color: #3355ff;
  color: #3355ff;
  background: #fff;
  box-shadow: 0 4px 14px rgba(51, 85, 255, 0.28);
}

#loading-steps .step.done .label,
#loading-steps .step.active .label {
  color: #101a3a;
}

#loading-steps .step.active .dot {
  border-color: #8b3cf0;
  color: #101a3a;
  background: #fff;
  box-shadow: 0 4px 16px rgba(139, 60, 240, 0.4);
  animation: loading-pulse 1.1s ease-in-out infinite;
}

@keyframes loading-pulse {
  0%,
  100% {
    box-shadow: 0 4px 16px rgba(139, 60, 240, 0.4);
  }
  50% {
    box-shadow: 0 6px 24px rgba(139, 60, 240, 0.7);
  }
}

#loading-tip {
  margin-top: clamp(18px, 4vh, 30px);
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(88vw, 460px);
  padding: 10px 16px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.85);
  box-shadow: 0 16px 40px rgba(20, 32, 84, 0.2);
  backdrop-filter: blur(10px);
}

#loading-tip .tip-badge {
  flex: none;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1px;
  color: #fff;
  background: linear-gradient(90deg, #2f6bff, #8b3cf0);
  border-radius: 6px;
  padding: 4px 8px;
}

#loading-tip .tip-text {
  font-size: 11px;
  line-height: 1.4;
  font-weight: 600;
  color: #3b4763;
}

@media (max-width: 640px) {
  #loading-steps {
    gap: 4px;
    width: min(96vw, 420px);
  }

  #loading-steps::before {
    left: 10%;
    right: 10%;
    top: 16px;
  }

  #loading-steps .step {
    width: 56px;
    gap: 4px;
  }

  #loading-steps .step .dot {
    width: 32px;
    height: 32px;
    font-size: 14px;
  }

  #loading-steps .step .label {
    font-size: 11px;
    letter-spacing: 0.5px;
    min-height: 18px;
  }
}

/* ---------- LOGIN (first page: name + PIN) ---------- */
/* login: daylight circuit photo behind a light "paper" sign-in card.
   This screen is the one light-themed surface in the app, so every
   colour below is set explicitly rather than inherited from the dark
   defaults the rest of the screens share. */
/* =========================================================
LOGIN ROAD MOTION
Creates the illusion that the road is rushing past
========================================================= */

#login {
  isolation: isolate;
  /* one source of truth for SIGN IN + ENTER GARAGE */
  /* first stop darkened from #1689ff: white ink measured 3.47:1 there,
     and these labels are 11-12px, so the 4.5 floor applies. #0f6ad0 = 5.26 */
  --auth-fill: linear-gradient(100deg, #0f6ad0 0%, #315fe9 55%, #7041ff 100%);
}

#login .road-motion {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  overflow: hidden;
}

/* Make sure actual login content stays above animation */
#login > *:not(.road-motion) {
  position: relative;
  z-index: 2;
}

/* LEFT SIDE */
.road-arrows-left {
  position: absolute;
  left: -40px;
  top: 55%;
  display: flex;
  gap: 35px;

  font-family: "Inter", sans-serif;
  font-size: 70px;
  font-weight: 900;

  color: #4f8cff;
  text-shadow:
    0 0 8px #4f8cff,
    0 0 20px #4f8cff,
    0 0 40px rgba(79, 140, 255, 0.8);

  animation: roadRushLeft 1.2s linear infinite;
}
/* The title screen's wordmark used to be a second, near-duplicate
   implementation here (.speed-brand-logo / -race / -for / -line / -speed):
   same font, same weight, same skew and same structure as the login hero,
   but with its own tracking, its own FOR size and its own gradient stops.
   Both screens render .rfs-brand now (see BRAND LOCKUP, below) — one
   geometry, two scale variants, two ink variants. */
/* RIGHT SIDE */
.road-arrows-right {
  position: absolute;
  right: -40px;
  top: 55%;
  display: flex;
  gap: 35px;

  font-family: "Inter", sans-serif;
  font-size: 70px;
  font-weight: 900;

  color: #ff3d9a;
  text-shadow:
    0 0 8px #ff3d9a,
    0 0 20px #ff3d9a,
    0 0 40px rgba(255, 61, 154, 0.8);

  animation: roadRushRight 1.2s linear infinite;
}

/* LEFT arrows rush outward */
@keyframes roadRushLeft {
  from {
    transform: translateX(0) scaleX(1);
    opacity: 0;
  }

  15% {
    opacity: 1;
  }

  85% {
    opacity: 1;
  }

  to {
    transform: translateX(-500px) scaleX(1.25);
    opacity: 0;
  }
}

/* RIGHT arrows rush outward */
@keyframes roadRushRight {
  from {
    transform: translateX(0) scaleX(1);
    opacity: 0;
  }

  15% {
    opacity: 1;
  }

  85% {
    opacity: 1;
  }

  to {
    transform: translateX(500px) scaleX(1.25);
    opacity: 0;
  }
}
#login > * {
  position: relative;
  z-index: 1;
}

/* centering column: the title + sign-in card stay optically centred in
   whatever room is left between the top bar and the footer, on every
   viewport (phone, tablet, desktop, landscape). It grows to fill the
   free space but never shrinks, so when the content is taller than the
   screen it keeps its natural height and #login scrolls instead of
   clipping the card. */

/* (the `#login .title .ttl-accent` selector that used to lead this group
   named an element that no longer exists in the markup) */
#login-topbar {
  position: absolute;
  top: calc(24px + env(safe-area-inset-top));
  left: calc(16px + env(safe-area-inset-left));
  right: calc(16px + env(safe-area-inset-right));
  display: flex;
  justify-content: flex-end;
  align-items: center;
  z-index: 2;
}

/* line-art wallet mark; inherits the pill's text colour so it works
   on both the light login button and the dark in-game chip */
.wallet-ico .wallet-svg {
  display: block;
  width: 1.25em;
  height: 1.25em;
}

/* the shared .btn gradient opens on cyan, which goes chalky on a white
   card — the sign-in button runs blue -> violet instead, in white ink */
#login #login-btn {
  color: #fff;
  margin-top: 2px;
  filter: drop-shadow(0 10px 20px rgba(64, 86, 226, 0.35));
}

#login #login-btn::before {
  /* was a second hardcoded blue->violet ramp opening on #2f6bff. Two IDs
     beat .auth-submit-btn::before, so the card had two CTA fills that only
     looked alike — and this one kept the low-contrast first stop. */
  background: var(--auth-fill);
}

#login #login-btn:hover,
#login #login-btn:focus-visible {
  filter: drop-shadow(0 12px 24px rgba(64, 86, 226, 0.45)) brightness(1.08);
}

/* ---------- GARAGE (vehicle showroom) ---------- */
#garage {
  z-index: 30;
  background: #02030a;
  gap: 0;
  /* padding:0 is deliberate — #garage-head owns the top inset and
     #garage-grid owns the bottom one, because both bleed to the edges */
  padding: 0;
  min-height: 100svh; /* same box in both toolbar states — see html,body */
  justify-content: flex-start;
}

#garage.hidden {
  display: none;
}

/* --- neon showroom backdrop: a single pre-rendered plate (garaze.png)
   that already contains the podium, its light ring and the wet floor. --- */
#garage-bg {
  /* How far the plate is lifted above the viewport's top edge. The box is
     grown upward (not translated) so `cover` still fills the screen —
     there is no bare strip left at the bottom. garage.js reads this box
     back with getBoundingClientRect(), so the podium (and the car parked
     on it) rides up with the plate. Tune this one number. */
  --garage-bg-lift: 140px;

  position: absolute;
  inset: calc(-1 * var(--garage-bg-lift)) 0 0 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;

  /* Desktop background */
  /* WebP: the same plate at 252 KB instead of 1.8 MB (86% smaller). The
     PNG stays as the fallback layer beneath for any browser without WebP —
     image-set picks the first it understands, so nothing is downloaded
     twice. garage.js reads this background-image, so keep the url() last. */
  background: #04070f image-set(url("garaze.webp") type("image/webp"), url("garaze.png") type("image/png")) no-repeat 50% 50% / cover;
}

/* =========================
PORTRAIT (phones + tablets held upright)
=========================

Keyed on the viewport's shape, not its width: `cover` fits the plate by its
SHORT axis, so putting the landscape plate in a taller-than-wide box blows
the podium up far wider than the screen (an iPad in portrait rendered a
~1100px podium on an 820px viewport). The portrait plate is the one whose
aspect matches, so it keeps the podium on screen at a sane size.

No `scale` zoom here — garage.js reads this background-image and
background-position back to work out where the podium lands, and a zoom just
crops floor away for no gain.

The box is the viewport plus --garage-bg-lift, so it turns taller-than-wide
BEFORE the viewport does: a 794x786 window already fitted the landscape
plate by its height and pushed an 860px podium across a 794px screen, while
the 3-column stage starved the canvas — the car got cropped at its edges.
13/10 is the shape at which the podium comes back under the viewport and
the canvas keeps ~440px (1024x768 stays on the desktop layout). The same
ratio keys the stacked stage below — change both together. */

@media (max-aspect-ratio: 13 / 10) {
  #garage-bg {
    --garage-bg-lift: 0px; /* portrait plate already fits — no lift */

    background-image: image-set(url("garage-mobile.webp") type("image/webp"), url("garage-mobile.png") type("image/png"));

    background-position: 50% 50%;
    background-size: cover;
    background-repeat: no-repeat;
  }
}

/* darken the edges so the tabs, stats and cards stay readable on top */
#garage-bg::after {
  content: "";
  position: absolute;
  /* pinned to the viewport, not the lifted plate, so the edge darkening
     still lands on the visible area */
  inset: var(--garage-bg-lift) 0 0 0;
  background:
    linear-gradient(
      180deg,
      rgba(2, 4, 12, 0.62) 0%,
      rgba(2, 4, 12, 0.12) 22%,
      transparent 45%,
      rgba(2, 4, 12, 0.35) 82%,
      rgba(2, 4, 12, 0.72) 100%
    ),
    radial-gradient(
      110% 85% at 50% 46%,
      transparent 45%,
      rgba(0, 0, 0, 0.3) 80%,
      rgba(0, 0, 0, 0.5) 100%
    );
}

#garage > *:not(#garage-bg) {
  position: relative;
  z-index: 1;
}

#garage-head {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--sp-5);
  /* the header owns the safe-area top inset — #garage sets padding:0 */
  padding: calc(var(--sp-5) + env(safe-area-inset-top))
    clamp(20px, 4vw, 56px) var(--sp-2);
}

#garage-head #garage-tabs {
  justify-self: center;
}

/* the page-title step of the heading scale: clearly a rank below the
   menu's .rfs-brand--hero wordmark (GARAGE is a subpage), but on the
   same ladder rather than an unrelated hand-picked 22-34px. */
#garage-head .g-title {
  justify-self: start;
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: var(--fs-page);
  font-weight: 900;
  letter-spacing: var(--ls-title);
  text-transform: uppercase;
  background: linear-gradient(100deg, #8ff8ff 0%, #4f8cff 52%, #6a3bff 115%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

#garage-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  max-width: 100%;
}

.gtab {
  pointer-events: auto;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font:
    700 var(--fs-btn-sm) / 1 "Segoe UI",
    system-ui,
    sans-serif;
  letter-spacing: var(--ls-btn-sm);
  /* the tabs are the garage's navigation — a real touch target, not
     whatever height 7px of padding around a glyph happened to give */
  min-height: var(--h-sm);
  color: #cdd6ff;
  background: rgba(255, 255, 255, 0.05);
  border: 1.5px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--r-pill);
  /* trimmed from 9px: the taller icon now sets the pill's height, so the
     old vertical padding would have made the row noticeably chunkier.
     Horizontal padding scales down below ~1250px: at a flat 20px the four
     tabs wrapped onto a second row and cost 40-48px of stage height. */
  padding: 7px clamp(8px, 1.6vw, 20px);
  transition: 0.15s;
}

/* stroke is currentColor, so the glyph inverts with the pill when active.
   The stroke is scaled down as the box grows so a bigger glyph does not
   read as a heavier one. */
.gtab-ico {
  width: 24px;
  height: 24px;
  flex: 0 0 auto;
  stroke-width: 1.5;
  opacity: 0.9;
}

.gtab.active .gtab-ico {
  opacity: 1;
}

.gtab.active {
  color: #05010f;
  background: var(--cyan);
  border-color: var(--cyan);
  box-shadow: 0 0 18px var(--cyan);
}

#garage-stage {
  position: relative;

  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
  display: grid;

  /*
* Keep the center area fixed and let the
* left/right areas take the remaining space.
*/
  grid-template-columns:
    minmax(220px, 1fr)
    minmax(0, 900px)
    minmax(220px, 1fr);

  grid-template-rows:
    auto
    minmax(0, 1fr)
    auto
    auto;

  /* actions span all three columns: penned into the middle one they wrapped
     into two or three rows on ~1024px screens and landed on top of the car. */
  grid-template-areas:
    "name    name    name"
    "stats   canvas  paint"
    "stats   canvas  paint"
    "actions actions actions";

  align-items: center;
  justify-items: center;

  column-gap: var(--sp-5);
  row-gap: var(--sp-1);

  padding: clamp(10px, 2.5vw, 24px) clamp(20px, 5vw, 70px) var(--sp-3);

  box-sizing: border-box;
}

#garage-canvas {
  grid-area: canvas;

  /* alignToPodium() translates the canvas down to seat the car on the
     painted podium, which pushes its box over the actions row. Nothing
     is bound to the canvas, so it stays out of hit-testing entirely. */
  pointer-events: none;

  width: 100%;
  max-width: 900px;

  height: 100%;
  max-height: min(50vh, 460px);

  align-self: center;
  justify-self: center;
  display: block;
  margin: 0;
}

/* section-title step: the item inside the page, so it sits one rank
   below the GARAGE page title instead of competing with it */
#garage-name {
  position: relative;
  grid-area: name;
  justify-self: center;
  font-size: var(--fs-section);
  font-weight: 900;
  letter-spacing: var(--ls-title);
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-bottom: 10px;
}

#garage-name::after {
  content: "";
  position: absolute;
  left: 6%;
  right: 6%;
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(90, 190, 255, 0.75) 22%,
    rgba(200, 235, 255, 0.95) 50%,
    rgba(190, 90, 255, 0.75) 78%,
    transparent 100%
  );
  box-shadow: 0 0 14px rgba(120, 170, 255, 0.55);
}

#garage-paint {
  grid-area: paint;

  width: min(300px, 100%);

  justify-self: end;
  align-self: end;

  margin-right: 0;
}

#garage-stats {
  grid-area: stats;

  width: min(260px, 100%);

  justify-self: start;
  align-self: start;

  margin-top: clamp(6px, 3vh, 30px);
  margin-left: 0;

  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.gstat {
  display: grid;
  /* minmax(0, ...) on the label and value: when the row is tight those two
     give way so the bar keeps its 60px, instead of the bar collapsing to a
     stub in the narrow left column of a ~1024px screen */
  grid-template-columns:
    minmax(0, clamp(58px, 8vw, 82px))
    minmax(60px, 1fr)
    minmax(0, clamp(48px, 6vw, 64px));
  align-items: center;
  gap: clamp(6px, 1.2vw, 10px);
}

/* size/tracking come from the .ui-label group. The old
   clamp(8px, 0.8vw, 10px) collapsed to its 8px MINIMUM at every tablet
   width, which is why TOP SPEED / ACCEL read smaller than every other
   caption on the screen. */
.gstat .gk {
  opacity: 0.65;
  white-space: nowrap;
}

.gstat .gbar {
  height: 7px;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.12);
  overflow: hidden;
}

.gstat .gbar i {
  display: block;
  height: 100%;
  border-radius: 5px;
}

.gstat .gv {
  font-size: clamp(11px, 1.1vw, 13px);
  font-weight: 800;
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

#garage-grid {
  width: 100%;
  flex: 0 0 auto;
  display: flex;
  gap: clamp(8px, 1.2vw, 14px);
  overflow-x: auto;
  overflow-y: hidden;
  touch-action: pan-x;
  /* top padding leaves room for the .gcard:hover lift + glow, which
     overflow-y:hidden would otherwise clip off the top edge.

     The BOTTOM padding is what stops the strip's last few pixels — the
     MPH line — being cut off by the viewport edge: #garage-grid is the
     screen's last row and #garage sets padding:0, so at `0` the cards
     ended exactly ON the bottom edge and any browser chrome or home
     indicator ate into them. */
  padding: var(--sp-2) 10px calc(var(--sp-2) + env(safe-area-inset-bottom));
  margin-top: 0px;
  flex-wrap: nowrap;
  /* "safe" keeps the strip centered when the cars fit, but falls back to
     start-alignment on overflow — plain `center` pushes the first card
     into unreachable negative scroll space. */
  justify-content: safe center;
  scrollbar-width: none;
  -ms-overflow-style: none;
  cursor: grab;
  mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 30px,
    #000 calc(100% - 30px),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 30px,
    #000 calc(100% - 30px),
    transparent 100%
  );
}

#garage-grid::-webkit-scrollbar {
  display: none;
}

#garage-grid.dragging {
  cursor: grabbing;
}

.gcard {
  position: relative;
  pointer-events: auto;
  cursor: pointer;
  width: clamp(108px, 10vw, 150px);
  height: clamp(108px, 10vw, 150px);
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 0;
  /* The thumbnails used to bake in their own studio backdrop, which
     only covered the top ~60% of the square card and left a visible
     band of card colour under every car. They are transparent PNGs of
     the vehicle now (_gen_thumbs2.mjs), so the card paints one
     gradient across its whole face -- garage.js re-uses --gcard-bg as
     the layer under the car so nothing seams. */
  --gcard-bg: linear-gradient(180deg, #12131a 0%, #05050a 100%);

  background-color: #05050a;
  background-image: var(--gcard-bg);
  /* two background-image layers get set in garage.js (car PNG, then
     --gcard-bg) -- size/position/repeat below are matching
     comma-separated lists, car layer first, gradient layer second, so
     the car can be sized up independently of the backdrop. */
  background-size:
    165% auto,
    100% 100%;
  background-position:
    center -84%,
    center 0%;
  background-repeat: no-repeat, no-repeat;
  border: 1px solid rgba(19, 241, 255, 0.35);
  border-radius: var(--r-md);
  transition: 0.15s;
  box-shadow:
    0 0 10px rgba(19, 241, 255, 0.18),
    inset 0 0 18px rgba(19, 241, 255, 0.05),
    0 4px 14px rgba(0, 0, 8, 0.35);
  overflow: hidden;
  box-sizing: border-box;
}

/* dark gradient overlay behind the bottom text band — sits above the
   car image (background-image on .gcard) but below the text. */
.gcard::after {
  content: "";
  position: absolute;
  inset: 40% 0 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(0, 0, 0, 0.72) 45%,
    rgba(0, 0, 0, 0.96) 100%
  );
}

.gcard:hover {
  border-color: rgba(19, 241, 255, 0.65);
  box-shadow:
    0 0 16px rgba(19, 241, 255, 0.35),
    inset 0 0 18px rgba(19, 241, 255, 0.08),
    0 4px 14px rgba(0, 0, 8, 0.35);
  transform: translateY(-2px);
}

.gcard.active {
  border-color: var(--cyan);
  box-shadow:
    0 0 22px rgba(19, 241, 255, 0.55),
    inset 0 0 22px rgba(19, 241, 255, 0.12);
}

/* Every card has the same three-part internal structure — image (the
   card's own background), NAME, STAT — and the stat must start at the
   same vertical position on all of them whether the name took one line
   or two. .gcard-name reserves two lines' worth either way; the text
   block is a column pinned to the bottom of the card so the stat can
   never be pushed past the card's edge. */
.gcard-text {
  position: relative;
  z-index: 2;
  width: 100%;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  box-sizing: border-box;
  padding: var(--sp-1) var(--sp-1) 6px;
  text-align: center;
}

.gcard-name {
  width: 100%;
  font-size: clamp(10px, 1.05vw, 12px);
  font-weight: 800;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: #fff;
  line-height: 1.3;
  /* exactly two lines, always: BUGATTI CHIRON wraps and FERRARI 458 does
     not, and without a reserved box the one-liners floated their MPH up
     to a different height than the two-liners. min-height rather than a
     hard height so a font-size override in a breakpoint cannot make the
     box shorter than the text it has to hold. */
  min-height: 2.6em;
  flex: 0 0 auto;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: break-word;
}

.gcard-stat {
  width: 100%;
  /* was clamp(9px, 0.95vw, 10.5px) — the 10.5px was the only half-pixel
     size in the sheet, and 9px on a tablet is under the readability floor */
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.3px;
  color: var(--cyan);
  /* never squeezed away: the stat line keeps its own height even when
     the name runs long, which is what clipped 245 MPH on the McLaren */
  flex: 0 0 auto;
  min-height: 1.3em;
  line-height: 1.3;
  margin-top: var(--sp-1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#garage-actions {
  grid-area: actions;
  /* above the translated canvas, which is later in the DOM */
  position: relative;
  z-index: 3;
  flex: 0 0 auto;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  /* the buttons are slanted parallelograms and grow to 1.06 on hover,
     so a small gap let the hovered one slide under its neighbour --
     keep enough room for the slant plus the hover scale */
  gap: var(--sp-7);
  padding: var(--sp-1) 0;
}

/* SELECT is the primary, SOUND and BACK are secondaries — but all three
   are one row of the same control, so they share a height and a minimum
   width. Letting the label alone size the box is what made BACK a stub
   next to SELECT. --btn-h keeps them on one baseline; min-width keeps
   them on one rhythm; the label still centres inside whatever it gets. */
#garage-actions .btn {
  --btn-h: var(--h-md);
  min-width: 132px;
  font-size: var(--fs-btn-sm);
  padding: 0 var(--sp-6);
}

/* SELECT reads as the primary by weight and fill (it is the only one
   without .alt), not by being wider than its neighbours */
#garage-actions #garage-select {
  min-width: 148px;
}

/* a hovered/pressed button scales up: lift it so it never renders
   beneath the button next to it */
#garage-actions .btn:hover,
#garage-actions .btn:active,
#garage-actions .btn:focus-visible {
  z-index: 1;
}

#garage-paints {
  grid-area: paint;
  justify-self: end;
  align-self: end;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: clamp(5px, 0.8vw, 7px);
  max-width: 100%;
  padding: 4px 0;
}

#garage-paints .gp-label {
  opacity: 0.55;
  margin-right: var(--sp-1);
  white-space: nowrap;
}

.gpaint {
  pointer-events: auto;
  cursor: pointer;
  flex: 0 0 auto;
  width: clamp(16px, 1.2vw, 22px);
  height: clamp(16px, 1.2vw, 22px);
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.25);
  transition: 0.12s;
}

.gpaint:hover {
  transform: scale(1.15);
}

.gpaint.active {
  border-color: #fff;
  box-shadow: 0 0 12px currentColor;
  transform: scale(1.12);
}

.gpaint.stock {
  background: conic-gradient(#e33 0 25%, #3ae 0 50%, #ee3 0 75%, #3e5 0);
  font-size: 0;
}

/* desktop from ~900px up: keep PAINT + every swatch on one line. The row is
   justify-self:end in its grid column, so a max-content width spills
   left over the canvas gutter (canvas is pointer-events:none) instead
   of wrapping. Narrower/stacked layouts keep the wrapping default. */
@media (min-width: 900px) and (min-aspect-ratio: 1 / 1) {
  #garage-paints {
    flex-wrap: nowrap;
    width: max-content;
    max-width: none;
  }
}

/* ---------- MOBILE ---------- */
@media (max-width: 640px) {
  .screen {
    gap: 14px;
    /* extra top clearance: #wallet-chip is a fixed top-right pill shown
       on every screen, and would otherwise sit on top of each screen's
       heading on narrow devices */
    --screen-pad-r: 12px;
    /* bottom clearance: #mute is pinned 18px up the bottom-right corner,
       40px tall. Scrolling screens (settings, create room/pot, help) end
       their last row exactly at this inset, so the chip sat on BACK. */
    --screen-pad-b: calc(58px + env(safe-area-inset-bottom));
    --screen-pad-l: 12px;
  }

  /* screens whose last row is a single centred button never reach the
     corner the chip lives in, and the login strip is pinned to this var;
     they keep the tight inset so a 548px viewport still fits them unscrolled */
  #login,
  #title,
  #crash,
  #results {
    --screen-pad-b: calc(12px + env(safe-area-inset-bottom));
  }

  /* these two carry their own hard-coded padding instead of the vars */
  #settings-screen,
  #help-screen,
  #wallet-screen,
  #chal-mine,
  #history {
    padding-bottom: calc(58px + env(safe-area-inset-bottom));
  }

  /* mode cards become LIST TILES on a phone: icon on the left, title and
     description on the right, one per row. Three 100px-wide upright cards
     in a row squeezed "PLAY & CREATE CHALLENGE" into 10px type and hid the
     descriptions; a 64px tile keeps every word and is a full-width thumb
     target. The stack is 3 × ~64px, so it still fits a 568px viewport. */
  .mp-cards {
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 8px;
    width: 100%;
  }

  .mp-card {
    width: 100%;
    flex: 0 0 auto;
    display: grid;
    grid-template-columns: 34px minmax(0, 1fr);
    column-gap: 12px;
    row-gap: 2px;
    align-items: center;
    text-align: left;
    padding: 10px 14px;
    min-height: var(--h-md);
  }

  .mp-card .mp-icon {
    grid-row: 1 / span 2;
    font-size: 22px;
    text-align: center;
  }

  .mp-card .mp-card-title {
    grid-column: 2;
    font-size: 12px;
    letter-spacing: 0.6px;
  }

  .mp-card .mp-card-desc {
    grid-column: 2;
    display: block;
    font-size: 11px;
    line-height: 1.4;
  }

  /* lobby (BATCH STARTING / WAITING FOR PLAYERS): the heading itself now
     stays on the shared page-title scale (--fs-page already comes down to
     24px here) — only the countdown/list below still need phone tightening */
  #countdown {
    font-size: 44px;
  }

  #countdown.waiting-text {
    font-size: 15px;
    letter-spacing: 1.5px;
  }

  #lobby-sub {
    font-size: 11px;
    letter-spacing: 1.5px;
  }

  /* race settings: single column, thumb-friendly, no heavy blur cost */
  .rs-header {
    margin-top: 30px;
  }

  .rs-body {
    grid-template-columns: 1fr;
    gap: 12px;
  }

  .rs-card {
    padding: 18px 14px;
    border-radius: var(--r-md);
    backdrop-filter: none;
  }

  #race-settings #weather-slot-mp .env-chip {
    padding: 12px 16px;
    flex: 1 1 auto;
  }

  .mp-wide-btn {
    width: auto;
  }

  #lobby .dur-chip {
    font-size: 10px;
    height: 30px;
    padding: 0 14px;
    letter-spacing: 0.8px;
  }

  /* MAP / RACE TIME / SPEED become collapsible icon-led setting cards
     on phone — same collapsed-button-plus-panel pattern as the weather
     picker (.dd / .dd-btn / #env-bar) above, generalized so it can
     wire up any number of these via JS instead of one hardcoded
     dropdown, restyled as a stat-card row (icon · caption+value · chevron). */
  #lobby {
    gap: 10px;
  }

  .chip-dd {
    width: 100%;
    max-width: 340px;
  }

  .chip-dd-btn {
    display: flex;
    width: 100%;
    pointer-events: auto;
    cursor: pointer;
    align-items: center;
    gap: 12px;
    text-align: left;
    background: rgba(18, 16, 34, 0.6);
    border: 1px solid rgba(160, 180, 255, 0.16);
    border-radius: var(--r-md);
    padding: 11px 16px;
  }

  .chip-dd-icon {
    display: flex;
    font-size: 17px;
    flex-shrink: 0;
    color: #fff;
    opacity: 0.9;
  }

  .chip-dd-icon svg {
    width: 18px;
    height: 18px;
  }

  .chip-dd-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
  }

  .chip-dd-caption {
    display: block;
    font-family: "Inter", sans-serif;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1.5px;
    color: #a99fc4;
  }

  .chip-dd-cur {
    display: block;
    font-family: "Inter", sans-serif;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.5px;
    color: #fff;
  }

  .chip-dd .dd-chev {
    flex-shrink: 0;
    font-size: 13px;
    color: #a99fc4;
  }

  .chip-dd #map-bar,
  .chip-dd #dur-bar,
  .chip-dd #solo-dur-bar,
  .chip-dd #acc-bar,
  .chip-dd #solo-acc {
    display: none !important;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 5;
    flex-wrap: wrap;
    padding: 10px;
    border-radius: var(--r-md);
    background: rgba(10, 8, 24, 0.95);
    backdrop-filter: blur(10px);
    border: 1px solid rgba(160, 180, 255, 0.25);
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45);
  }

  .chip-dd.open #map-bar,
  .chip-dd.open #dur-bar,
  .chip-dd.open #solo-dur-bar,
  .chip-dd.open #acc-bar,
  .chip-dd.open #solo-acc {
    display: flex !important;
  }

  .chip-dd #map-bar .tlabel,
  .chip-dd #dur-bar .tlabel,
  .chip-dd #solo-dur-bar .tlabel,
  .chip-dd #acc-bar .tlabel {
    display: none;
  }

  .chip-dd.open .dd-chev {
    transform: rotate(180deg);
  }

  .invite-card {
    max-width: 300px;
    padding: 10px 12px;
  }

  .invite-card-code {
    font-size: 20px;
    letter-spacing: 5px;
  }

  .invite-card-btn {
    font-size: 10px;
    padding: 7px 8px;
  }

  #lobby-list {
    /* .pl-row below is shorter here (smaller padding + font) — the only
       thing the three-row cap needs told. */
    --pl-row-h: 29px;
    min-width: 0;
    width: 100%;
    max-width: 320px;
  }

  .pl-row {
    padding: 6px 12px;
    font-size: 12px;
  }

  /* icon-only pills — the full "ONLINE" / "CONNECT WALLET" text was
     wide enough to overlap the title on narrow screens */
  .online-label,
  .wallet-label {
    display: none;
  }

  #login-online,
  #login-wallet-btn {
    padding: 7px 10px;
  }

  #login-online {
    gap: 4px;
    display: none;
  }

  #login-wallet-btn .wallet-ico,
  #wallet-chip .wallet-ico {
    display: inline-flex;
    align-items: center;
  }

  /* icon-only chip: only the disconnected state carries a
     .wallet-label, so a connected chip still shows its balance */
  #wallet-chip:has(.wallet-label) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 7px 12px;
    font-size: 19px;
  }

  /* #wallet-chip is a global top-right pill shown on every screen
     (including login) whenever betting is enabled — its full text
     ("CONNECT WALLET" / balance+address) was wide enough to overlap
     the title on narrow screens. */
  :root {
    --chips-top: calc(20px + env(safe-area-inset-top));
    --chips-right: calc(10px + env(safe-area-inset-right));
    --chips-h: 40px;
  }

  #top-right-chips {
    gap: 8px;
  }

  #wallet-chip {
    font-size: 10px;
    padding: 0 var(--sp-3);
    max-width: 46vw;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  /* the screen's --screen-pad-t already reserves 52px for the fixed
     wallet-chip pill, so the stack can stay vertically centred; `safe`
     keeps it pinned to the top (never clipped) when it overflows, e.g.
     with the settings panel open on a short device */
  #title {
    justify-content: safe center;
    /* every break in the menu rhythm scales with the phone's HEIGHT: the
       fixed --sp steps left a tall phone with a tight cluster and two big
       empty bands. The floors are the old fixed values, so a short phone
       (iPhone SE) is unchanged; the ceilings stop a tablet-tall phone
       from drifting apart. */
    gap: clamp(8px, 2vh, 18px);
  }

  #title #hello {
    margin-top: clamp(12px, 3vh, 28px);
    margin-bottom: clamp(12px, 3vh, 28px);
  }

  #title .menu-tiles {
    margin-top: clamp(4px, 3vh, 28px);
  }

  #title .btn.tile {
    gap: clamp(8px, 1.6vh, 16px);
  }

  #title .tile-ico {
    width: clamp(40px, 6.5vh, 56px);
    height: clamp(40px, 6.5vh, 56px);
  }

  #title .btn-row:has(#exit-btn) {
    margin-top: clamp(20px, 6vh, 56px);
  }

  #login-main {
    gap: var(--sp-4);
  }

  /* phone drops to the small step of the button ladder — but keeps the
     44px --btn-h touch target, which the old flat 12px/22px padding did
     not guarantee once a label got short */
  .btn {
    font-size: var(--fs-btn-sm);
    letter-spacing: var(--ls-btn-sm);
    padding: 0 var(--sp-5);
  }

  .mp-wide-btn {
    width: auto;
  }

  .btn-row {
    gap: var(--sp-2);
  }

  /* the three mode tiles are one row on every phone: icon + label, no
     caption. With captions they only fit two across on a 393px screen
     (BET & PLAY dropped to its own row) and one across on a 320px one. */
  #title .menu-tiles {
    flex-wrap: nowrap;
    width: 100%;
  }

  .btn.tile {
    flex: 1 1 0;
    min-width: 0;
    padding: var(--sp-2) 4px;
  }

  .tile-ico {
    width: 40px;
    height: 40px;
    border-radius: 11px;
  }

  .tile-label {
    font-size: 11px;
    letter-spacing: 1.2px;
  }

  .tile-sub {
    display: none;
  }

  /* the hero CTA steps down on a phone but stays the largest control on
     the screen; !important only because the old markup carried an inline
     style here — that inline pair is gone now (see index.html), so this
     is a plain size override on .btn--lg */
  #battle-btn {
    font-size: 15px;
    padding: 0 var(--sp-7);
  }

  .hint {
    font-size: 10px;
    letter-spacing: 1px;
    padding: 0 10px;
  }

  .hint-keys {
    gap: 6px;
    padding: 7px 14px;
    letter-spacing: 1.6px;
  }

  .hint-keys kbd {
    min-width: 22px;
    height: 19px;
    font-size: 10px;
  }

  #env-bar {
    gap: 5px;
  }

  .env-chip {
    font-size: 11px;
    padding: 4px 9px;
  }

  .name-in {
    width: 200px;
    font-size: 14px;
  }

  #login .auth-card {
    padding: 18px 18px;
  }

  #login #auth-form input {
    font-size: 15px;
    padding: 0 12px;
    border-radius: var(--r-md);
  }

  #login #auth-form input#pin-in {
    font-size: 18px;
    letter-spacing: 10px;
  }

  .corner {
    padding: 0 12px;
    top: calc(12px + env(safe-area-inset-top));
  }

  .value {
    font-size: 26px;
  }

  #best-wrap {
    top: calc(90px + env(safe-area-inset-top));
    z-index: 12;
  }

  #best-wrap .label,
  #best-wrap .value {
    opacity: 1;
    text-shadow:
      0 0 8px #000,
      0 0 4px #000;
  }

  #nitro-bar {
    width: 90px;
  }

  #leaderboard {
    width: 150px;
    top: calc(96px + env(safe-area-inset-top));
    right: calc(8px + env(safe-area-inset-right));
  }

  .lb-row {
    font-size: 11px;
    padding: 4px 7px;
  }

  #garage {
    overflow: hidden;
  }

  #garage-head {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    padding: calc(var(--sp-3) + env(safe-area-inset-top)) var(--sp-3)
      var(--sp-1);
    gap: var(--sp-3);
  }

  #garage-head .g-title,
  #garage-head #garage-tabs {
    justify-self: auto;
  }

  /* --fs-page already bottoms out at 24px here; the hand-set 18px was
     the only thing keeping GARAGE off the shared heading scale */
  #garage-head .g-title {
    letter-spacing: var(--ls-title);
  }

  #garage-tabs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 100%;
  }

  .gtab {
    font-size: 11px;
    padding: 7px 14px;
    text-align: center;
    gap: 6px;
  }

  .gtab-ico {
    width: 20px;
    height: 20px;
  }

  /* phone: stack name / stats / paint / turntable / actions in a single
   column so nothing ever has to share a row and overlap. SELECT / SOUND /
   BACK sit at the BOTTOM, directly under the podium: they act on the car,
   so they belong under it rather than wedged between its name and stats. */
  #garage-stage {
    grid-template-columns: 1fr;
    /* the turntable is the only elastic row. With all-auto rows the canvas
       kept its own height and overflowed the stage, which pushed the paint
       swatches under the card strip (and clean off a 640px-tall screen).
       The portrait plate's aspect matches a phone, so `cover` has no
       vertical slack and the podium stays at PLATES["garage-mobile"].cy of
       the screen (~67%): the actions row below the canvas sits under it. */
    grid-template-rows: auto auto auto minmax(0, 1fr) auto;

    grid-template-areas:
      "name"
      "stats"
      "paint"
      "canvas"
      "actions";

    row-gap: 10px;
  }
  #garage-canvas {
    width: 100%;
    max-width: 100%;
    height: 100%;
    min-height: 150px;
    max-height: none;
    align-self: stretch;
  }

  #garage-name {
    letter-spacing: var(--ls-title);
  }

  #garage-stats {
    width: 100%;
    max-width: 320px;
    justify-self: center;
    margin-top: 4px;
  }

  .gstat {
    grid-template-columns: 64px 1fr 56px;
    gap: 6px;
  }

  #garage-paints {
    justify-self: center;
    justify-content: center;
    gap: 6px;
  }

  .gpaint {
    width: 19px;
    height: 19px;
  }

  #garage-grid {
    margin-top: 14px;
  }

  .gcard {
    width: 74px;
    height: 96px;
    padding: 6px 4px;
    background-size:
      120% auto,
      100% 100%;
    background-position:
      center 6%,
      center 0%;
  }

  #garage-actions {
    gap: var(--sp-2);
    width: 100%;
  }

  /* three buttons have to share a phone's width, so the minimum width
     drops out and they flex instead — the shared height stays, so the
     row is still one baseline and still a legal touch target */
  #garage-actions .btn,
  #garage-actions #garage-select {
    min-width: 0;
    flex: 1 1 0;
    font-size: clamp(10px, 3vw, 12px);
    padding: 0 clamp(6px, 2.4vw, 16px);
  }

  #race-timer {
    font-size: 22px;
  }

  #horn-btn,
  #nitro-btn {
    font-size: 12px;
    padding: 10px 16px;
  }

  #nitro-btn {
    left: calc(50% + 8px);
    right: auto;
    transform: none;
  }

  #horn-btn {
    left: calc(50% - 8px);
    transform: translateX(-100%);
  }

  #horn-btn:active {
    transform: translateX(-100%) scale(0.94);
  }
}

/* =========================
TABLET HELD UPRIGHT (portrait, wider than a phone)
=========================

These screens take the portrait plate above but were still laid out by the
desktop 3-column stage, which parked the stats in the far top-left corner
and dropped the paint row on top of the podium. They also inherited the
desktop's vw-based type scale, which at ~820px collapses every clamp() to
its MINIMUM — the stat labels rendered at 8px. So: stack the stage like the
phone does, and pin the type to real sizes instead of viewport width.

Keyed on the same 13/10 as the portrait-plate swap above: the stacked stage
and the portrait plate go together (this block's `scale` is tuned for that
plate), and a near-square landscape window has the same problem — see the
note on the plate swap. */

@media (min-width: 641px) and (max-aspect-ratio: 13 / 10) {
  /* the portrait plate's podium spans ~93% of its width (PLATES pw), so
     `cover` already draws it wide — no zoom, or it crops at both edges.
     The plate is taller than a tablet box, so seatPlate() has slack to
     seat the podium in the turntable row. */
  #garage {
    overflow: hidden;
  }

  #garage-head {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-3);
    padding: calc(var(--sp-4) + env(safe-area-inset-top)) var(--sp-6)
      var(--sp-2);
  }

  #garage-head .g-title,
  #garage-head #garage-tabs {
    justify-self: auto;
  }

  #garage-tabs {
    justify-content: center;
    flex-wrap: nowrap;
  }

  #garage-stage {
    grid-template-columns: 1fr;
    /* see the phone block: only the turntable row flexes, so the stage
       always fits and the paint swatches stay above the card strip */
    grid-template-rows: auto auto minmax(0, 1fr) auto auto;

    /* SELECT / SOUND / BACK live at the BOTTOM of the stage, directly
       above PAINT. They act on the car, so they read as one control band
       with the swatches under the turntable, instead of splitting the
       car's name from its own stats the way they did between rows 2 and 3. */
    grid-template-areas:
      "name"
      "stats"
      "canvas"
      "actions"
      "paint";

    row-gap: var(--sp-5);
    padding: var(--sp-5) clamp(24px, 5vw, 64px) var(--sp-3);
  }

  /* the stat block reads as part of the car's name card above it, so it
     sits closer to the name than the stage's default row gap */
  #garage-stage #garage-stats {
    margin-top: 0;
  }

  /* the bottom control band: buttons, then swatches, then the card strip.
     The margins keep the three apart without touching the podium art. */
  #garage-paints {
    margin-top: var(--sp-2);
    margin-bottom: var(--sp-3);
  }

  /* --fs-section resolves to 22px at this width; the hand-set 26px was
     tuned against the old 30px cap and now outranks the page title */

  #garage-stats {
    width: 100%;
    max-width: 420px;
    justify-self: center;
    align-self: center;
    margin-top: 0;
    margin-left: 0;
  }

  .gstat {
    grid-template-columns: 92px minmax(40px, 1fr) 74px;
    gap: 10px;
  }

  /* the 12px that used to be restated here was compensating for the old
     clamp(8px, 0.8vw, 10px) bottoming out at 8px on a tablet. The
     .ui-label token holds a real size at this width now, so the label
     matches every other caption in the app instead of being the one
     that got hand-tuned. */
  .gstat .gv {
    font-size: 15px;
  }

  #garage-canvas {
    width: 100%;
    max-width: 100%;
    height: 100%;
    min-height: 200px;
    max-height: none;
    justify-self: center;
    align-self: stretch;
  }

  #garage-paints {
    justify-self: center;
    align-self: center;
    justify-content: center;
    gap: 10px;
  }

  .gpaint {
    width: 24px;
    height: 24px;
  }

  /* tablet has the room for the full-size label; height and minimum
     width still come from the base rule, so the row stays even */
  #garage-actions .btn {
    font-size: var(--fs-btn);
    padding: 0 var(--sp-7);
  }

  .gcard-name {
    font-size: 13px;
  }
}

/* short landscape (phone on its side): stacked, the wordmark alone eats
   most of the height and pushed the sign-in button below the fold, so
   put the title beside the card and keep the pair centred. */
@media (orientation: landscape) and (max-height: 560px) {
  /* one number instead of three: the lockup's parts are sized in em off
     --brand, so a short landscape viewport only has to restate the scale
     (in vh, since height is what's scarce here) and RACE / FOR / SPEED
     all follow in proportion. */
  .rfs-brand {
    --brand: clamp(26px, 8vh, 52px);
  }

  /* the hero offset is the other half of the overflow: --screen-pad-t was
     retuned here but --hero-top stayed at 75px */
  #login,
  #loading {
    --hero-top: 18px;
  }

  #loading-ring {
    width: clamp(90px, 26vh, 140px);
    height: clamp(90px, 26vh, 140px);
    margin: clamp(10px, 3vh, 20px) 0;
  }

  #loading-tagline {
    margin-top: 6px;
  }

  #loading-tip {
    margin-top: clamp(10px, 3vh, 18px);
    padding: 7px 12px;
  }

  #login,
  #loading {
    --screen-pad-t: calc(14px + env(safe-area-inset-top));
    --screen-pad-b: calc(14px + env(safe-area-inset-bottom));
  }

  /* every other screen is taller than a sideways phone and scrolls from
     the top, where its heading ran under the fixed #wallet-chip, and its
     last row ended under #mute. Reserve both bands. */
  .screen:not(#login):not(#garage) {
    --screen-pad-t: calc(64px + env(safe-area-inset-top));
    --screen-pad-b: calc(64px + env(safe-area-inset-bottom));
  }

  #settings-screen,
  #help-screen,
  #wallet-screen,
  #chal-mine,
  #history {
    padding-top: calc(64px + env(safe-area-inset-top));
    padding-bottom: calc(64px + env(safe-area-inset-bottom));
  }

  /* pinned to the bottom of a screen that scrolls = pinned over whatever
     is scrolled under it (the DRIVE SOLO / BET & PLAY captions). In flow
     it lands after the last row instead. */
  .bet-foot {
    position: static;
    width: 100%;
    margin-top: var(--sp-3);
    padding-right: 0;
  }

  #login-main {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 28px;
  }

  #login .auth-card {
    width: min(52vw, 360px);
    padding: 14px 20px;
  }

  #login #auth-form input {
    padding: 0 12px;
    font-size: 15px;
    border-radius: var(--r-md);
  }

  #login #auth-form input#pin-in {
    font-size: 18px;
    letter-spacing: 10px;
  }

  #login #lg-error {
    min-height: 0;
  }

  /* the PIN-reset warning is the tallest thing in the card; on a screen
     this short it is what pushed ENTER GARAGE off-screen. It still reads
     in full on every other size. */
  #login .auth-info {
    display: none;
  }

  /* ---- GARAGE ----
     The desktop 3-column stage is the right shape for a sideways phone, but
     at its desktop type and paddings the head, name, buttons and card strip
     ate all 390px of height and left the turntable row ~34px tall -- the car
     rendered as a speck under the buttons. Shrink the chrome and hand the
     height back to the canvas row. */
  /* landscape phone: the notch is on the SIDE here, not the top, so the
     header keeps a flat top pad and the screen's side insets do the work */
  #garage-head {
    padding: var(--sp-2) clamp(10px, 2vw, 24px) var(--sp-1);
    gap: var(--sp-3);
  }

  /* height, not width, is what's scarce on a phone laid on its side, so
     the page title is re-derived in vh — still the page-title role, just
     measured against the axis that runs out first */
  #garage-head .g-title {
    font-size: clamp(16px, 4.4vh, 24px);
    letter-spacing: var(--ls-title);
  }

  .gtab {
    min-height: 30px;
    font-size: 11px;
    padding: 5px clamp(7px, 1.2vw, 12px);
    gap: 5px;
  }

  .gtab-ico {
    width: 18px;
    height: 18px;
  }

  #garage-stage {
    padding: 4px clamp(12px, 3vw, 40px) 4px;
    row-gap: 2px;
  }

  #garage-name {
    font-size: clamp(15px, 4.6vh, 22px);
    letter-spacing: var(--ls-title);
    padding-bottom: 5px;
  }

  #garage-stats {
    margin-top: 0;
    gap: 5px;
  }

  .gstat .gbar {
    height: 5px;
  }

  #garage-actions {
    gap: 16px;
    padding: 0;
  }

  /* a phone on its side has ~360px of height for the whole showroom, so
     this is the one place the row is allowed under the 44px floor */
  #garage-actions .btn,
  #garage-actions #garage-select {
    --btn-h: 34px;
    min-width: 104px;
    font-size: 11px;
    padding: 0 var(--sp-4);
  }

  /* one line, spilling left over the (empty, non-interactive) canvas gutter
     rather than wrapping into a block that overhangs the card strip */
  #garage-paints {
    flex-wrap: nowrap;
    width: max-content;
    max-width: none;
    gap: 5px;
  }

  .gpaint {
    width: 15px;
    height: 15px;
  }

  #garage-grid {
    padding-top: 4px;
  }

  .gcard {
    width: 112px;
    height: 86px;
  }

  /* an 86px card cannot hold two lines of name plus the stat, so the
     name clamps to one line here — and the reserved box shrinks to match
     rather than leaving a blank second line above the MPH */
  .gcard-name {
    -webkit-line-clamp: 1;
    line-clamp: 1;
    min-height: 1.3em;
    font-size: 11px;
  }

  .gcard-stat {
    margin-top: 2px;
  }
}

/* short portrait phones (iPhone SE / Safari with both bars): the 2x2 tab
   grid plus the 150px canvas floor added up to ~620px of showroom on a
   548px screen and the car ran into the card strip. One scrolling tab row
   and a lower canvas floor bring it back inside the viewport. */
@media (max-width: 640px) and (max-height: 620px) and (orientation: portrait) {
  #garage-tabs {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    gap: 8px;
  }

  #garage-tabs::-webkit-scrollbar {
    display: none;
  }

  .gtab {
    flex: 0 0 auto;
  }

  #garage-stage {
    row-gap: 6px;
  }

  #garage-canvas {
    min-height: 120px;
  }

  #garage-grid {
    margin-top: 8px;
  }
}

/* 320px-wide phones (iPhone SE 1st gen / 5s): the wordmark and hero CTA
   step down a size, and the eleven paint swatches lose their label so
   they stay on one line. */
@media (max-width: 360px) {
  :root {
    --fs-hero: clamp(38px, 13vw, 46px);
  }

  #battle-btn {
    font-size: 13px;
    padding: 0 var(--sp-5);
  }

  /* 98px per tile: DRIVE SOLO / BET & PLAY wrap at 11px, fit at 10px */
  #title .tile-label {
    font-size: 10px;
    letter-spacing: 1px;
  }

  #garage-paints {
    gap: 4px;
  }

  #garage-paints .gp-label {
    display: none;
  }
}

/* ...and when that phone also shows Safari's bars (~454px of height) the
   showroom has to give up chrome, not the car: tighter head, shorter
   buttons and cards, and a lower floor for the turntable. */
@media (max-width: 640px) and (max-height: 520px) and (orientation: portrait) {
  #garage-head {
    padding-bottom: 0;
    gap: var(--sp-2);
  }

  #garage-stage {
    padding-top: 4px;
    padding-bottom: 6px;
  }

  #garage-stats {
    margin-top: 0;
  }

  #garage-canvas {
    min-height: 90px;
  }

  #garage-actions .btn,
  #garage-actions #garage-select {
    --btn-h: 40px;
  }

  .gcard {
    height: 90px;
  }

  /* two lines still, one size down: a 74px card clamped to one line
     truncated every name to "FERRA…" */
  .gcard-name {
    font-size: 10px;
    line-height: 1.25;
  }

  .gcard-stat {
    margin-top: 2px;
  }
}

/* =========================================================
SETTINGS PAGE
Cash Batch inspired layout
========================================================= */

#settings-screen {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  /* `safe` (like .screen): once the page is taller than the viewport,
     plain `center` overflows the top out of the scroll range and the
     SETTINGS heading becomes unreachable */
  justify-content: safe center;
  align-items: center;
  padding: 24px 20px 20px;
}

#settings-screen .settings-page,
#help-screen .settings-page,
#support-screen .settings-page,
#wallet-screen .settings-page,
#chal-mine .settings-page,
#history .settings-page {
  width: min(760px, 94vw);
  min-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: safe center;
  gap: 16px;
  padding: 14px 0;
}

/* ---------- heading ---------- */

#settings-screen .settings-header,
#help-screen .settings-header,
#support-screen .settings-header,
#wallet-screen .settings-header,
#chal-mine .settings-header,
#history .settings-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
}

#settings-screen .settings-title,
#help-screen .settings-title,
#support-screen .settings-title,
#wallet-screen .settings-title,
#chal-mine .settings-title,
#history .settings-title {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 900;
  font-size: var(--fs-page);
  line-height: 0.95;
  letter-spacing: var(--ls-title);
  text-transform: uppercase;

  background: linear-gradient(100deg, #8ff8ff 0%, #4f8cff 52%, #6a3bff 115%);

  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;

  filter: drop-shadow(0 8px 25px rgba(79, 140, 255, 0.28));

  transform: skewX(-6deg);
}

#settings-screen .settings-sub,
#help-screen .settings-sub,
#support-screen .settings-sub,
#wallet-screen .settings-sub,
#chal-mine .settings-sub,
#history .settings-sub {
  font-family: "Inter", sans-serif;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: var(--ls-label);
  color: #9a8fb5;
  text-transform: uppercase;
}

/* ---------- content ---------- */

#settings-screen .settings-content,
#help-screen .settings-content,
#support-screen .settings-content,
#wallet-screen .settings-content,
#chal-mine .settings-content,
#history .settings-content {
  width: min(620px, 100%);
  display: flex;
  flex-direction: column;
  gap: 20px;

  padding: 22px 24px;
  border-radius: var(--r-lg);
  background: rgba(8, 8, 22, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(120, 140, 220, 0.2);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
}

/* ---------- settings-only shell overrides ----------
   The header/content/back rules above are shared with HELP and SUPPORT.
   SETTINGS alone drops the outer glass panel (each section is its own
   card, like the reference); the heading stays centered over the cards. */

#settings-screen .settings-header,
#settings-screen .settings-content {
  width: min(700px, 100%);
}

#settings-screen .settings-header {
  gap: 8px;
}

#settings-screen .settings-sub {
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: var(--ls-body);
  text-transform: none;
  line-height: 1.4;
}

#settings-screen .settings-content {
  gap: 14px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

/* ---------- section card ---------- */

#settings-screen {
  /* every option card / row on this screen shares one chrome */
  --set-card-fill: rgba(10, 12, 30, 0.92);
  --set-card-line: rgba(120, 170, 255, 0.4);
  --set-card-line-hi: rgba(79, 140, 255, 0.9);
  --set-card-glow: 0 0 15px rgba(79, 140, 255, 0.3);
  /* selected: the same blue fill + ring as .cr-chips .dur-chip.active
     (the lobby / pre-race chips) — no check badge */
  --set-sel: var(--cyan);
  --set-sel-fill: rgba(79, 140, 255, 0.16);
  --set-sel-glow: 0 0 14px rgba(79, 140, 255, 0.35);
  --set-ico: #9ec3ff;
  --set-hint: #aab3d0;
}

#settings-screen .settings-section {
  width: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px 16px;
  border-radius: var(--r-md);
  background: rgba(15, 17, 38, 0.9);
  border: 1px solid rgba(120, 140, 220, 0.2);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

#settings-screen .settings-section-head {
  display: flex;
  align-items: center;
  gap: 12px;
  text-align: left;
}

#settings-screen .settings-section-ico {
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: var(--r-sm);
  display: grid;
  place-items: center;
  background: rgba(79, 140, 255, 0.12);
  border: 1px solid rgba(120, 170, 255, 0.35);
  color: #8ff8ff;
}

#settings-screen .settings-section-ico svg,
#settings-screen .settings-row-ico svg,
#settings-screen .settings-row-chev,
.settings-back-btn svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

#settings-screen .settings-section-ico svg {
  width: 18px;
  height: 18px;
}

#settings-screen .settings-section-title {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: clamp(13px, 2vw, 16px);
  font-weight: 800;
  letter-spacing: var(--ls-title);
  color: #e9edff;
  text-transform: uppercase;
}

#settings-screen .settings-section-hint {
  margin-top: 3px;
  font-family: "Inter", sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: var(--ls-body);
  color: #9a8fb5;
}

/* ---------- option grids ----------
   #weather-dd, #solo-acc and #gfx-bar are the shared chip bars relocated
   in here (main.js) — on this screen they lay out as card grids. */

#settings-screen .settings-options,
#settings-screen #weather-slot-settings,
#settings-screen #weather-slot-settings .dd {
  width: 100%;
}

#settings-screen #weather-slot-settings #env-bar,
#settings-screen #solo-acc,
#settings-screen #gfx-bar,
#settings-screen .settings-options--rows {
  width: 100%;
  display: grid;
  gap: 10px;
}

#settings-screen #weather-slot-settings #env-bar {
  grid-template-columns: repeat(5, minmax(0, 1fr));
}

#settings-screen #solo-acc,
#settings-screen .settings-options--rows {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

#settings-screen #gfx-bar {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* a lone row (RANKINGS) spans the full width */
#settings-screen .settings-options--rows > :only-child {
  grid-column: 1 / -1;
}

/* Hide the old DRIVE / GRAPHICS labels because
the new section already provides them */

#settings-screen #solo-acc .tlabel,
#settings-screen #gfx-bar .tlabel {
  display: none;
}

/* ---------- one chrome for every option card and row ---------- */

#settings-screen #weather-slot-settings .env-chip,
#settings-screen #solo-acc .dur-chip,
#settings-screen #gfx-bar .dur-chip,
#settings-screen .settings-row {
  position: relative;
  box-sizing: border-box;
  width: auto;
  height: auto;
  min-width: 0;
  max-width: none;
  margin: 0;
  border: 1.5px solid var(--set-card-line);
  border-radius: var(--r-md);
  background: var(--set-card-fill);
  color: #e9edff;
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: left;
  white-space: normal;
  cursor: pointer;
  transition:
    border-color 0.15s,
    box-shadow 0.15s,
    transform 0.08s;
}

#settings-screen #weather-slot-settings .env-chip:hover,
#settings-screen #solo-acc .dur-chip:hover,
#settings-screen #gfx-bar .dur-chip:hover,
#settings-screen .settings-row:hover {
  border-color: var(--set-card-line-hi);
  box-shadow: var(--set-card-glow);
}

#settings-screen #weather-slot-settings .env-chip:active,
#settings-screen #solo-acc .dur-chip:active,
#settings-screen #gfx-bar .dur-chip:active,
#settings-screen .settings-row:active {
  transform: scale(0.97);
}

/* selected: blue fill + ring, same as every other screen's chips */
#settings-screen #weather-slot-settings .env-chip.active,
#settings-screen #solo-acc .dur-chip.active,
#settings-screen #gfx-bar .dur-chip.active {
  border-color: var(--set-sel);
  background: var(--set-sel-fill);
  box-shadow: var(--set-sel-glow);
}

/* ---------- DISPLAY: map cards (icon over name) ----------
   Same ::before mask icon as the DRIVING / GRAPHICS cards, stacked above
   the label because five cells across can't fit COUNTRYSIDE beside one. */

#settings-screen #weather-slot-settings .env-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 64px;
  padding: 10px 12px;
  font-size: 10.5px;
  text-align: center;
}

#settings-screen #weather-slot-settings .env-chip::before {
  content: "";
  width: 20px;
  height: 20px;
  background-color: var(--set-ico);
  -webkit-mask: var(--set-icon) center / contain no-repeat;
  mask: var(--set-icon) center / contain no-repeat;
}

#settings-screen #weather-slot-settings .env-chip.active::before {
  background-color: var(--set-sel);
}

#settings-screen #weather-slot-settings .env-chip[data-env="day"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41'/%3E%3C/svg%3E");
}
#settings-screen #weather-slot-settings .env-chip[data-env="sunset"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 10V2M4.93 10.93l1.41 1.41M2 18h2M20 18h2M19.07 10.93l-1.41 1.41M22 22H2M16 6l-4 4-4-4M16 18a4 4 0 0 0-8 0'/%3E%3C/svg%3E");
}
#settings-screen #weather-slot-settings .env-chip[data-env="night"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z'/%3E%3C/svg%3E");
}
#settings-screen #weather-slot-settings .env-chip[data-env="cloudy"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z'/%3E%3C/svg%3E");
}
#settings-screen #weather-slot-settings .env-chip[data-env="hills"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 20c3-7 6-9 9-5 1.5 2 2.5 3.5 3.5 5M9 20c2.5-6 6-8 13-2'/%3E%3Ccircle cx='17' cy='7' r='2.5'/%3E%3C/svg%3E");
}

/* ---------- DRIVING / GRAPHICS: icon + label + hint cards ----------
   The chip's only child is its label text (chip-dd's collapsed-label sync
   reads textContent, so nothing else may be added to it): the icon is
   ::before, the hint is ::after from data-hint (set by hud.js). */

#settings-screen #solo-acc .dur-chip,
#settings-screen #gfx-bar .dur-chip {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  column-gap: 12px;
  row-gap: 3px;
  align-items: center;
  justify-items: start;
  min-height: 60px;
  padding: 10px 12px;
  line-height: 1.2;
}

#settings-screen #solo-acc .dur-chip::before,
#settings-screen #gfx-bar .dur-chip::before {
  content: "";
  grid-column: 1;
  grid-row: 1 / span 2;
  width: 22px;
  height: 22px;
  background-color: var(--set-ico);
  -webkit-mask: var(--set-icon) center / contain no-repeat;
  mask: var(--set-icon) center / contain no-repeat;
}

#settings-screen #solo-acc .dur-chip.active::before,
#settings-screen #gfx-bar .dur-chip.active::before {
  background-color: var(--set-sel);
}

#settings-screen #solo-acc .dur-chip::after,
#settings-screen #gfx-bar .dur-chip::after {
  content: attr(data-hint);
  grid-column: 2;
  grid-row: 2;
  font-family: "Inter", sans-serif;
  font-style: normal;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: var(--ls-body);
  text-transform: none;
  color: var(--set-hint);
}

#settings-screen #solo-acc .dur-chip[data-mode="auto"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 18a8 8 0 1 1 16 0'/%3E%3Cpath d='m12 18 4-6'/%3E%3C/svg%3E");
}
#settings-screen #solo-acc .dur-chip[data-mode="manual"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 5v14M12 5v14M18 5v14M6 12h12'/%3E%3C/svg%3E");
}
#settings-screen #gfx-bar .dur-chip[data-mode="auto"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3v4M12 17v4M3 12h4M17 12h4M5.6 5.6l2.8 2.8M15.6 15.6l2.8 2.8M5.6 18.4l2.8-2.8M15.6 8.4l2.8-2.8'/%3E%3C/svg%3E");
}
#settings-screen #gfx-bar .dur-chip[data-mode="high"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M5 20v-5M12 20v-10M19 20V5'/%3E%3C/svg%3E");
}
#settings-screen #gfx-bar .dur-chip[data-mode="medium"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M5 20v-5M12 20v-10'/%3E%3Cpath d='M19 20V5' opacity='.3'/%3E%3C/svg%3E");
}
#settings-screen #gfx-bar .dur-chip[data-mode="low"] {
  --set-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M5 20v-5'/%3E%3Cpath d='M12 20v-10M19 20V5' opacity='.3'/%3E%3C/svg%3E");
}

/* ---------- RANKINGS / HELP: navigation rows ---------- */

#settings-screen .settings-row {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 60px;
  padding: 10px 14px;
}

#settings-screen .settings-row-ico {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: var(--r-sm);
  display: grid;
  place-items: center;
  background: rgba(79, 140, 255, 0.1);
  color: var(--set-ico);
}

#settings-screen .settings-row-ico svg {
  width: 20px;
  height: 20px;
}

#settings-screen .settings-row-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  line-height: 1.2;
}

#settings-screen .settings-row-hint {
  font-family: "Inter", sans-serif;
  font-style: normal;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: var(--ls-body);
  text-transform: none;
  color: var(--set-hint);
}

#settings-screen .settings-row-chev {
  flex: none;
  margin-left: auto;
  width: 18px;
  height: 18px;
  color: var(--set-hint);
}

/* ---------- back button ---------- */

#settings-screen .settings-back-btn,
#help-screen .settings-back-btn,
#support-screen .settings-back-btn,
#wallet-screen .settings-back-btn,
#chal-mine .settings-back-btn,
#history .settings-back-btn {
  width: 150px;
  height: 48px;

  margin-top: 10px;
  align-self: center;

  position: relative;
  isolation: isolate;

  border: none;
  outline: none;
  background: none;

  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: var(--fs-btn-sm);
  font-weight: 800;
  letter-spacing: var(--ls-btn-sm);

  color: #e9edff;

  cursor: pointer;

  transition:
    transform 0.15s ease,
    filter 0.15s ease;
}

#settings-screen .settings-back-btn::before,
#help-screen .settings-back-btn::before,
#support-screen .settings-back-btn::before,
#wallet-screen .settings-back-btn::before,
#chal-mine .settings-back-btn::before,
#history .settings-back-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;

  clip-path: polygon(10px 0, 100% 0, calc(100% - 10px) 100%, 0 100%);

  background: rgba(15, 17, 38, 0.9);

  box-shadow:
    inset 0 0 0 1px rgba(79, 140, 255, 0.65),
    0 0 10px rgba(79, 140, 255, 0.12);
}

#settings-screen .settings-back-btn:hover,
#help-screen .settings-back-btn:hover,
#support-screen .settings-back-btn:hover,
#wallet-screen .settings-back-btn:hover,
#chal-mine .settings-back-btn:hover,
#history .settings-back-btn:hover {
  transform: translateY(-2px);
  filter: brightness(1.15);
}

#settings-screen .settings-back-btn:hover::before {
  box-shadow:
    inset 0 0 0 1px var(--cyan),
    0 0 16px rgba(79, 140, 255, 0.35);
}

/* every back button carries the arrow, so the layout for it is shared */
#settings-screen .settings-back-btn,
#help-screen .settings-back-btn,
#support-screen .settings-back-btn,
#wallet-screen .settings-back-btn,
#chal-mine .settings-back-btn,
#history .settings-back-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

/* SETTINGS alone sits tighter under the cards */
#settings-screen .settings-back-btn {
  margin-top: 2px;
}

.settings-back-btn svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

#settings-screen .settings-back-btn:active,
#help-screen .settings-back-btn:active,
#support-screen .settings-back-btn:active,
#wallet-screen .settings-back-btn:active,
#chal-mine .settings-back-btn:active,
#history .settings-back-btn:active {
  transform: translateY(1px);
}

/* ---------- mobile ---------- */

@media (max-width: 560px) {
  #settings-screen {
    padding: calc(24px + env(safe-area-inset-top)) 14px
      calc(24px + env(safe-area-inset-bottom));
  }

  #settings-screen .settings-page,
  #help-screen .settings-page,
  #support-screen .settings-page,
  #wallet-screen .settings-page,
  #chal-mine .settings-page,
  #history .settings-page {
    width: 100%;
    gap: 16px;
    padding: 12px 0;
  }

  #settings-screen .settings-sub,
  #help-screen .settings-sub,
  #support-screen .settings-sub,
  #wallet-screen .settings-sub,
  #chal-mine .settings-sub,
  #history .settings-sub {
    font-size: 11px;
    letter-spacing: 3px;
  }

  #settings-screen .settings-content,
  #help-screen .settings-content,
  #support-screen .settings-content,
  #wallet-screen .settings-content,
  #chal-mine .settings-content,
  #history .settings-content {
    width: 100%;
    gap: 16px;
  }

  #settings-screen .settings-sub {
    font-size: 12px;
    letter-spacing: var(--ls-body);
  }

  #settings-screen .settings-content {
    gap: 12px;
  }

  #settings-screen .settings-section {
    padding: 12px 12px 14px;
  }

  #settings-screen #solo-acc,
  #settings-screen #gfx-bar {
    padding: 0;
  }

  /* 3 map cards per row, 2 option cards per row, rows full width */
  #settings-screen #weather-slot-settings #env-bar {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  #settings-screen #gfx-bar {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  #settings-screen .settings-options--rows {
    grid-template-columns: minmax(0, 1fr);
  }

  #settings-screen #weather-slot-settings .env-chip {
    gap: 5px;
    min-height: 58px;
    padding: 8px 6px;
    font-size: 10px;
    letter-spacing: 0.04em;
  }

  #settings-screen #weather-slot-settings .env-chip::before {
    width: 18px;
    height: 18px;
  }

  #settings-screen #solo-acc .dur-chip,
  #settings-screen #gfx-bar .dur-chip {
    padding: 9px 10px;
    column-gap: 9px;
    font-size: 11px;
  }

  #settings-screen .settings-back-btn,
  #help-screen .settings-back-btn,
  #support-screen .settings-back-btn,
  #wallet-screen .settings-back-btn,
  #chal-mine .settings-back-btn,
  #history .settings-back-btn {
    width: 135px;
    height: 44px;
  }
}

/* new login form */
/* =========================================================
FIRST SCREEN / AUTH LANDING PAGE
========================================================= */

#login {
  position: absolute;
  inset: 0;

  /* GROUND OVERRIDE — the secondary-button tokens are defined at :root for
     the NIGHT screens: a dark translucent glass fill under near-white ink.
     #login is the one screen with a white card, and that same treatment
     painted SIGN UP as a flat grey slab that reads as disabled next to the
     blue SIGN IN. Same component, same variables — this screen just states
     what its own ground is, so anything using .btn.alt / .auth-secondary-btn
     here comes out right without a second implementation. */
  /* faintly cooler than the card under it (#fff at .94) so the button has
     a body of its own and is not carried by the hairline alone */
  --btn-alt-fill: rgba(237, 243, 255, 0.95);
  --btn-alt-fill-hi: rgba(224, 234, 255, 0.98);
  --btn-alt-line: rgba(49, 92, 255, 0.4);
  --btn-alt-line-hi: rgba(49, 92, 255, 0.8);
  --btn-alt-ink: #1d3fb8;

  /* .screen is already a flex column; it scrolls at every width so the
     footer is the last row in normal flow and a tall sign-up card pushes
     it down instead of growing over it. */
  overflow-x: hidden;
  overflow-y: auto;

  color: #ffffff;

  /* the scrim is a background LAYER, not a ::before: #login scrolls when
     the sign-up card is taller than the window, and an absolutely
     positioned child sized by inset:0 is only as tall as the visible box
     and scrolls away with the content — the lower part of the photo was
     un-veiled. Background layers on a scroll container stay fixed to the
     box, the same way the photo already does. */
  background:
    var(--first-screen-scrim),
    url("firstScreen.jpg") center bottom / cover no-repeat,
    var(--first-screen-fallback);

  z-index: 40;
}

/* ---------- TOP BAR ---------- */

/* same corner, same inset as #top-right-chips (14px / 16px + safe area):
   the login pill used to sit 4px lower and 6px further in than the menu
   pill, so the control appeared to jump when the player signed in. */
#login > #login-topbar {
  position: absolute;

  top: calc(14px + env(safe-area-inset-top));
  left: 0;
  right: 0;

  padding: 0 calc(16px + env(safe-area-inset-right)) 0
    calc(16px + env(safe-area-inset-left));

  display: flex;
  justify-content: flex-end;
  align-items: center;

  z-index: 10;
}

/* ONLINE */

#login-online {
  display: flex;
  align-items: center;
  gap: 7px;

  padding: 6px 10px;

  border-radius: var(--r-pill);

  background: rgba(255, 255, 255, 0.88);

  border: 1px solid rgba(255, 255, 255, 0.75);

  box-shadow: 0 5px 18px rgba(20, 30, 70, 0.12);

  color: #23314f;

  font-family: "Inter", sans-serif;

  font-size: 10px;
  font-weight: 800;

  letter-spacing: 1px;
}

#login-online .dot {
  width: 7px;
  height: 7px;

  border-radius: 50%;

  background: #10c879;

  box-shadow: 0 0 7px rgba(16, 200, 121, 0.8);
}

#login-online .sig {
  display: flex;
  align-items: flex-end;

  gap: 2px;

  height: 10px;
}

#login-online .sig i {
  display: block;

  width: 3px;

  border-radius: 2px;

  background: #10c879;
}

#login-online .sig i:nth-child(1) {
  height: 40%;
}

#login-online .sig i:nth-child(2) {
  height: 70%;
}

#login-online .sig i:nth-child(3) {
  height: 100%;
}

/* ---------- WALLET ---------- */

/* geometry, type and hover all come from .wallet-connect /
   .wallet-connect--light in the WALLET CONNECT block above — the ~30
   lines that used to be restated here (10px Orbitron, 1px border,
   8/18 padding, radius 20) are what made the login pill a visibly
   different control from the menu one. Only the corner it sits in is
   this screen's business. */
#login-wallet-btn {
  pointer-events: auto;
}

/* desktop has room for the words, so the pills are text-only there:
   the wallet glyph is dropped and "CONNECT WALLET" (or the balance)
   carries the meaning on its own. Phones flip it — the label goes and
   the mark stands alone in a round speaker-style chip. */
@media (min-width: 641px) {
  #login-wallet-btn .wallet-ico,
  #wallet-chip .wallet-ico {
    display: none;
  }
}

/* =========================================================
MAIN CONTENT
========================================================= */

#login-main {
  position: relative;

  z-index: 2;

  width: 100%;
  /* grows into the free space (keeping the footer pinned to the bottom
     edge when the card is short) but never shrinks below its content */
  flex: 1 0 auto;

  display: flex;

  flex-direction: column;

  align-items: center;

  /* anchored from the top (not "center") on purpose: centering the whole
     group re-centers the logo every time .auth-card resizes (opening the
     form, showing an error, toggling auth-info) which made the logo visibly
     jump up/down. Top-anchoring keeps the logo's position fixed. */
  justify-content: flex-start;

  gap: var(--sp-6);

  padding: var(--hero-top) var(--sp-5) var(--sp-5);
}

/* =========================================================
   BRAND LOCKUP — .rfs-brand
   The single RACE / FOR / SPEED wordmark. One geometry, expressed
   in em off the container's font-size, so a scale variant only has
   to change that one number and every part (tracking, the FOR row,
   the tapered blades, the italic-overhang padding) follows.

     .rfs-brand--hero   the menu: the loudest type in the game
     .rfs-brand--page   login + loading: same lockup, stepped down
                        so the auth card is the screen's focal point

   Do not add a third wordmark. Add a variant.
   ========================================================= */

.rfs-brand {
  /* the one number a variant changes. A little larger than a plain page
     title (--fs-page) — this is the game's own name, not a screen title. */
  --brand: clamp(36px, 7.4vw, 64px);
  /* ink + its halo */
  --brand-ink: #ffffff;
  --brand-ink-shadow:
    0 2px 6px rgba(0, 0, 0, 0.9), 0 0 16px rgba(255, 255, 255, 0.25);
  --brand-ink-shadow-sm: 0 2px 5px rgba(0, 0, 0, 0.9);
  --brand-glow: drop-shadow(0 4px 10px rgba(40, 100, 255, 0.5));

  font-size: var(--brand);
  width: min(700px, 90vw);

  display: flex;
  flex-direction: column;
  align-items: center;

  text-align: center;

  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 900;

  transform: skewX(-5deg);
}

.rfs-brand--hero {
  --brand: var(--fs-hero);
}

.rfs-brand--page {
  --brand: clamp(40px, 6vw, 68px);
}

/* RACE */
.rfs-race {
  font-size: 1em;
  line-height: 0.85;
  letter-spacing: var(--ls-display);

  color: var(--brand-ink);
  text-shadow: var(--brand-ink-shadow);
}

/* FOR + the two tapered blades */
.rfs-for {
  width: 100%;

  display: flex;
  align-items: center;
  justify-content: center;

  /* ~1/3 of RACE — the proportion both lockups already used */
  font-size: 0.34em;
  gap: 0.5em;
  margin: 0.28em 0;

  letter-spacing: var(--ls-title);

  color: var(--brand-ink);
  text-shadow: var(--brand-ink-shadow-sm);
}

.rfs-for .line {
  height: 3px;
  max-width: 110px;
  flex: 1;

  background: linear-gradient(90deg, transparent, #2f7cff);

  clip-path: polygon(0 20%, 100% 0, 96% 100%, 0 80%);
}

.rfs-for .line:last-child {
  background: linear-gradient(90deg, #ff3d6e, transparent);
}

/* SPEED */
.rfs-speed {
  font-size: 1.08em;
  line-height: 0.82;
  letter-spacing: var(--ls-display);

  /* the gradient is painted only inside this box (background-clip: text),
     so the italic D's top-right overhang fell outside it and rendered
     transparent — widen the box symmetrically to keep it centred */
  padding: 0 0.14em;

  background: linear-gradient(
    100deg,
    #2f7cff 0%,
    #496cff 35%,
    #7a3bff 58%,
    #ff315c 100%
  );

  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;

  filter: var(--brand-glow);
}
/* =========================================================
AUTH CARD
========================================================= */

#login .auth-card {
  width: min(330px, 88vw);

  /* roomier than the 10px/12px it shipped with, but not so roomy that the
     sign-up state runs long — this is the one card a player types into */
  padding: var(--sp-5) var(--sp-5) var(--sp-4);

  border-radius: var(--r-lg);

  background: rgba(255, 255, 255, 0.94);

  border: 1px solid rgba(255, 255, 255, 0.95);

  box-shadow:
    0 18px 55px rgba(20, 35, 80, 0.22),
    0 4px 15px rgba(20, 35, 80, 0.12);

  backdrop-filter: blur(14px);

  display: flex;

  flex-direction: column;

  align-items: center;

  text-align: center;

  color: #182444;
}

/* ---------- CARD TITLE ---------- */

#login .auth-card-title {
  font-family: "Inter", sans-serif;

  font-size: var(--fs-label);

  font-weight: 800;

  letter-spacing: var(--ls-label);

  color: #3168d9;

  margin-bottom: var(--sp-4);

  text-transform: uppercase;
}

/* ---------- LABEL ---------- */

/* "New here?" / "Already have an account?" — a sentence, not a caption,
   so it takes the body role rather than joining the .ui-label group */
#login .auth-option-label {
  font-family: "Inter", sans-serif;

  font-size: var(--fs-body);
  font-weight: 700;
  letter-spacing: var(--ls-body);

  color: #1d2945;

  margin-bottom: var(--sp-2);
}

/* =========================================================
SIGN UP BUTTON
========================================================= */

/* same slanted chrome as the home-menu .btn — fill and sheen ride on
   clipped ::before/::after layers, never on the button box (clip-path on
   the box would kill hit-testing at the angled corners) */

#login .auth-main-btn,
#login .auth-secondary-btn,
#login .auth-submit-btn {
  width: 100%;

  border: none;

  outline: none;

  position: relative;

  isolation: isolate;

  background: none;

  box-shadow: none;

  pointer-events: auto;

  cursor: pointer;

  font-family: "Orbitron", sans-serif;

  font-style: italic;

  font-weight: 800;

  display: flex;

  align-items: center;

  justify-content: center;

  gap: 10px;

  transition:
    filter 0.18s,
    transform 0.14s;
}

#login .auth-main-btn::before,
#login .auth-secondary-btn::before,
#login .auth-submit-btn::before {
  content: "";

  position: absolute;

  inset: 0;

  z-index: -2;

  clip-path: var(--btn-slant);
}

#login .auth-main-btn,
#login .auth-secondary-btn {
  height: var(--h-md);

  font-size: var(--fs-btn-sm);

  letter-spacing: var(--ls-btn-sm);
}

/* SIGN UP + CREATE DRIVER = primary CTA */

#login .auth-main-btn,
#login .auth-submit-btn {
  color: #fff;

  overflow: hidden;
}

#login .auth-main-btn::before,
#login .auth-submit-btn::before {
  /* the login card's own blue→purple CTA fill — no cyan, unlike --btn-fill */
  background: var(--auth-fill);
}

#login .auth-main-btn::after,
#login .auth-submit-btn::after {
  content: "";

  position: absolute;

  inset: 0;

  z-index: -1;

  clip-path: var(--btn-slant);

  background-image: var(--btn-sheen);

  background-repeat: no-repeat;

  background-size: 220% 100%;

  animation: sheen 3.4s ease-in-out infinite;
}

#login .auth-main-btn:hover,
#login .auth-submit-btn:hover,
#login .auth-main-btn:focus-visible,
#login .auth-submit-btn:focus-visible {
  filter: brightness(1.12);
}

/* SIGN IN = secondary (BACK stays a plain text link, see below) */

#login .auth-secondary-btn {
  color: var(--btn-alt-ink);
}

#login .auth-secondary-btn::before {
  background: var(--btn-alt-fill);

  backdrop-filter: blur(10px);

  transition: background 0.18s;
}

/* outline as a ring in the same silhouette — see --btn-slant-ring */
#login .auth-secondary-btn::after {
  content: "";

  position: absolute;

  inset: 0;

  z-index: -1;

  clip-path: var(--btn-slant-ring);

  background: var(--btn-alt-line);

  transition: background 0.18s;
}

#login .auth-secondary-btn:hover::before,
#login .auth-secondary-btn:focus-visible::before {
  background: var(--btn-alt-fill-hi);
}

#login .auth-secondary-btn:hover::after,
#login .auth-secondary-btn:focus-visible::after {
  background: var(--btn-alt-line-hi);
}

#login .auth-main-btn:active,
#login .auth-secondary-btn:active,
#login .auth-submit-btn:active {
  transform: scale(0.97);
}

/* ICON */

#login .auth-icon {
  font-family: "Inter", sans-serif;

  font-style: normal;

  font-size: 16px;

  line-height: 1;
}

/* =========================================================
DIVIDER
========================================================= */

#login .auth-divider {
  width: 100%;

  display: flex;

  align-items: center;

  gap: var(--sp-3);

  margin: var(--sp-4) 0;

  color: #5a6377;
}

#login .auth-divider span {
  flex: 1;

  height: 1px;

  background: linear-gradient(90deg, transparent, rgba(100, 115, 145, 0.28));
}

#login .auth-divider span:last-child {
  background: linear-gradient(90deg, rgba(100, 115, 145, 0.28), transparent);
}

#login .auth-divider b {
  font-family: "Orbitron", sans-serif;

  font-size: var(--fs-label);

  letter-spacing: var(--ls-label);
}

/* =========================================================
LOGIN FORM
========================================================= */

/* label -> input -> label -> input -> error -> submit -> back.
   Spacing is carried by the rows' own margins (see the label rule and
   .auth-submit-btn) rather than a flat container gap, so the two
   label/input pairs read as pairs instead of six evenly spaced rows. */
#login #auth-form {
  width: 100%;

  display: none;

  flex-direction: column;

  gap: 0;

  margin-top: var(--sp-2);
}

#login #auth-form.show {
  display: flex;
}

/* size/weight/tracking/case come from the .ui-label group */
#login #auth-form label {
  align-self: flex-start;

  font-family: "Inter", sans-serif;

  color: #64708c;

  /* :first-child so DRIVER NAME hugs the top of the form and only the
     SECOND pair gets the separating space */
  margin-top: var(--sp-2);
  margin-bottom: var(--sp-1);
}

#login #auth-form label:first-child {
  margin-top: 0;
}

#login #auth-form input {
  width: 100%;

  /* the shared control height: an input a player taps is the same size
     as a button they tap */
  height: var(--h-md);

  padding: 0 var(--sp-3);

  border-radius: var(--r-sm);

  border: 1px solid rgba(80, 105, 170, 0.28);

  background: #f7f9ff;

  color: #172443;

  font-family: "Inter", sans-serif;

  font-size: 13px;

  font-weight: 700;

  outline: none;
}

#login #auth-form input:focus {
  border-color: #416cff;

  box-shadow: 0 0 0 3px rgba(65, 108, 255, 0.1);
}

#login #auth-form input::placeholder {
  color: #626c88;
}

/* BACK: plain text link, not a slanted button */
#login .auth-cancel-btn {
  width: 100%;

  /* a real touch target, not a 22px sliver — it is the only way back */
  height: var(--h-sm);

  margin-top: 0;

  border: none;

  background: transparent;

  color: #64708c;

  font-family: "Inter", sans-serif;

  font-size: 11px;

  font-weight: 800;

  letter-spacing: 1px;

  cursor: pointer;
}

#login .auth-cancel-btn:hover {
  color: #416cff;
}

/* SUBMIT */

#login .auth-submit-btn {
  height: var(--h-md);

  margin-top: var(--sp-3);

  font-size: var(--fs-btn-sm);

  letter-spacing: var(--ls-btn-sm);
}

/* ERROR */

/* the one message a player cannot recover from (there is no PIN reset),
   so it is the clearest string on the card, not the faintest */
/* reserved so the row can appear without shifting the button, but no
   taller than the 12px line it holds */
#login #lg-error {
  min-height: var(--sp-2);

  margin-top: var(--sp-1);

  color: #c62340;

  font-size: var(--fs-body);

  font-weight: 700;
}

/* =========================================================
INFORMATION
========================================================= */

/* the small print is the tallest block on the sign-up card — tighter
   leading here is worth more than anywhere else on the screen */
#login .auth-info {
  width: 100%;

  margin-top: var(--sp-2);

  font-family: "Inter", sans-serif;

  font-size: var(--fs-body);

  line-height: 1.45;

  color: #5d6680;
}

/* =========================================================
FOOTER
========================================================= */

#login #login-footer,
#loading #loading-footer {
  /* relative, not static: the shade below is a z-index:-1 ::before and
     needs the footer itself to be the positioned/stacking parent */
  position: relative;
  flex: 0 0 auto;
  /* shrink-to-fit and centred, so the hairline is exactly as wide as the
     credit row and lands centred with it instead of running edge to edge.
     The negative bottom margin cancels .screen's --screen-pad-b so the
     strip still sits on the very bottom edge. */
  margin: 0 auto calc(-1 * var(--screen-pad-b));
  width: max-content;
  /* floor so both screens' strips land on the same hairline width; the
     min() keeps it from overflowing a narrow desktop window */
  min-width: min(var(--footer-strip-w), calc(100% - 40px));
  max-width: calc(100% - 40px);
  z-index: 5;

  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;

  /* in normal flow with a negative bottom margin cancelling the screen
     pad, so this footer owns the bottom edge and composes the inset in */
  padding: var(--sp-3) 0 calc(var(--sp-3) + var(--footer-safe-b));

  border-top: 1px solid rgba(255, 255, 255, 0.55);
}

/* #loading is top-aligned (justify-content: flex-start), so its copy has
   to claim the free space to reach the bottom edge; #login is centred and
   must not have its card pushed up. */
#loading #loading-footer {
  margin-top: auto;
}

#login #login-footer .sep,
#loading #loading-footer .sep {
  opacity: 0.7;
}

/* a touch of extra air before the X links; nothing is pushed to an edge
   now that the row is centred */
#login #login-footer .spacer,
#loading #loading-footer .spacer {
  flex: 0 0 6px;
}

#login #login-footer .ico,
#loading #loading-footer .ico {
  display: inline-flex;
  align-items: center;
}

#login #login-footer .ico .pad-svg,
#loading #loading-footer .ico .pad-svg {
  display: block;
  width: 16px;
  height: 16px;
}

#login #login-footer .x-link,
#loading #loading-footer .x-link {
  display: inline-flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
  transition: opacity 0.2s;
}

#login #login-footer .x-link svg,
#loading #loading-footer .x-link svg {
  display: block;
  width: 14px;
  height: 14px;
}

#login #login-footer .x-link:hover,
#loading #loading-footer .x-link:hover {
  opacity: 0.65;
}

/* =========================================================
MOBILE
========================================================= */

@media (max-width: 600px) {
  #login-topbar {
    padding-left: 12px;
    padding-right: 12px;
  }

  /* bare icons on phones — the white pills read as UI chrome over the
     photo backdrop, so drop the plate and let the marks stand alone,
     scaled up to stay tappable. A soft light halo keeps them legible
     against the bright part of the sky. */
  #login-online,
  #login-wallet-btn {
    display: inline-flex;
    align-items: center;
    padding: 0;
    border: none;
    background: none;
    box-shadow: none;
    color: #1b2440;
    filter: drop-shadow(0 1px 3px rgba(255, 255, 255, 0.85));
  }

  #login-online {
    gap: 5px;
  }

  #login-online .dot {
    width: 11px;
    height: 11px;
  }

  #login-online .sig {
    height: 16px;
    gap: 3px;
  }

  #login-online .sig i {
    width: 4px;
  }

  #login-wallet-btn .wallet-ico .wallet-svg {
    width: 30px;
    height: 30px;
  }

  #login .auth-card {
    width: min(340px, 92vw);

    padding: var(--sp-5);
  }

  #login-main {
    gap: var(--sp-5);
  }

}

/* ---------- phone wallet chip ----------
   Same plate as the bottom-right #mute button: a 40px
   round chip, dark translucent fill, green hairline border. Lives at
   the end of the sheet so the login/loading white skins and the
   icon-only pill rules above can't repaint it. */
@media (max-width: 640px) {
  #login-wallet-btn,
  #wallet-chip:has(.wallet-label),
  body:has(#login:not(.hidden)) #wallet-chip:has(.wallet-label),
  body:has(#loading:not(.hidden)) #wallet-chip:has(.wallet-label) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    background: rgba(10, 8, 20, 0.72);
    border: 1px solid #14f19555;
    border-radius: 20px;
    color: #eafff6;
    filter: none;
    box-shadow: none;
    opacity: 0.75;
    font-size: 16px;
    line-height: 1;
    transition: opacity 0.2s;
  }

  #login-wallet-btn:hover,
  #wallet-chip:has(.wallet-label):hover,
  body:has(#login:not(.hidden)) #wallet-chip:has(.wallet-label):hover,
  body:has(#loading:not(.hidden)) #wallet-chip:has(.wallet-label):hover {
    border-color: #14f19555;
    transform: none;
    opacity: 1;
    box-shadow: none;
  }

  /* matches #mute .mute-svg — sized off the chip's font-size */
  #login-wallet-btn .wallet-ico .wallet-svg,
  #wallet-chip .wallet-ico .wallet-svg {
    width: 1.25em;
    height: 1.25em;
  }

  /* the gear keeps mirroring it in the opposite corner at this width */
  /* both chips shrink together via --chips-h, set on :root above */

  #settings-btn {
    padding: 0;
    opacity: 0.75;
    font-size: 16px;
    line-height: 1;
  }
}

/* ---------- desktop login footer ----------
   The strip sits over the brightest part of the photo (wet road plus
   neon reflections), where 72%-opacity navy on a 1px white shadow lost
   its edges. Full-strength ink, a stronger white halo and a soft light
   veil fading upward give it a stable surface to sit on without
   turning into a solid bar. */
@media (min-width: 641px) {
  /* colour is .app-footer--light's job — only the shade under the strip
     is this breakpoint's */
  #login #login-footer::before,
  #loading #loading-footer::before {
    content: "";
    position: absolute;
    /* bottom 0, not -30px: the strip owns the bottom edge, so anything
       hanging below it is scrollable overflow on #login (overflow-y: auto)
       and put a scrollbar on the desktop sign-in screen */
    inset: -18px 0 0;
    z-index: -1;
    pointer-events: none;
    /* the veil this comment block describes was never actually declared —
       the rule set geometry and nothing to paint, so the white strip sat
       bare on the photo. Same recipe as the phone footer below. */
    background: linear-gradient(
      to top,
      rgba(6, 8, 20, 0.72),
      rgba(6, 8, 20, 0)
    );
  }
}

/* ---------- phone login footer ----------
   At 7px in the dark ink it was set in, the strip disappeared into the
   road photo. It was also pinned absolutely to the viewport bottom while
   #login clipped its overflow, so the taller sign-in form grew straight
   over it. On phones the screen scrolls instead and the footer flows as
   the last row of the column, so it is pushed below the card rather than
   covered by it. */
@media (max-width: 640px) {
  #login #login-footer,
  #loading #loading-footer {
    /* edge to edge: the strip cancels the screen inset on all three sides
       it touches rather than sitting inside it, so the hairline and its
       shade run the full width of the phone. --screen-pad-l/r resolve per
       screen (#login inherits .screen's 12px, #loading :root's 16px), so
       the same three lines fit both. */
    width: calc(100% + var(--screen-pad-l) + var(--screen-pad-r));
    /* margin-top left alone: #loading-footer sets it to auto to reach the
       bottom of its top-aligned column */
    margin-right: calc(-1 * var(--screen-pad-r));
    margin-left: calc(-1 * var(--screen-pad-l));
    margin-bottom: calc(-1 * var(--screen-pad-b));
    min-width: 0;
    max-width: none;
    justify-content: center;
    flex-wrap: wrap;
    gap: 6px;
    /* the 14px is now the text's own inset from the phone edge, not the
       box's */
    padding: 10px 14px calc(var(--sp-1) + var(--footer-safe-b));
  }

  /* shade only behind the strip, fading upward so it doesn't read as a
     bar sitting on the photo */
  #login #login-footer::before,
  #loading #loading-footer::before {
    content: "";
    position: absolute;
    inset: -18px 0 0;
    z-index: -1;
    pointer-events: none;
    background: linear-gradient(
      to top,
      rgba(6, 8, 20, 0.72),
      rgba(6, 8, 20, 0)
    );
  }
}

/* keyboard shortcut hint on the horn/nitro buttons */
#horn-btn small,
#nitro-btn small {
  /* the keycap stays upright system type — an italic Orbitron "H" in a 4px
     box is unreadable */
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
  font-style: normal;
  font-size: 11px;
  letter-spacing: 1px;
  opacity: 0.9;
  vertical-align: middle;
  border: 1px solid currentColor;
  border-radius: 4px;
  padding: 1px 4px;
  margin-left: 4px;
}
body.touch #horn-btn small,
body.touch #nitro-btn small {
  display: none;
}

/* the HUD's "NITRO — SHIFT" key hint: a phone has a NITRO button, no
   Shift key, so the key part of the label goes */
body.touch .nitro-label .key-hint {
  display: none;
}

/* ============================================================
   HELP SCREEN (searchable FAQ — shares the settings shell above)
   ============================================================ */

/* the help list is a plain column, not the centred section stack */
#help-screen .settings-content,
#support-screen .settings-content,
#wallet-screen .settings-content,
#chal-mine .settings-content {
  gap: 18px;
}

/* --- "still stuck?" button at the bottom of the FAQ --- */
#help-screen .help-open-btn {
  font-family: "Orbitron", sans-serif;
  font-size: var(--fs-btn-sm);
  font-weight: 800;
  letter-spacing: var(--ls-btn-sm);
  text-transform: uppercase;
  color: #e9edff;
  cursor: pointer;
  width: 100%;
  max-width: 520px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 14px 22px;
  border-radius: var(--r-md);
  border: 1px solid rgba(120, 140, 220, 0.45);
  background: rgba(20, 24, 55, 0.7);
  transition:
    border-color 0.15s,
    box-shadow 0.15s,
    transform 0.08s;
}
#help-screen .help-open-btn:hover {
  border-color: rgba(143, 248, 255, 0.8);
  box-shadow: 0 0 18px rgba(79, 140, 255, 0.35);
}
#help-screen .help-open-btn:active {
  transform: scale(0.97);
}
#help-screen .help-open-btn .help-q {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(180, 195, 240, 0.75);
  border-radius: 50%;
  font-size: 11px;
  letter-spacing: 0;
  line-height: 1;
}
#help-screen .help-open-btn .help-q svg {
  width: 11px;
  height: 11px;
}

/* --- search --- */
#help-screen .help-searchbar {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
}
#help-screen .help-search-icon {
  position: absolute;
  left: 14px;
  font-size: 13px;
  opacity: 0.7;
  pointer-events: none;
}
#help-screen #help-search {
  width: 100%;
  font-family: "Inter", sans-serif;
  font-size: 13px;
  color: #e9edff;
  padding: 12px 36px 12px 38px;
  border-radius: var(--r-md);
  border: 1px solid rgba(120, 140, 220, 0.35);
  background: rgba(6, 8, 22, 0.85);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}
#help-screen #help-search::placeholder {
  color: #7b7595;
}
#help-screen #help-search:focus {
  border-color: rgba(143, 248, 255, 0.7);
  box-shadow: 0 0 16px rgba(79, 140, 255, 0.28);
}
#help-screen #help-search::-webkit-search-cancel-button {
  display: none;
}
#help-screen #help-search-clear {
  position: absolute;
  right: 8px;
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: 50%;
  background: rgba(120, 140, 220, 0.18);
  color: #c8d0f5;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

/* --- category chips --- */
#help-screen .help-cats {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
}
#help-screen .help-cat {
  font-family: "Orbitron", sans-serif;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 2px;
  color: #a9b0d8;
  cursor: pointer;
  padding: 8px 14px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(120, 140, 220, 0.3);
  background: rgba(16, 18, 42, 0.7);
  transition:
    color 0.15s,
    border-color 0.15s,
    background 0.15s;
}
#help-screen .help-cat:hover {
  color: #e9edff;
  border-color: rgba(143, 248, 255, 0.6);
}
#help-screen .help-cat.active {
  color: #06101f;
  border-color: transparent;
  background: linear-gradient(100deg, #8ff8ff 0%, #4f8cff 60%, #6a3bff 120%);
}

/* --- list, groups, items --- */
#help-screen #help-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* the filter hides individual rows — .hidden is only a .screen rule elsewhere */
#help-screen #help-list .hidden {
  display: none !important;
}

#help-screen .help-group {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 4px;
  color: #8ff8ff;
  text-transform: uppercase;
  margin-top: 14px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(79, 140, 255, 0.28);
}
#help-screen .help-group:first-child {
  margin-top: 0;
}

#help-screen .help-item {
  border-radius: var(--r-md);
  border: 1px solid rgba(120, 140, 220, 0.2);
  background: rgba(14, 16, 38, 0.6);
  overflow: hidden;
}
#help-screen .help-item[open] {
  border-color: rgba(79, 140, 255, 0.5);
}
#help-screen .help-item summary {
  list-style: none;
  cursor: pointer;
  padding: 13px 40px 13px 16px;
  position: relative;
  font-family: "Inter", sans-serif;
  font-size: 13px;
  font-weight: 700;
  color: #e9edff;
}
#help-screen .help-item summary::-webkit-details-marker {
  display: none;
}
#help-screen .help-item summary::after {
  content: "+";
  position: absolute;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 16px;
  color: #8ff8ff;
}
#help-screen .help-item[open] summary::after {
  content: "\2212";
}
#help-screen .help-body {
  padding: 0 16px 14px;
  font-family: "Inter", sans-serif;
  font-size: var(--fs-body);
  line-height: 1.65;
  color: #c2c8e6;
}
#help-screen .help-body b {
  color: #e9edff;
}

#help-screen .help-list {
  margin: 0;
  padding-left: 18px;
}
#help-screen .help-list li {
  margin: 5px 0;
}

#help-screen .help-note {
  margin-top: 10px;
  padding: 10px 12px;
  border-radius: var(--r-sm);
  border-left: 3px solid #ffcf33;
  background: rgba(255, 207, 51, 0.08);
  color: #ecdfb8;
  font-size: 12px;
}

#help-screen .help-keys {
  width: 100%;
  border-collapse: collapse;
}
#help-screen .help-keys td {
  padding: 6px 8px 6px 0;
  vertical-align: top;
  border-bottom: 1px solid rgba(120, 140, 220, 0.12);
}
#help-screen .help-keys td:first-child {
  white-space: nowrap;
  width: 42%;
  color: #e9edff;
  font-weight: 700;
}
#help-screen .help-keys kbd {
  display: inline-block;
  font-family: "Inter", sans-serif;
  font-size: var(--fs-meta);
  font-weight: 800;
  letter-spacing: var(--ls-body);
  color: #06101f;
  background: linear-gradient(180deg, #cfe3ff, #9fbdf5);
  border-radius: 5px;
  padding: 2px 7px;
  margin-right: 4px;
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.45);
}

#help-screen .help-empty {
  text-align: center;
  padding: 26px 10px;
  color: #7b7595;
  font-family: "Inter", sans-serif;
  font-size: 13px;
}

@media (max-width: 560px) {
  #help-screen .help-item summary {
    font-size: var(--fs-body);
  }
  #help-screen .help-keys td:first-child {
    width: 46%;
  }
}

/* ============================================================
   SUPPORT SCREEN (tickets — shares the settings shell above;
   markup is built by src/supportUI.js)
   ============================================================ */

/* the form hides its "other" inputs — .hidden is only a .screen rule elsewhere */
#support-screen .hidden {
  display: none !important;
}

#support-screen #support-body {
  display: flex;
  flex-direction: column;
  gap: 18px;
  width: 100%;
  text-align: left; /* a form and a thread read left-to-right, unlike the centred settings stack */
}

#support-screen .support-section-title {
  font-family: "Orbitron", sans-serif;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 3px;
  color: #a9b0d8;
  text-transform: uppercase;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(120, 140, 220, 0.25);
}

#support-screen .support-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

#support-screen .support-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
#support-screen .support-field > span {
  font-family: "Inter", sans-serif;
  font-size: 12px;
  font-weight: 600;
  color: #c8d0f5;
}
#support-screen .support-field > span em {
  font-style: normal;
  font-weight: 400;
  color: #7b7595;
  margin-left: 6px;
}

#support-screen .support-field input,
#support-screen .support-field select,
#support-screen .support-field textarea,
#support-screen .support-reply textarea {
  width: 100%;
  font-family: "Inter", sans-serif;
  font-size: 13px;
  color: #e9edff;
  padding: 11px 13px;
  border-radius: var(--r-md);
  border: 1px solid rgba(120, 140, 220, 0.35);
  background: rgba(6, 8, 22, 0.85);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  resize: vertical;
}
#support-screen .support-field select {
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, #a9b0d8 50%),
    linear-gradient(135deg, #a9b0d8 50%, transparent 50%);
  background-position:
    calc(100% - 18px) 50%,
    calc(100% - 13px) 50%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
  padding-right: 34px;
}
#support-screen .support-field select option {
  background: #0a0d20;
  color: #e9edff;
}
#support-screen .support-field input::placeholder,
#support-screen .support-field textarea::placeholder,
#support-screen .support-reply textarea::placeholder {
  color: #7b7595;
}
#support-screen .support-field input:focus,
#support-screen .support-field select:focus,
#support-screen .support-field textarea:focus,
#support-screen .support-reply textarea:focus {
  border-color: rgba(143, 248, 255, 0.7);
  box-shadow: 0 0 16px rgba(79, 140, 255, 0.28);
}

#support-screen .support-note {
  font-family: "Inter", sans-serif;
  font-size: 12px;
  color: #7b7595;
  line-height: 1.5;
}

#support-screen .support-status {
  font-family: "Inter", sans-serif;
  font-size: 12px;
  color: #c8d0f5;
  min-height: 1em;
}

/* --- buttons: the SUBMIT / SEND / CONNECT actions --- */
#support-screen .support-btn {
  font-family: "Orbitron", sans-serif;
  font-size: var(--fs-btn-sm);
  font-weight: 800;
  letter-spacing: var(--ls-btn-sm);
  text-transform: uppercase;
  color: #e9edff;
  cursor: pointer;
  align-self: flex-start;
  padding: 12px 22px;
  border-radius: var(--r-md);
  border: 1px solid rgba(120, 140, 220, 0.45);
  background: rgba(20, 24, 55, 0.7);
  transition:
    border-color 0.15s,
    box-shadow 0.15s,
    transform 0.08s;
}
#support-screen .support-btn.primary {
  color: #06101f;
  border-color: transparent;
  background: linear-gradient(100deg, #8ff8ff 0%, #4f8cff 60%, #6a3bff 120%);
}
#support-screen .support-btn:hover {
  border-color: rgba(143, 248, 255, 0.8);
  box-shadow: 0 0 18px rgba(79, 140, 255, 0.35);
}
#support-screen .support-btn:active {
  transform: scale(0.97);
}
#support-screen .support-btn:disabled {
  opacity: 0.5;
  cursor: default;
  box-shadow: none;
  transform: none;
}
#support-screen .support-empty .support-btn {
  align-self: center;
  margin-top: 14px;
}
#support-screen .support-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* --- ticket list --- */
#support-screen .support-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

#support-screen .support-ticket {
  border-radius: var(--r-md);
  border: 1px solid rgba(120, 140, 220, 0.25);
  background: rgba(16, 18, 42, 0.6);
}
#support-screen .support-ticket[open] {
  border-color: rgba(143, 248, 255, 0.45);
}
#support-screen .support-ticket summary {
  list-style: none;
  cursor: pointer;
  display: grid;
  grid-template-columns: auto auto 1fr;
  grid-template-areas:
    "id badge subject"
    "meta meta meta";
  align-items: center;
  column-gap: 10px;
  row-gap: 3px;
  padding: 12px 14px;
  font-family: "Inter", sans-serif;
  font-size: 13px;
  color: #e9edff;
}
#support-screen .support-ticket summary::-webkit-details-marker {
  display: none;
}
#support-screen .support-ticket-id {
  grid-area: id;
  font-family: "Orbitron", sans-serif;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1px;
  color: #8ff8ff;
}
#support-screen .support-ticket-subject {
  grid-area: subject;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#support-screen .support-ticket-meta {
  grid-area: meta;
  font-size: 11px;
  color: #7b7595;
}

#support-screen .support-status-badge {
  grid-area: badge;
  justify-self: start;
  font-family: "Orbitron", sans-serif;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  border: 1px solid currentColor;
  white-space: nowrap;
}
#support-screen .support-status-badge.open {
  color: #ffd166;
}
#support-screen .support-status-badge.in_progress {
  color: #8ff8ff;
}
#support-screen .support-status-badge.resolved {
  color: #7dffb3;
}
#support-screen .support-status-badge.closed {
  color: #7b7595;
}

#support-screen .support-ticket-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0 14px 14px;
}

/* --- the thread --- */
#support-screen .support-msg {
  padding: 10px 12px;
  border-radius: var(--r-sm);
  background: rgba(6, 8, 22, 0.6);
  border-left: 2px solid rgba(120, 140, 220, 0.35);
}
#support-screen .support-msg.admin {
  border-left-color: #8ff8ff;
  background: rgba(79, 140, 255, 0.1);
}
#support-screen .support-msg-head {
  font-family: "Inter", sans-serif;
  font-size: 11px;
  color: #7b7595;
  margin-bottom: 4px;
}
#support-screen .support-msg-head b {
  color: #c8d0f5;
  letter-spacing: 1px;
}
#support-screen .support-msg-body {
  font-family: "Inter", sans-serif;
  font-size: 13px;
  line-height: 1.5;
  color: #e9edff;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

#support-screen .support-reply {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}

#support-screen .support-empty {
  text-align: center;
  padding: 26px 10px;
  color: #7b7595;
  font-family: "Inter", sans-serif;
  font-size: 13px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

@media (max-width: 560px) {
  #support-screen .support-ticket summary {
    grid-template-columns: auto 1fr;
    grid-template-areas:
      "id badge"
      "subject subject"
      "meta meta";
  }
  #support-screen .support-ticket-subject {
    white-space: normal;
  }
  #support-screen .support-btn {
    align-self: stretch;
  }
}

/* Resume-a-paid-round banner. Fixed above every screen (.screen is z-index
   20) but under the toasts, and it owns clicks, so no pointer-events:none
   here. */
#bet-resume {
  position: fixed;
  top: calc(10px + env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  max-width: min(560px, calc(100vw - 24px));
  padding: 12px 18px;
  border-radius: var(--r-md);
  background: rgba(16, 18, 40, 0.9);
  backdrop-filter: blur(14px);
  box-shadow:
    inset 0 0 0 1.5px var(--btn-alt-line),
    0 20px 60px rgba(0, 0, 0, 0.6);
  color: rgba(233, 237, 255, 0.75);
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: var(--ls-body);
  line-height: 1.5;
  text-align: center;
}

#bet-resume b {
  color: #7ef7ff;
  font-weight: 800;
}

#bet-resume-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-top: 10px;
}

#bet-resume-actions button {
  padding: 8px 16px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--btn-fill);
  color: var(--btn-ink);
  font: inherit;
  font-size: var(--fs-btn-sm);
  font-weight: 800;
  letter-spacing: var(--ls-btn-sm);
  cursor: pointer;
}

#bet-resume-actions #bet-resume-dismiss {
  background: var(--btn-alt-fill);
  box-shadow: inset 0 0 0 1px var(--btn-alt-line);
  color: var(--btn-alt-ink);
  font-weight: 600;
}

/* =========================================================
   PHONE + TABLET: login / loading centred, wallet dropdown readable
   ========================================================= */

/* The logo + card (login) and logo + ring (loading) groups were top-
   anchored by a --hero-top formula tuned for desktop, which left them
   sitting 50-160px above the middle of a phone or tablet. Between the
   top inset and the credit strip they now centre by layout, so every
   height and every card state is exact. Short landscape phones keep
   their own side-by-side layout (the max-height: 560px block). Desktop
   is untouched. */
@media (max-width: 1080px) and (orientation: portrait),
  (max-width: 1080px) and (min-height: 561px) {
  #login,
  #loading {
    --hero-top: 0px;
  }

  /* the bottom padding was the one asymmetry left: it pulled the centre
     10px up from the middle of the band between top inset and strip */
  #login-main {
    justify-content: safe center;
    padding-bottom: 0;
  }

  /* #loading-footer already carries margin-top: auto to reach the bottom;
     giving the wordmark the same splits the free space evenly above the
     logo and below the ring */
  #loading .rfs-brand {
    margin-top: auto;
  }
}

.wt-label {
  flex: 0 0 auto;
}

.wt-addr {
  flex: 1 1 auto;
  min-width: 0;
}

/* Wallet picker (EIP-6963) — one row per wallet the browser announced.
   Shares #wallet-menu's shell; these are just the rows inside it. */
.wallet-menu-head {
  font-size: 11px;
  letter-spacing: 1px;
  opacity: 0.7;
  padding: 2px 6px 8px;
}

.wallet-pick {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 10px;
  margin-bottom: 4px;
  font: inherit;
  font-size: 13px;
  letter-spacing: 0.5px;
  text-align: left;
  color: #eafff6;
  background: rgba(20, 241, 149, 0.06);
  border: 1px solid #14f19533;
  border-radius: 9px;
  cursor: pointer;
}

.wallet-pick:hover,
.wallet-pick:focus-visible {
  background: rgba(20, 241, 149, 0.14);
  border-color: #14f19588;
}

.wallet-pick img {
  width: 20px;
  height: 20px;
  border-radius: 5px;
  flex: none;
}

/* ============================================================
   WALLET SCREEN (WALLET next to EXIT — shares the settings shell above)
   ============================================================ */

#wallet-screen .settings-content {
  gap: 16px;
}

#wallet-screen #ws-body {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* --- not signed in --- */
#wallet-screen .ws-connect {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 18px 0 6px;
  text-align: center;
}

#wallet-screen .ws-connect-text {
  font-family: "Inter", sans-serif;
  font-size: var(--fs-body);
  color: #aab3d0;
  max-width: 380px;
  line-height: 1.5;
}

/* --- the two balance cards --- */
#wallet-screen .ws-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

#wallet-screen .ws-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 18px;
  border-radius: var(--r-md);
  background: rgba(15, 17, 38, 0.9);
  border: 1px solid rgba(120, 140, 220, 0.2);
  min-width: 0;
}

#wallet-screen .ws-card-game {
  border-color: rgba(79, 140, 255, 0.55);
  box-shadow: 0 0 18px rgba(79, 140, 255, 0.14);
}

#wallet-screen .ws-card-chain {
  border-color: rgba(120, 170, 255, 0.4);
}

#wallet-screen .ws-card-label {
  font-family: "Inter", sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 2px;
  color: #9a8fb5;
  text-transform: uppercase;
}

#wallet-screen .ws-card-amt {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 800;
  font-size: clamp(18px, 3vw, 24px);
  color: #e9edff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#wallet-screen .ws-card-game .ws-card-amt {
  color: #5aa0ff;
}

#wallet-screen .ws-card-usd {
  font-family: "Inter", sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #aab3d0;
  min-height: 1.2em;
}

#wallet-screen .ws-card-note {
  margin-top: 4px;
  font-family: "Inter", sans-serif;
  font-size: 11px;
  color: #7f86a6;
  line-height: 1.35;
}

#wallet-screen .ws-card-note.warn {
  color: #ffb547;
}

/* --- address + network line --- */
#wallet-screen .ws-addr-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 0 4px;
  font-family: "Inter", sans-serif;
  font-size: 12px;
  color: #aab3d0;
}

#wallet-screen .ws-addr-wrap {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

#wallet-screen .ws-addr {
  font-family: monospace;
  font-size: 12px;
  color: #e9edff;
  letter-spacing: 0.5px;
}

#wallet-screen .ws-explorer {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.5px;
  color: #8ff8ff;
  text-decoration: none;
}

#wallet-screen .ws-explorer:hover {
  text-decoration: underline;
}

/* --- amount panel --- */
#wallet-screen .ws-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px 18px 18px;
  border-radius: var(--r-md);
  background: rgba(15, 17, 38, 0.9);
  border: 1px solid rgba(120, 140, 220, 0.2);
}

#wallet-screen .ws-tabs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  padding: 4px;
  border-radius: 10px;
  background: rgba(8, 8, 22, 0.8);
}

#wallet-screen .ws-tab {
  border: none;
  outline: none;
  background: none;
  padding: 10px 0;
  border-radius: var(--r-sm);
  cursor: pointer;
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 800;
  font-size: 12px;
  letter-spacing: 2px;
  color: #9a8fb5;
  transition: background 0.15s, color 0.15s;
}

#wallet-screen .ws-tab.on {
  background: rgba(79, 140, 255, 0.18);
  color: #e9edff;
  box-shadow: inset 0 0 0 1px rgba(120, 170, 255, 0.5);
}

#wallet-screen .ws-tab-hint {
  font-family: "Inter", sans-serif;
  font-size: 11px;
  color: #9a8fb5;
  text-align: center;
  min-height: 1.2em;
}

#wallet-screen .ws-amt-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
}

#wallet-screen .ws-amt {
  flex: 1;
  min-width: 0;
  padding: 0 16px;
  height: 52px;
  border-radius: var(--r-sm);
  border: 1px solid rgba(120, 170, 255, 0.4);
  background: rgba(8, 8, 22, 0.8);
  color: #e9edff;
  font-family: "Orbitron", sans-serif;
  font-weight: 800;
  font-size: 20px;
  outline: none;
}

#wallet-screen .ws-amt::placeholder {
  color: #4f5678;
}

#wallet-screen .ws-amt:focus {
  border-color: var(--cyan);
  box-shadow: 0 0 12px rgba(79, 140, 255, 0.25);
}

/* fixed unit tag beside the box — the panel is SOL only */
#wallet-screen .ws-amt-unit {
  display: flex;
  align-items: center;
  padding: 0 14px;
  border-radius: var(--r-sm);
  border: 1px solid rgba(120, 170, 255, 0.3);
  background: rgba(8, 8, 22, 0.8);
  color: #9a8fb5;
  font-family: "Inter", sans-serif;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.5px;
}

#wallet-screen .ws-quick {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

#wallet-screen .ws-quick-btn {
  flex: 1;
  min-width: 56px;
  padding: 9px 6px;
  border-radius: var(--r-sm);
  border: 1px solid rgba(120, 170, 255, 0.3);
  background: rgba(8, 8, 22, 0.6);
  color: #cdd3f0;
  cursor: pointer;
  font-family: "Inter", sans-serif;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 1px;
  transition: border-color 0.15s, background 0.15s;
}

#wallet-screen .ws-quick-btn:hover {
  border-color: var(--cyan);
  background: rgba(79, 140, 255, 0.12);
}

#wallet-screen .ws-approx {
  font-family: "Inter", sans-serif;
  font-size: 12px;
  color: #aab3d0;
  text-align: center;
  min-height: 1.2em;
}

#wallet-screen .ws-go {
  width: 100%;
}

#wallet-screen .ws-go:disabled {
  opacity: 0.55;
  cursor: wait;
}

#wallet-screen .ws-status {
  margin-top: 4px;
  max-width: none;
  text-align: center;
  min-height: 1.2em;
}

#wallet-screen .ws-status:empty {
  display: none;
}

/* --- recent activity --- */
#wallet-screen .ws-recent-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0 4px;
}

#wallet-screen .ws-recent-title {
  font-family: "Orbitron", sans-serif;
  font-style: italic;
  font-weight: 800;
  font-size: 12px;
  letter-spacing: 2px;
  color: #e9edff;
}

#wallet-screen .ws-link {
  border: none;
  background: none;
  cursor: pointer;
  font-family: "Inter", sans-serif;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.5px;
  color: #8ff8ff;
  /* a 76x12 text link was the smallest tap target in the game; the
     padding grows the hit area to the --h-sm floor without moving the
     text (negative margin cancels it in the row) */
  min-height: var(--h-sm);
  padding: 0 8px;
  margin: -8px -8px -8px 0;
}

#wallet-screen .ws-link:hover {
  text-decoration: underline;
}

#wallet-screen .ws-recent {
  display: flex;
  flex-direction: column;
  border-radius: var(--r-md);
  background: rgba(15, 17, 38, 0.9);
  border: 1px solid rgba(120, 140, 220, 0.2);
  overflow: hidden;
}

#wallet-screen .ws-row {
  display: grid;
  grid-template-columns: 1fr auto 78px 96px;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid rgba(120, 140, 220, 0.12);
  font-family: "Inter", sans-serif;
  font-size: 12px;
}

#wallet-screen .ws-row:last-child {
  border-bottom: none;
}

#wallet-screen .ws-row-type {
  text-align: left;
  font-weight: 800;
  letter-spacing: 1px;
  color: #e9edff;
  text-transform: uppercase;
}

#wallet-screen .ws-row-when {
  color: #7f86a6;
  white-space: nowrap;
  text-align: right;
}

/* CONFIRMED badges are display:none (global .tx-status.confirmed), which
   would drop that cell and slide the amount into the badge's column —
   so every cell is pinned to its column. */
#wallet-screen .ws-row-type {
  grid-column: 1;
}

#wallet-screen .ws-row-when {
  grid-column: 2;
}

#wallet-screen .ws-row .tx-status {
  grid-column: 3;
  justify-self: end;
}

#wallet-screen .ws-row-amt {
  grid-column: 4;
}

#wallet-screen .ws-row-amt {
  font-family: "Orbitron", sans-serif;
  font-weight: 800;
  font-size: 12px;
  white-space: nowrap;
  color: #e9edff;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#wallet-screen .ws-row-amt.in {
  color: #5aa0ff;
}

#wallet-screen .ws-row-amt.out {
  color: #ff6b8b;
}

#wallet-screen .ws-actions {
  display: flex;
  justify-content: center;
  /* wider than .btn-row's 16px on purpose: the two plates lean the same way,
     so REFRESH's bottom-right corner and LOGOUT's top-left corner close in on
     each other and 12px read as almost touching. */
  gap: 24px;
  flex-wrap: wrap;
}

#wallet-screen .ws-logout {
  color: #ff6b8b;
}

@media (max-width: 560px) {
  #wallet-screen .ws-cards {
    grid-template-columns: 1fr;
  }

  #wallet-screen .ws-row {
    grid-template-columns: 1fr auto;
    row-gap: 2px;
  }

  #wallet-screen .ws-row-when {
    grid-column: 1;
    grid-row: 2;
    text-align: left;
  }

  #wallet-screen .ws-row .tx-status {
    grid-column: 2;
    grid-row: 2;
    justify-self: end;
  }

  #wallet-screen .ws-row-amt {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
  }
}

/* =========================================================
   RESPONSIVE SYSTEM
   The one place that states how the sheet adapts. Everything above is
   per-screen tuning; the rules here are cross-cutting and sit last so
   they win ties on specificity.

   Breakpoints (mobile-first tiers; a rule picks the tier it is FOR):
     phone           < 640px          (max-width: 640px)
     tablet          640 – 1023px     (min-width: 641px) and (max-width: 1023px)
     laptop          1024 – 1279px
     desktop         1280 – 1535px
     large           1536px +         (min-width: 1536px)
     ultrawide       2200px +         (min-width: 2200px)  — HUD band, see below
   Orientation tiers that cut across width:
     short landscape (orientation: landscape) and (max-height: 560px) — phones held sideways
     upright         (orientation: portrait)                          — phones and tablets
   Pointer tier:
     (pointer: coarse) — fingers; every control gets the --h-md floor.

   Older 560px / 600px cut-offs above are deliberate sub-tiers inside the
   phone band (small vs large phones), not a second system.
   ========================================================= */

/* ---------- no sideways scroll, ever ----------
   .screen scrolls vertically (overflow-y: auto), which makes overflow-x
   compute to auto as well — so any element a couple of px too wide (a
   glow, a card's slanted plate, a long address) let the whole screen be
   dragged sideways on a phone. Horizontal scrolling lives in the inner
   strips that ask for it (#garage-grid, #garage-tabs); the screen itself
   never does. */
.screen {
  overflow-x: hidden;
}

/* ---------- keyboard focus: one visible ring for every control ----------
   .btn's only :focus-visible treatment was the hover brighten/scale, and a
   dozen controls clear the outline for their own :focus border. The ring
   below is the keyboard-only signal; pointer focus keeps the quieter
   per-control styles. Specificity is raised where a rule above says
   `outline: none`, and :where() covers the rest without out-ranking them. */
:where(button, [role="button"], a[href], summary, [tabindex="0"]):focus-visible,
.btn:focus-visible,
.bet-opt:focus-visible,
.mp-card:focus-visible,
.tile:focus-visible,
.env-chip:focus-visible,
.dur-chip:focus-visible,
.gtab:focus-visible,
.gcard:focus-visible,
.opt:focus-visible,
.help-cat:focus-visible,
#wallet-screen .ws-tab:focus-visible,
#settings-screen .settings-back-btn:focus-visible,
#history .settings-back-btn:focus-visible,
#login .auth-submit-btn:focus-visible {
  outline: 2px solid #8ff8ff;
  outline-offset: 3px;
}

/* ---------- motion: honour the OS setting everywhere ---------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- touch targets: the --h-md (44px) floor on every finger-sized
   control. Chips and steppers were tuned by eye to 24–36px for the
   desktop pointer; on a coarse pointer the box grows to the floor while
   the label keeps its size. min-height (not height) so the many per-screen
   `height:` rules above are simply raised, never fought. ---------- */
@media (pointer: coarse) {
  .env-chip,
  .dur-chip,
  .cr-chips .dur-chip,
  .cp-panel .dur-chip,
  #lobby .dur-chip,
  #solo-acc .dur-chip,
  #gfx-bar .dur-chip,
  #settings-screen #weather-slot-settings .env-chip,
  #settings-screen #solo-acc .dur-chip,
  #settings-screen #gfx-bar .dur-chip,
  .gtab,
  .help-cat,
  #help-screen .help-cat,
  .ws-tab,
  .tx-unit-btn,
  .chal-pill,
  .chal-tab,
  .chal-copy-btn,
  .support-btn,
  #support-screen .support-btn,
  .help-open-btn,
  #help-screen .help-open-btn,
  .invite-card-btn,
  .dd-btn,
  .chip-dd-btn,
  .pb-card,
  .bet-opt,
  .auth-cancel-btn,
  .cr-input-wrap,
  .cr-stepper {
    min-height: var(--h-md);
  }

  .cr-step,
  .cp-panel .cr-step,
  #help-screen #help-search-clear,
  .wt-copy,
  #mute {
    min-width: 40px;
    min-height: 40px;
  }

  /* one-digit chips ("2", "5") are 37px wide on their padding alone */
  .dur-chip,
  .env-chip {
    min-width: var(--h-md);
  }

  /* the small button size (MY CHALLENGES' card VIEW / SHARE) meets the floor here */
  .btn--sm {
    --btn-h: var(--h-md);
  }

  /* the showroom's SELECT / SOUND / BACK drop to 34px on a sideways phone
     to keep the car strip on screen; 40px is the floor a thumb needs */
  #garage-actions .btn,
  #garage-actions #garage-select {
    min-height: 40px;
  }

  /* the footer's X glyph is a 14px link; a negative-margin pad grows the
     hit area to the floor without moving the glyph */
  #login #login-footer .x-link,
  #loading #loading-footer .x-link {
    padding: 13px;
    margin: -13px;
  }

  #login .auth-cancel-btn {
    height: var(--h-md);
  }

  /* the settings back button and the modal pair already meet the floor;
     inputs a thumb has to land in do not */
  .name-in,
  .modal-in,
  .cr-input,
  #help-screen #help-search,
  .chal-input,
  input[type="text"],
  input[type="number"],
  input[type="search"] {
    min-height: var(--h-md);
  }
}

/* ---------- the first-screen photo on an upright phone ----------
   firstScreen.jpg is 1280×801 with the car in its left fifth. `cover` on a
   390×844 portrait viewport scales it to 1348×843 and, centred, shows only
   x = 479…869 — trees, mountains and empty road; the car is cropped off
   the left edge. Anchor the crop near the left so the car stays in frame
   (it sits low, under the sign-in card, not behind it). */
@media (orientation: portrait) {
  #login,
  #loading {
    background-position: 12% bottom;
  }
}

/* ---------- 320px phones: the two grids whose cells could not hold their
   longest label at three-up (COUNTRYSIDE in the DISPLAY map picker, the
   history's INFLOW / OUTFLOW / NET totals) ---------- */
@media (max-width: 360px) {
  #settings-screen #weather-slot-settings #env-bar {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .tx-total-label {
    letter-spacing: 1px;
  }

  .tx-total {
    padding: 12px 6px;
  }
}

/* ---------- large and ultrawide screens ----------
   The menus are already centred, capped columns (min(760px, 94vw) etc.),
   so a 3440px monitor shows them in the middle with calm space either
   side. The race HUD is the one thing that hugged the edges: DISTANCE at
   x=24 and SPEED at x=3416 are further apart than a driver's eyes travel.
   Past 2200px the HUD keeps its corners inside a centred 2000px band. */
@media (min-width: 1920px) {
  /* the showroom's three-column stage (stats | car | paint) spread with
     the viewport, parking the stats 600px from the car on a 3440px
     monitor. Cap it; the car's column stays centred, so garage.js's
     podium alignment is unaffected. */
  #garage-head,
  #garage-stage {
    width: min(100%, 1720px);
  }
}

@media (min-width: 2200px) {
  #hud {
    left: calc((100vw - 2000px) / 2);
    right: calc((100vw - 2000px) / 2);
  }

  /* menu scrim gets a little more breathing room at the edges */
  .screen {
    --screen-pad-r: max(32px, env(safe-area-inset-right));
    --screen-pad-l: max(32px, env(safe-area-inset-left));
  }
}
