/* Arena 1 — shell + the Phase 4 HUD port (prototype's panel layout and
   palette, reference/prototype.html 14–78). */
:root {
  --ink: #170D2B; --sand: #F2D6A2; --coral: #FF7A59; --teal: #3EC5B4;
  --pink: #FF3D81; --fuel: #FFB13D;
  --mono: "Cascadia Mono", "JetBrains Mono", Consolas, monospace;
}
* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0; height: 100%; width: 100%;
  overflow: hidden; background: var(--ink); font-family: var(--mono);
}
#game {
  position: fixed; inset: 0;
  width: 100vw; height: 100vh;
  display: block; outline: none;
  touch-action: none;
}
/* MD 23 — CONTROLS MODAL. `booting` now means "the modal is up", not "a camera
   is flying somewhere": the world behind is the player's own spawn view, live
   and unmoved, so dismissing is a fade and never a cut. The HUD is dimmed
   rather than hidden — it belongs to the player, and the player is already
   here — and the OS arrow stays hidden throughout, because an arrow parked on
   a game canvas is the single loudest "this is broken" signal there is. */
/* Dim #hud AS A WHOLE, never child-by-child. A per-child rule sets opacity on
   elements that were deliberately hidden and drags them back into view — it
   surfaced the "CLICK FOR MOUSE LOOK" chip behind the modal, which is the one
   piece of instruction text this MD bans. Dimming the container leaves each
   child's own visibility rules intact. The modal is a sibling of #hud for the
   same reason: it must not inherit the dimming it causes. */
body.booting #hud { opacity: .18; transition: opacity .22s ease; }
body.booting #game, body.booting #hud { cursor: none; }
#game, #hud { cursor: none; }              /* the crosshair IS the cursor */

#controls {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  /* "Roughly a third of the screen each way" — clamped so it neither shrinks
     to unreadable on a laptop nor sprawls on a 4K display. */
  width: clamp(420px, 38vw, 640px); min-height: clamp(280px, 33vh, 420px);
  box-sizing: border-box; padding: 34px 38px 30px;
  display: grid; align-content: center; gap: 2px;
  opacity: 0; pointer-events: none; transition: opacity .22s ease;
  /* Arena 1's own chrome: the pause menu's dark plum panel, sand type, coral
     and teal accents. Deliberately not a browser dialog. */
  background: linear-gradient(180deg, rgba(30,20,38,.96), rgba(20,13,26,.97));
  border: 2px solid var(--coral); border-radius: 42px;
  box-shadow: 0 26px 70px rgba(0,0,0,.62), inset 0 1px 0 rgba(255,255,255,.06);
}
body.booting #controls { opacity: 1; pointer-events: auto; }

/* An affordance, not a call to action: quiet until you go looking for it. */
#controlsX {
  position: absolute; top: 10px; right: 12px;
  width: 34px; height: 34px; padding: 0; line-height: 1;
  background: none; border: 0; border-radius: 8px; cursor: pointer;
  font: inherit; font-size: 24px; color: var(--sand); opacity: .38;
  transition: opacity .15s ease, background .15s ease;
}
#controlsX:hover, #controlsX:focus-visible { opacity: .95; background: rgba(255,255,255,.07); }

#controlsRows { display: grid; gap: 14px; }
.ctlRow {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 18px;
}
.ctlAct {
  /* Large and sparse: five lines a new player reads at a glance, not a manual. */
  font-size: clamp(15px, 1.45vw, 21px); font-weight: 800; letter-spacing: .13em;
  color: var(--sand);
}
.ctlKeys { display: flex; align-items: center; gap: 7px; justify-self: end; }
.ctlKeys kbd {
  display: inline-grid; place-content: center; box-sizing: border-box;
  min-width: 2.2em; padding: .42em .6em;
  font: inherit; font-size: clamp(13px, 1.2vw, 18px); font-weight: 800; letter-spacing: .1em;
  color: var(--teal);
  background: rgba(255,255,255,.055);
  border: 2px solid rgba(255,255,255,.16);
  border-bottom-width: 4px;              /* reads as a keycap, not a chip */
  border-radius: 7px;
}
.ctlKeys kbd.wide { letter-spacing: .13em; }
.ctlKeys em {
  font-style: normal; font-size: clamp(10px, .85vw, 13px); letter-spacing: .1em;
  color: var(--sand); opacity: .55; margin-left: 2px;
}
@media (max-width: 560px) {
  #controls { width: min(92vw, 460px); padding: 26px 20px 22px; }
  .ctlRow { grid-template-columns: 1fr; gap: 6px; }
  .ctlKeys { justify-self: start; }
}
@media (prefers-reduced-motion: reduce) { #controls { transition: none } }



#hud {
  position: fixed; inset: 0;
  padding-top: var(--safe-top, 0px);   /* wrapper's setSafeTop lands here (Phase 6) */
  pointer-events: none;                /* gameplay clicks belong to the canvas —
                                          interactive HUD islands opt back in,
                                          the lesson Chomp's pause menu learned */
  user-select: none; -webkit-user-select: none;
  color: var(--sand);
}
.panel {
  position: absolute; background: rgba(23, 13, 43, .55);
  border: 1px solid rgba(242, 214, 162, .18);
  padding: 8px 12px; backdrop-filter: blur(2px);
}
#xh { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 22px; height: 22px; }
/* White, not the sand accent: the reticle is a sighting instrument, and it has
   to read the same against every surface in the level rather than tinting with
   the palette. */
