/* Gorilla XR — movement playground · UI design system
   One accent: the GRIP-GREEN (#a9dc76), the colour of holding on in the climb mechanic — used only
   for focus / active / primary, never as decoration. Surfaces are quiet forest-glass; type is Space
   Grotesk for chrome. Everything derives from the tokens below. */
:root {
  --ink: #eef4ee;
  --ink-dim: rgba(238, 244, 238, 0.52);
  --glass: rgba(17, 22, 20, 0.52);
  --glass-hi: rgba(26, 32, 29, 0.66);
  --card: rgba(15, 19, 17, 0.92);
  --line: rgba(228, 242, 226, 0.14);
  --line-2: rgba(228, 242, 226, 0.26);
  --accent: #a9dc76;
  --accent-hi: #c4ef9a;
  --accent-ink: #10160e;            /* near-black for text on the accent */
  --r-btn: 11px;
  --r-card: 18px;
  --blur: 10px;
  --shadow: 0 10px 34px rgba(0, 0, 0, 0.34);
  --ctl: 42px;                      /* unified control-button size */
  --font-ui: 'Space Grotesk', ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-body: ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

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

html, body {
  height: 100%;
  overflow: hidden;
  /* Match the sky-dome bottom colour so the brief "no first frame yet" flash is
     a soft sky tone instead of a black void that reads as a dark overlay. */
  background: #dff0f7;
  font-family: var(--font-body);
  color: var(--ink);
  -webkit-user-select: none;
  user-select: none;
}

/* Shared control-button base: gear / camera. Quiet glass, hairline, crisp icon; accent only on the
   active state. One size, one radius — the cluster reads as a set, not scattered placeholder buttons. */
.ctl-btn {
  position: fixed;
  top: calc(14px + env(safe-area-inset-top, 0px));
  z-index: 30;
  width: var(--ctl);
  height: var(--ctl);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: var(--r-btn);
  color: var(--ink);
  background: var(--glass);
  border: 1px solid var(--line);
  cursor: pointer;
  -webkit-backdrop-filter: blur(var(--blur));
  backdrop-filter: blur(var(--blur));
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.06s ease;
}
.ctl-btn:hover { background: var(--glass-hi); border-color: var(--line-2); }
.ctl-btn:active { transform: scale(0.94); }
.ctl-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ctl-btn svg { display: block; width: 21px; height: 21px; opacity: 0.94; }

canvas { display: block; }

/* Heads-up overlay (hidden once an immersive session starts) */
#hud {
  position: fixed;
  top: 16px;
  left: 16px;
  max-width: 360px;
  padding: 14px 16px;
  border-radius: 14px;
  background: rgba(12, 16, 22, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  pointer-events: none;
  z-index: 10;
  line-height: 1.5;
}

#title {
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: 0.2px;
  margin-bottom: 6px;
}

#status {
  font-size: 0.82rem;
  color: #a9dc76;
  font-variant-numeric: tabular-nums;
  margin-bottom: 8px;
  white-space: pre-line;
}

#hint {
  font-size: 0.78rem;
  color: #c7ccd2;
}

#hint b { color: #eef2f5; }
#hint .desk { color: #8b93a0; display: inline-block; margin-top: 6px; }

/* Boot error panel — only rendered when JS removes the `hidden` attribute on a
   real failure. Using `#boot-error[hidden] { display: none }` (with higher
   specificity than the visible rule) so the HTML `hidden` attribute wins. */
#boot-error {
  position: fixed;
  inset: 0;
  align-items: center;
  justify-content: center;
  padding: 24px;
  text-align: center;
  background: rgba(8, 10, 14, 0.92);
  color: #ff8080;
  font-size: 0.9rem;
  white-space: pre-wrap;
  z-index: 100;
  display: flex;
}
#boot-error[hidden] { display: none; }

/* Our custom Enter-VR button (only shown when navigator.xr reports immersive-vr
   is supported — so on desktop it never appears at all). */
#enter-vr {
  position: fixed;
  left: 50%;
  bottom: 30px;
  transform: translateX(-50%);
  padding: 13px 30px;
  font: 600 0.95rem/1 var(--font-ui);
  letter-spacing: 0.02em;
  color: var(--accent-ink);
  background: var(--accent);
  border: none;
  border-radius: 999px;
  cursor: pointer;
  z-index: 20;
  box-shadow: var(--shadow);
}
#enter-vr:hover { background: var(--accent-hi); }

/* 1st/3rd-person camera toggle — top-right. Accent ring + dot when in 3rd person (active). */
#cam-toggle { right: calc(14px + env(safe-area-inset-right, 0px)); }
#cam-toggle.third { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 55%, transparent); background: var(--glass-hi); }

/* Gear / settings button — top-left. */
#gear-btn { left: calc(14px + env(safe-area-inset-left, 0px)); }

/* Mic mute — top-right, left of the camera toggle. Red when muted. */
#mic-btn { right: calc(14px + var(--ctl) + 10px + env(safe-area-inset-right, 0px)); }
#mic-btn.muted { color: #ff6b5a; border-color: color-mix(in srgb, #ff6b5a 55%, transparent); background: var(--glass-hi); }

