/* Powder Party — display (big screen) layout. The theme owns colour/type
   (shared/theme.css); this file owns layout + the alpine retheme. */

html, body { margin: 0; height: 100%; overflow: hidden; background: #cfeaf8; }

/* Persistent 3D backdrop */
#scene { position: fixed; inset: 0; z-index: 0; }
#scene canvas { display: block; }
#scene::after {       /* soft vignette to reinforce the diorama feel */
  content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 1;
  background: radial-gradient(120% 90% at 50% 38%, transparent 55%, rgba(20, 50, 80, 0.28) 100%);
}

/* ---- Lobby ---- */
#lobby {
  position: fixed; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3vh; padding: 5vh 6vw; box-sizing: border-box;
}
/* Card + QR side by side; the join-URL chip is centred below the row. The row is
   capped and centred (#lobby centres it) so on a wide display the pair sits as a
   balanced group framing the race in the gap, rather than hugging the far edges. */
.lobby__row { width: 100%; max-width: 1800px; display: flex; align-items: center; justify-content: space-between; gap: 4vw; }
/* The card is the main element (the live race just plays quietly behind it) — grow
   to fill the space left of the QR (flex:1, 0 basis) so its width is stable, capped
   just above the QR's width on a wide display. */
.lobby__card { padding: clamp(1.5rem, 3vw, 3rem); flex: 1; max-width: calc(1.12 * clamp(220px, 26vw, 420px) + 4.8rem); }
.lobby__card h1 {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.4rem, 5vw, 4.2rem); margin: 0 0 1rem; color: var(--ink);
}
.lobby__card h1 span { color: var(--brand); }
/* join URL lives in the bottom chip now (.join-chip); base type here, sized there */
.join__url { font-family: var(--font-display); font-weight: 600; color: var(--ink); word-break: break-all; }
.join__code { color: var(--accent); }
#count { color: var(--ink-2); font-weight: 700; margin-bottom: 1.2rem; }