#xh::before, #xh::after { content: ''; position: absolute; background: #fff; opacity: .9; }
#xh::before { left: 50%; top: 0; width: 2px; height: 100%; transform: translateX(-50%); }
#xh::after { top: 50%; left: 0; height: 2px; width: 100%; transform: translateY(-50%); }
#xh .gap { position: absolute; left: 50%; top: 50%; width: 8px; height: 8px; transform: translate(-50%, -50%); background: transparent; box-shadow: 0 0 0 3px var(--ink) inset; }
#hitmark { position: absolute; left: 50%; top: 50%; width: 30px; height: 30px; transform: translate(-50%, -50%) rotate(45deg); opacity: 0; transition: opacity .18s; }
#hitmark::before, #hitmark::after { content: ''; position: absolute; background: var(--pink); }
#hitmark::before { left: 50%; top: 0; width: 3px; height: 100%; transform: translateX(-50%); }
#hitmark::after { top: 50%; left: 0; height: 3px; width: 100%; transform: translateY(-50%); }
#hitmark.on { opacity: 1; transition: none; }

#hpPanel { left: 18px; bottom: 18px; width: 250px; }
.lbl { font-size: 10px; letter-spacing: .2em; opacity: .7; }
.bar { height: 10px; background: rgba(242, 214, 162, .12); margin-top: 5px; position: relative; }
#hpFill { height: 100%; width: 100%; background: var(--teal); transition: width .12s linear; }
#hpNum { position: absolute; right: 0; top: -16px; font-size: 12px; }
#fuelBar { height: 8px; margin-top: 9px; }
#fuelFill { height: 100%; width: 100%; background: var(--fuel); transition: width .08s linear; }
#fuelNum { position: absolute; right: 0; top: -15px; font-size: 11px; color: var(--fuel); }

#flowPanel { right: 18px; bottom: 18px; width: 260px; text-align: right; }
#flowNum { font-size: 28px; line-height: 1; color: var(--sand); }
#flowNum b { color: var(--coral); }
#flowBar { height: 6px; background: rgba(242, 214, 162, .12); margin-top: 6px; }
#flowFill { height: 100%; width: 0%; background: var(--coral); transition: width .05s linear; }
#pips { margin-top: 8px; display: flex; gap: 6px; justify-content: flex-end; }
.pip { width: 34px; height: 6px; background: rgba(242, 214, 162, .15); }
.pip.full { background: var(--pink); }
#alt { font-size: 11px; margin-top: 6px; opacity: .7; letter-spacing: .1em; }

#score { left: 18px; top: 18px; font-size: 12px; letter-spacing: .08em; }
#score b { color: var(--coral); font-size: 18px; }

/* --safe-right/--safe-top: insets the embed shell needs — the wrapper's exit
   chip owns the top-right corner (48px at 14px insets → a 62px square), so
   the perf panel shifts inward when framed. NOTE: #hud's padding does NOT
   move these panels (absolute children position against the padding box
   edge), which is why the insets live in the offsets themselves. */
#perf { right: calc(18px + var(--safe-right, 0px)); top: calc(18px + var(--safe-top, 0px)); font-size: 11px; text-align: right; line-height: 1.6; letter-spacing: .05em; }
#perf .dim { opacity: .55; }
#perf .lod-on { color: var(--teal); }

#feed { position: absolute; left: 50%; top: 60%; transform: translateX(-50%); text-align: center; font-size: 13px; letter-spacing: .15em; }
.feedMsg { opacity: 0; animation: feed 1.1s ease-out forwards; color: var(--coral); text-shadow: 0 0 12px rgba(255, 122, 89, .6); }
@keyframes feed {
  0% { opacity: 0; transform: translateY(8px); }
  15% { opacity: 1; transform: translateY(0); }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-10px); }
}

/* MD 13 weapon HUD. No transitions on the highlight — the active state must
   flip on the SAME frame as the 1/2 press, not ease toward it. */
#weapons { position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%); display: flex; align-items: flex-end; gap: 10px; }
/* Slot and glyph both scale — bumping only the slot leaves the icon a small
   mark in a bigger box. 76px at 74% puts the glyph at ~56px against the old
   ~35px, so the shapes are readable at a glance instead of squinted at. */