/* Build button — UNDER the camera toggle (same right edge, one row down). Opens the 3D inventory. */
#build-btn {
  right: calc(14px + env(safe-area-inset-right, 0px));
  top: calc(14px + var(--ctl) + 10px + env(safe-area-inset-top, 0px));
}
#build-btn.active { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 55%, transparent); background: var(--glass-hi); }

/* ---- Settings / pause overlay (flat-screen). The in-world ui3d panel handles VR. ----
   A single quiet card: identity (name) up top, then the few real options, then Resume. The accent
   appears only on the eyebrow, focus rings, the active toggle, and the primary button. */
#settings {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 22px;
  background: rgba(7, 10, 9, 0.5);
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
}
#settings.show { display: flex; }
#settings-card {
  position: relative;
  width: min(92vw, 350px);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow);
  padding: 26px 24px 22px;
}
#set-close {
  position: absolute; top: 12px; right: 12px;
  width: 34px; height: 34px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; line-height: 1; color: var(--ink-dim);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line); border-radius: 50%;
  cursor: pointer; transition: background 0.15s, color 0.15s;
}
#set-close:hover { background: rgba(255, 255, 255, 0.1); color: var(--ink); }
.set-eyebrow { font-family: var(--font-ui); font-size: 11px; font-weight: 600; letter-spacing: 0.24em; text-transform: uppercase; color: var(--accent); }
.set-title { font-family: var(--font-ui); font-size: 1.45rem; font-weight: 700; letter-spacing: -0.01em; margin: 3px 0 20px; }
.set-label { font-family: var(--font-ui); font-size: 12px; font-weight: 500; letter-spacing: 0.03em; color: var(--ink-dim); }

.set-field { margin-bottom: 18px; }
.set-field .set-label { display: block; margin-bottom: 8px; }
#set-name {
  width: 100%; height: 42px; padding: 0 13px;
  border-radius: var(--r-btn);
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid var(--line);
  color: var(--ink);
  font: 500 15px/1 var(--font-ui);
  outline: none;
  transition: border-color 0.15s ease, background 0.15s ease;
}
#set-name:focus { border-color: var(--accent); background: rgba(255, 255, 255, 0.06); }
#set-name::placeholder { color: var(--ink-dim); }

.set-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 13px 0; border-top: 1px solid var(--line); }
.set-row .set-label { font-size: 14px; color: var(--ink); letter-spacing: 0.01em; }

/* Volume slider — hairline track, accent fill via the thumb's box-shadow trick kept simple. */
#set-volume { -webkit-appearance: none; appearance: none; flex: 1; max-width: 168px; height: 4px; border-radius: 999px; background: var(--line-2); outline: none; }
#set-volume::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--accent); cursor: pointer; border: none; }
#set-volume::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--accent); cursor: pointer; border: none; }

/* Custom toggle switch (replaces the default checkbox — reads far more finished). */
.set-toggle { position: relative; width: 44px; height: 26px; flex: none; cursor: pointer; }
.set-toggle input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.set-toggle .track { position: absolute; inset: 0; border-radius: 999px; background: rgba(255, 255, 255, 0.1); border: 1px solid var(--line); transition: background 0.18s ease, border-color 0.18s ease; }
.set-toggle .knob { position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: var(--ink); transition: transform 0.18s ease; }
.set-toggle input:checked ~ .track { background: var(--accent); border-color: var(--accent); }
.set-toggle input:checked ~ .knob { transform: translateX(18px); background: var(--accent-ink); }
.set-toggle input:focus-visible ~ .track { outline: 2px solid var(--accent); outline-offset: 2px; }

#set-resume {
  margin-top: 20px; width: 100%; height: 46px;
  font: 600 15px/1 var(--font-ui); letter-spacing: 0.01em;
  border: none; border-radius: var(--r-btn);
  background: var(--accent); color: var(--accent-ink);
  cursor: pointer;
  transition: background 0.15s ease;
}
#set-resume:hover { background: var(--accent-hi); }
#set-resume:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* Once the user clicks to play, collapse the HUD to a small unobtrusive corner
   chip and hide the play prompt entirely so nothing covers the view. */
body.playing #hud {
  max-width: 220px;
  padding: 8px 12px;
  background: rgba(12, 16, 22, 0.35);
}
body.playing #hud #hint { display: none; }
/* Debug status readout (fps / grounded / speed / mode) — hidden everywhere; it's a dev overlay, not
   player-facing UI. (Real load errors still surface via #boot-error.) */
#hud { display: none !important; }

/* Jump-power meter: a skinny, transparent bar centered at the top. While the jump
   button (Space / A·X) is held, the white fill grows from 0 → 100% over the charge
   time, so a quick tap = small jump and a full hold = max jump. Shown only while
   charging (the .show class is toggled from the render loop). */
#jump-bar {
  position: fixed;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  width: 220px;
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.28);
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.12s ease;
  pointer-events: none;
  z-index: 20;
}
#jump-bar.show { opacity: 1; }
#jump-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  border-radius: 999px;
}