#players { display: grid; gap: 0.6rem; }
.seat {
  display: flex; align-items: center; gap: 0.7rem;
  background: var(--surface-2); border: 2px solid var(--hairline);
  border-radius: var(--r-sm); padding: 0.7rem 1rem; font-weight: 800; color: var(--ink);
}
.seat--open { opacity: 0.5; }
.seat__open { color: var(--ink-3); font-weight: 700; }
.seat__name { flex: 1; }
.seat__host { font-size: 0.7rem; font-weight: 800; letter-spacing: 0.08em; color: #fff; background: var(--brand); border-radius: var(--r-pill); padding: 0.15rem 0.6rem; }
.seat__skier { font-size: 0.85rem; color: var(--ink-3); font-weight: 700; }

/* Difficulty switch — the SAME shared Blue/Red/Black widget as the host's phone
   (theme.css), laid out left-aligned in the lobby card below the roster and bumped
   up a touch for the big screen. Live here too — the display is authoritative. */
.lobby__level { align-items: flex-start; gap: 0.55rem; margin-top: 1.3rem; }
.lobby__level .level-select__cap { font-size: 0.95rem; letter-spacing: 0.05em; }
.lobby__level .level-seg__btn { font-size: 1.2rem; padding: 0.55rem 1.5rem; }
/* Reserve the switch's built box (3 buttons: Blue/Red/Black) so it's at final
   size on first paint — buildLevelSeg fills this empty container from JS, which
   would otherwise snap the pill from a bare nub to full width (and grow the card
   a row taller) a frame after load. justify-content: center keeps the buttons
   centred in the reserved width if font metrics land a hair under the reserve. */
.lobby__level .level-seg { min-width: 18.25rem; min-height: 3.25rem; justify-content: center; }

.lobby__qr { flex: none; }
.qr-card { background: #fff; padding: 1.2rem; border-radius: var(--r-lg); box-shadow: var(--shadow-float); }
/* aspect-ratio holds the final SQUARE box from first paint: the canvas starts at
   its default 300×150 intrinsic (until renderQR makes it square), and without this
   `height: auto` would lay it out half-height, then pop to full when the QR lands. */
.qr-card canvas { display: block; width: clamp(220px, 26vw, 420px); aspect-ratio: 1; height: auto; image-rendering: pixelated; }

/* Join-URL chip — pinned to the bottom-centre of the page, and a <button>: a
   click (or Enter/Space) copies the full join link, confirmed by the .toast.
   min-width reserves the production URL's footprint (powder.couch-games.com/<code>
   ≈ 30rem on a big screen) so the "…" placeholder already sits at final size,
   instead of the chip expanding from the centre when the room code + URL arrive.
   Transparent border (border-box) holds the box steady as :hover tints it. */
.join-chip { position: fixed; left: 50%; bottom: 3vh; transform: translateX(-50%); min-width: 30rem; padding: 0.7rem 1.6rem; background: #fff; border: 2px solid transparent; border-radius: var(--r-pill); box-shadow: var(--shadow-float); white-space: nowrap; text-align: center; font: inherit; color: inherit; cursor: pointer; transition: border-color 0.15s ease, transform 0.06s ease; }
.join-chip:hover { border-color: var(--brand); }
.join-chip:active { transform: translateX(-50%) translateY(1px); }
.join-chip:focus-visible { outline: 3px solid var(--brand); outline-offset: 3px; }
.join-chip .join__url { font-size: clamp(1.1rem, 2vw, 1.7rem); word-break: normal; }

/* Copy-confirmation toast — floats just above the join chip; fades + rises in,
   then back out (main.js toggles .is-on for ~1.6s). */
.toast {
  position: fixed; left: 50%; bottom: calc(3vh + 5.5rem); z-index: 10;
  transform: translate(-50%, 0.5rem);
  font-weight: 800; font-size: 1rem; color: #fff;
  background: var(--brand); padding: 0.55rem 1.3rem; border-radius: var(--r-pill);
  box-shadow: var(--shadow-pop); opacity: 0; pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.toast.is-on { opacity: 1; transform: translate(-50%, 0); }

/* Cross-fade between looping lobby attract races — covers the 3D scene (z:0) but
   sits UNDER the lobby cards (z:2), so the race dips to snow-white and back while
   the join UI stays crisp. main.js toggles .is-on around each restart. */
#lobby-fade { position: fixed; inset: 0; z-index: 1; background: #eaf2fb; opacity: 0; pointer-events: none; transition: opacity 0.4s ease; }
#lobby-fade.is-on { opacity: 1; }

/* ---- Run overlays ---- */
#race { position: fixed; inset: 0; z-index: 2; pointer-events: none; }
#race .btn, #race .icon-btn { pointer-events: auto; }

#pause-btn { position: fixed; top: 1.4rem; right: 1.4rem; z-index: 4; }

#countdown {
  position: fixed; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: 700; font-size: 26vh; color: #fff;
  text-shadow: 0 6px 30px rgba(20, 50, 80, 0.5); pointer-events: none;
}
#countdown.is-go { color: var(--brand); }

#pause-overlay, #results {
  position: fixed; inset: 0; z-index: 5;
  display: flex; align-items: center; justify-content: center;
  background: rgba(20, 50, 80, 0.32); backdrop-filter: blur(6px);
}
.pause-card, .results-card { padding: clamp(1.5rem, 3vw, 2.6rem); min-width: min(90vw, 420px); text-align: center; }
.pause-card h2, .results-card h2 { font-family: var(--font-display); margin: 0 0 1.2rem; color: var(--ink); }
.pause-card__btns, .results-card__btns { display: flex; gap: 0.8rem; justify-content: center; flex-wrap: wrap; }

#results-list { list-style: none; margin: 0 0 1.4rem; padding: 0; display: grid; gap: 0.5rem; text-align: left; }
#results-list li { display: flex; align-items: center; gap: 0.7rem; background: var(--surface-2); border-radius: var(--r-sm); padding: 0.6rem 0.9rem; font-weight: 800; color: var(--ink); }
.res__rank { width: 1.6rem; font-family: var(--font-display); color: var(--accent); }
.res__name { flex: 1; }
.res__cpu { font-size: 0.7rem; color: var(--ink-3); background: var(--hairline); border-radius: var(--r-pill); padding: 0.1rem 0.5rem; }
.res__time { font-family: var(--font-display); color: var(--ink-2); }
/* Late joiner on the board — unranked "next run" row: quieter and dashed so it
   reads as queued for the rematch, not a result. */
#results-list li.res--joining { opacity: 0.75; outline: 2px dashed var(--hairline); outline-offset: -2px; }
.res--joining .res__rank { color: var(--ink-3); }
.res--joining .res__time { font-style: italic; font-family: var(--font-body); font-weight: 700; color: var(--ink-3); }

/* ---- Split-screen cell labels (positioned each frame by SceneRenderer) ---- */
.race-labels { font-family: var(--font-display); }
.cell-label {
  position: absolute; display: flex; flex-direction: column; gap: 0.1rem;
  background: rgba(255, 255, 255, 0.85); border-left: 5px solid var(--c, #2d9cdb);
  border-radius: 8px; padding: 0.3rem 0.6rem; box-shadow: var(--shadow-pop);
}
.cell-label__name { font-weight: 700; color: var(--ink); font-size: 1.05rem; }
.cell-label__stat { font-weight: 700; color: var(--ink-2); font-size: 0.85rem; }
.cell-label.is-finished { background: var(--brand); }
.cell-label.is-finished .cell-label__name, .cell-label.is-finished .cell-label__stat { color: #fff; }

/* per-cell steer indicator (mirrors the phone's carve bar), centred along the
   cell bottom — a livery-coloured fill that slides with the player's lean. The
   left/top are set per cell each frame; transform:translateX(-50%) centres it. */
.cell-steer {
  position: absolute; display: none; transform: translateX(-50%);
  width: clamp(150px, 15vw, 280px); height: 2rem;
  background: rgba(255, 255, 255, 0.9); border: 2px solid var(--hairline);
  border-radius: var(--r-pill); overflow: hidden; box-shadow: var(--shadow-pop);
}
.cell-steer::before {
  content: ''; position: absolute; left: 50%; top: 0; bottom: 0; width: 2px;
  background: rgba(40, 80, 120, 0.18);
}
.cell-steer__fill {
  position: absolute; left: 50%; top: 0; bottom: 0; width: 50%; margin-left: -25%;
  background: var(--c, var(--brand)); border-radius: var(--r-pill);
  transition: transform 0.05s linear;
}

/* ---- Reconnect card ---- a QR for a dropped player, centred in their own
   split-screen cell (where the live HUD usually sits) while their skier keeps its
   place on the slope. SceneRenderer._loop sets left/top to the cell centre and
   toggles display; translate(-50%,-50%) centres the card on that point. Frosted
   card with a livery top-border so it reads as that player's seat. */
.cell-reconnect {
  position: absolute; display: none; transform: translate(-50%, -50%);
  flex-direction: column; align-items: center; gap: 0.5rem; text-align: center;
  padding: clamp(0.7rem, 1.5vw, 1.3rem) clamp(1.1rem, 2.4vw, 2.2rem);
  background: rgba(255, 255, 255, 0.92);
  border-radius: 12px; border-top: 6px solid var(--c, var(--brand));
  box-shadow: var(--shadow-pop); pointer-events: none;
}
.rc-card__head {
  display: flex; align-items: center; max-width: min(80vw, 22rem);
  font-weight: 800; font-size: clamp(1rem, 1.4vw, 1.35rem); color: var(--ink);
}
.rc-card__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rc-card__sub {
  font-weight: 700; font-size: clamp(0.78rem, 1vw, 0.95rem); letter-spacing: 0.02em;
  text-transform: uppercase; color: var(--ink-3);
}
.rc-card__qr {
  display: block; width: clamp(200px, 24vw, 360px); aspect-ratio: 1 / 1;
  border-radius: 8px; image-rendering: pixelated;
}

/* Audio-unlock hint — shown when a run starts before any local gesture has
   unlocked Web Audio; removed by main.js on the first click/keypress. */
#sound-hint {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(1rem + env(safe-area-inset-bottom));
  z-index: 40; pointer-events: none;
  padding: 0.45rem 0.9rem;
  font-family: var(--font-body); font-weight: 800; font-size: 0.85rem;
  color: var(--ink); background: rgba(255, 255, 255, 0.85);
  border-radius: var(--r-pill); box-shadow: var(--shadow-pop);
}

@media (max-width: 860px) {
  #lobby { gap: 2vh; }
  .lobby__row { flex-direction: column; align-items: center; gap: 2vh; }
  .lobby__card { flex: none; max-width: 90vw; }
}

/* ---- Device choice ---- the chooser a phone gets when it lands on this
   big-screen page (shared link, or a controller bailed here with ?bail=…).
   Fully opaque and above every run overlay, so the heavy 3D world booting
   underneath never shows through. Hidden by default; the media query below
   surfaces it on cramped viewports only. */
#device-choice {
  position: fixed; inset: 0; z-index: 60;
  display: none; align-items: center; justify-content: center;
  padding:
    calc(5vh + env(safe-area-inset-top)) calc(8vw + env(safe-area-inset-right))
    calc(5vh + env(safe-area-inset-bottom)) calc(8vw + env(safe-area-inset-left));
  background: linear-gradient(180deg, var(--sky-1) 0%, var(--sky-2) 50%, #ffffff 100%);
}
.dc-card {
  display: flex; flex-direction: column; align-items: center; gap: 0.9rem;
  max-width: 24rem; padding: 1.6rem 1.4rem; text-align: center;
}
.dc-card h1 { font-family: var(--font-display); font-weight: 700; font-size: 2.1rem; line-height: 1.02; margin: 0; color: var(--ink); }
.dc-card h1 span { color: var(--brand); }
.dc-sub { color: var(--ink-2); font-weight: 700; margin: 0; }
.dc-toast { color: var(--danger); font-weight: 800; margin: 0; }
.dc-toast.hidden { display: none; }
.dc-card .btn { width: 100%; margin: 0; }
#dc-continue { font-size: 0.95rem; }

/* Cramped viewport = almost certainly a phone holding the display URL: show the
   chooser unless the user already chose this device (html.device-choice-dismissed,
   sticky for the session) or a run is on (html.in-session — resizing a desktop
   window mid-race must not cover the world). Size-only triggers on purpose: the
   "bigger screen or continue here" choice applies to a narrow desktop window too,
   and the continue button is one tap away. */
@media (max-width: 950px), (max-height: 500px) {
  html:not(.device-choice-dismissed):not(.in-session) #device-choice { display: flex; }
}