.wslot {
  position: relative; width: 76px; height: 76px; border-radius: 18px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(23, 13, 43, .5); border: 2px solid rgba(242, 214, 162, .22);
  color: var(--sand); opacity: .42;
}
.wslot svg { width: 74%; height: 74%; }
.wslot.on {
  opacity: 1; background: rgba(23, 13, 43, .85);
  border-color: #FFE7B0;
  box-shadow: 0 0 16px rgba(255, 231, 176, .35);
}
.wkey { position: absolute; top: 4px; right: 8px; font-size: 12px; opacity: .65; letter-spacing: 0; }
/* grapple: a state readout, not a slot — smaller, and the extra margin pushes
   the selectable pair to sit centred while the hook hangs off to the left */
/* Still smaller than the pair — it is a state readout, not a selectable slot —
   but scaled with them so the relationship holds rather than shrinking away. */
.wslot.grap { width: 56px; height: 56px; border-radius: 13px; margin-right: 16px; }
.wslot.grap.on {
  border-color: var(--cmenu-accent, #9EE02B);
  box-shadow: 0 0 14px var(--cmenu-accent, #9EE02B);
}

#hurtVig { position: absolute; inset: 0; box-shadow: inset 0 0 140px 40px rgba(255, 61, 129, .55); opacity: 0; transition: opacity .5s; }
#speedVig { position: absolute; inset: 0; box-shadow: inset 0 0 120px 10px rgba(255, 122, 89, .28); opacity: 0; transition: opacity .2s; }
#jetVig { position: absolute; inset: 0; box-shadow: inset 0 -80px 120px -20px rgba(255, 177, 61, .35); opacity: 0; transition: opacity .15s; }

.dmg { position: absolute; font-size: 15px; font-weight: bold; color: var(--sand); text-shadow: 0 0 6px var(--pink); pointer-events: none; transform: translate(-50%, -50%); }

#hud-boot {
  position: absolute; left: 50%; top: 12px; transform: translateX(-50%);
  font-size: 10px; font-weight: 700; letter-spacing: .22em; opacity: .4;
  /* the readout grows (room · role · corr …); never let it reach the corners
     where the wrapper's exit chip lives */
  max-width: calc(100% - 2 * (80px + var(--safe-right, 0px)));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* The one gesture pointer lock demands, invited by a chip instead of a title
   screen. Sits over the LIVE game; pointer-events stay off so the inviting
   click lands on the canvas underneath it. */
#lockHint {
  position: absolute; left: 50%; bottom: 96px; transform: translateX(-50%);
  padding: 8px 16px; border-radius: 999px;
  background: rgba(23, 13, 43, .72); border: 1px solid rgba(242, 214, 162, .28);
  font-size: 11px; font-weight: 700; letter-spacing: .22em; color: var(--sand);
  opacity: 0; transition: opacity .25s ease;
}
#lockHint.on { opacity: 1; animation: pulse 1.8s infinite; }
@keyframes pulse { 50% { opacity: .45; } }

/* MD 25 — LEADERBOARD. An overlay, never a mode: the game keeps rendering and
   the sim keeps running behind it, so it is deliberately compact and slightly
   transparent rather than a full-screen takeover you cannot see past. */
#board {
  position: fixed; top: 14%; left: 50%; transform: translateX(-50%);
  width: min(560px, 84vw); box-sizing: border-box;
  padding: 14px 16px 12px; border-radius: 14px;
  background: linear-gradient(180deg, rgba(30,20,38,.93), rgba(20,13,26,.95));
  border: 1px solid rgba(255,255,255,.14);
  box-shadow: 0 18px 50px rgba(0,0,0,.55);
  opacity: 0; pointer-events: none; transition: opacity .1s ease;
  font-size: 13px; letter-spacing: .08em;
}
body.board #board { opacity: 1; }
#boardHead, .boardRow {
  display: grid; grid-template-columns: 1fr 62px 62px 62px; gap: 8px; align-items: center;
}
#boardHead {
  font-size: 10px; letter-spacing: .22em; color: var(--sand); opacity: .5;
  padding-bottom: 8px; margin-bottom: 6px; border-bottom: 1px solid rgba(255,255,255,.12);
}
#boardHead span:not(:first-child), .boardRow span:not(:first-child) { text-align: right; }
.boardRow { padding: 5px 0; font-weight: 700; color: var(--sand); }
.boardRow + .boardRow { border-top: 1px solid rgba(255,255,255,.055); }
/* The accent dot ties a row to the pill you see in the world — the same colour
   that player wears — so the board is readable at a glance mid-fight. */
.boardRow .boardName { display: flex; align-items: center; gap: 9px; min-width: 0; }
.boardRow .boardDot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.boardRow .boardTag { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.boardRow.is-me { color: #fff; }
.boardRow.is-me .boardTag { text-decoration: underline; text-underline-offset: 3px; }
#boardEmpty { opacity: .5; padding: 6px 0; font-weight: 700; }
@media (prefers-reduced-motion: reduce) { #board { transition: none } }