/* ---- Touch controls (mobile, non-VR) ----
   The whole overlay is injected into the DOM by touchControls.js, and is shown only while the
   touch scheme is the ACTIVE one (`body.touch-mode`, set by main.js's applyControlMode) AND the
   player is `playing`. Gating on touch-mode (not just playing) means a desktop pointer-lock
   session never shows the overlay, and the scheme can be swapped live on resize/rotate.

   Sizing is fully responsive: button + ring sizes use clamp(px, vmin, px) so they scale down on
   small phones and up to a comfortable cap on tablets, and the look/move split + button anchor
   adapt to landscape and short viewports. --stick-r is the single source of truth for the
   joystick radius — touchControls.js reads it back via getComputedStyle (onResize), so changing
   it here (incl. in a media query) is all that's needed. Heights prefer dvh (dynamic viewport
   height) so mobile-browser chrome show/hide doesn't clip the zones. */
#touch-controls {
  --stick-r: clamp(46px, 9vmin, 64px);
  --btn-jump: clamp(74px, 17vmin, 104px);
  --btn-sprint: clamp(56px, 13vmin, 80px);
  position: fixed;
  inset: 0;
  z-index: 15;
  pointer-events: none;
  display: none;
  touch-action: none;
}
body.playing.touch-mode #touch-controls { display: block; }

/* Move stick: BOTTOM-LEFT only (not full width) so the rest of the screen — including the lower-right
   by the jump button — is free to look. */
#touch-move {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 50%;
  height: 45%;
  height: 45dvh;
  pointer-events: auto;
}
/* Look zone: the WHOLE screen (under the move stick + buttons, which capture their own regions first
   as later siblings). So you can drag to look anywhere except the bottom-left stick — top, and the
   lower-right next to jump. */
#touch-look {
  position: fixed;
  inset: 0;
  pointer-events: auto;
}
/* While standing on the customizer pad, let panel taps fall through the look zone. */
body.customizing #touch-look { pointer-events: none; }

/* Joystick ring — positioned at the touch point each press (JS sets left/top). */
#stick-base {
  position: fixed;
  width: calc(var(--stick-r) * 2);
  height: calc(var(--stick-r) * 2);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(12, 16, 22, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.18);
  display: none;
}
#stick-base.show { display: block; }
#stick-thumb {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--stick-r) * 0.92);
  height: calc(var(--stick-r) * 0.92);
  transform: translate(0, 0);
  margin-left: calc(var(--stick-r) * -0.46);
  margin-top: calc(var(--stick-r) * -0.46);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.32);
  border: 1px solid rgba(255, 255, 255, 0.4);
}

/* Action buttons, bottom-right, above the look zone. */
#touch-buttons {
  position: fixed;
  right: calc(20px + env(safe-area-inset-right, 0px));
  bottom: calc(28px + env(safe-area-inset-bottom, 0px));
  display: flex;
  align-items: flex-end;
  gap: clamp(12px, 3vmin, 20px);
  pointer-events: none;
  z-index: 16;
}
#touch-buttons button {
  pointer-events: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  color: var(--ink);
  background: var(--glass);
  border: 1px solid var(--line);
  -webkit-backdrop-filter: blur(var(--blur));
  backdrop-filter: blur(var(--blur));
  transition: background 0.1s ease, border-color 0.1s ease, transform 0.06s ease;
}
#btn-jump {
  width: var(--btn-jump);
  height: var(--btn-jump);
}
#btn-jump svg { width: 42%; height: 42%; opacity: 0.92; }
#touch-buttons button.down { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); transform: scale(0.95); }

/* Landscape / short viewports (most phones held sideways): the screen is wide but shallow, so
   give the look zone more height, shrink the move zone, lift the buttons clear of the home bar,
   and tuck the ring/buttons a touch smaller so thumbs reach everything. */
@media (orientation: landscape) and (max-height: 540px) {
  #touch-controls {
    --stick-r: clamp(40px, 11vmin, 58px);
    --btn-jump: clamp(64px, 20vmin, 92px);
    --btn-sprint: clamp(50px, 15vmin, 68px);
  }
  #touch-move { height: 42%; height: 42dvh; }   /* look stays full-screen (inset:0); stick bottom-left */
  #touch-buttons { bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
}

/* Very short viewports (tiny phones in landscape): pin buttons even closer to the corner. */
@media (max-height: 380px) {
  #touch-buttons { gap: 10px; bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
}

/* ---- Objective HUD (NON-VR only) ----
   The coin counts (spendable balance + today's hunt progress) are one grouped cluster built in JS by
   coinHud.js (top-LEFT, clear of the top-centre jump/jet bars). VR stays HUD-free — the coin pop +
   chime + fanfare are the diegetic feedback there. */

#gl-lost {
  position: fixed; inset: 0; z-index: 50; display: grid; place-items: center;
  background: rgba(0, 0, 0, 0.6); color: #fff; font: 600 16px system-ui, sans-serif;
}
#gl-lost[hidden] { display: none; }
