:root{color-scheme:dark;--accent:#c084fc;--ink:#07040f;--panel:#12091f}
/* min-height on BODY must be 100vh, not 100%, and that is not a style choice.
   A percentage min-height resolves against the containing block's HEIGHT, and
   html here only has a min-height — its height is auto — so `100%` resolved to
   zero and body collapsed to the height of its own content. The flex centering
   on the next line then had nothing to centre within, which pinned the game to
   the top of the screen: in fullscreen at 1080p these cabinets sat at y=0 with
   150px of dead space underneath, while waves 1 and 2 (which use 100vh) centred
   at 70px top and bottom. That is the "wave 3 sits higher" mismatch. */
*{box-sizing:border-box}html,body{margin:0;min-height:100vh;background:radial-gradient(circle at 50% 20%,#25103d,#07040f 68%);color:#ede9fe;font-family:Segoe UI,system-ui,sans-serif}
body{display:flex;align-items:center;justify-content:center;padding:16px;overflow:hidden}
.game{width:min(100%,1040px);text-align:center}.kicker{margin:0;color:#c4b5fd;font-size:.72rem;letter-spacing:.24em;text-transform:uppercase}
h1{margin:.15rem 0 .45rem;font:800 clamp(1.35rem,3vw,2.2rem) Georgia,serif;letter-spacing:.08em;color:#f5d0fe;text-shadow:0 0 24px var(--accent)}
.frame{position:relative;margin:auto;aspect-ratio:16/9;max-height:calc(100vh - 142px);border:2px solid color-mix(in srgb,var(--accent),#fff 15%);border-radius:14px;overflow:hidden;background:#05030b;box-shadow:0 0 44px color-mix(in srgb,var(--accent) 38%,transparent),inset 0 0 50px #000}
.frame:before{content:"";position:absolute;inset:0;z-index:3;pointer-events:none;background:repeating-linear-gradient(0deg,transparent 0 3px,rgba(2,0,8,.16) 3px 4px);mix-blend-mode:multiply}
.frame:after{content:"";position:absolute;inset:-1px;z-index:4;pointer-events:none;box-shadow:inset 0 0 75px 18px rgba(0,0,0,.68);border-radius:14px}
canvas{display:block;width:100%;height:100%;touch-action:none}.topbar{display:flex;justify-content:center;gap:1.25rem;margin:.5rem 0 0;font:700 .8rem ui-monospace,monospace}.topbar b{color:var(--accent)}
.controls{margin:.35rem 0 0;color:#a99ac2;font-size:.72rem}.overlay{position:absolute;inset:0;z-index:12;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:8%;background:linear-gradient(180deg,rgba(7,4,15,.9),rgba(18,9,31,.96));cursor:pointer}
.overlay.hidden{display:none}.overlay h2{margin:0 0 .5rem;color:#f5d0fe;font:800 clamp(1.5rem,4vw,2.5rem) Georgia,serif;text-shadow:0 0 22px var(--accent)}.overlay p{max-width:650px;margin:.2rem 0;color:#ddd6fe}.overlay .small{font-size:.8rem;color:#a78bfa}.overlay button,.icon{border:1px solid var(--accent);border-radius:999px;background:rgba(124,58,237,.18);color:#fff;padding:.6rem 1.25rem;margin-top:1rem;font-weight:800;letter-spacing:.08em;cursor:pointer}
.nav{position:fixed;top:10px;left:10px;z-index:20;display:flex;gap:.4rem}.nav a,.icon{color:#ddd6fe;text-decoration:none;background:rgba(7,4,15,.85);border:1px solid #5b3b83;border-radius:8px;padding:.38rem .65rem;font-size:.72rem}.tools{position:fixed;top:10px;right:142px;z-index:20;display:flex;gap:.35rem}.icon{margin:0;padding:.38rem .6rem}
.toast{position:absolute;top:14%;left:50%;transform:translateX(-50%);padding:.4rem .8rem;border-radius:999px;background:#12091fe6;border:1px solid var(--accent);font-weight:800;opacity:0;transition:opacity .2s;pointer-events:none}.toast.show{opacity:1}
@media(max-width:650px){body{padding:4px;align-items:flex-start}.game{padding-top:42px}.frame{max-height:calc(100vh - 132px)}.controls{font-size:.63rem}.topbar{gap:.65rem;font-size:.7rem}}
@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important;animation:none!important;transition:none!important}}
/* Fullscreen. arcade-controls.js injects `:fullscreen #gameCanvas{height:84vh;width:auto}`,
   written for games whose canvas is a direct child of body. Ours sits inside .frame, which
   caps itself at calc(100vh - 142px) and clips overflow — so that rule alone leaves the game
   its normal size, cropped, in a black screen. `html:fullscreen` (1,1,1) outranks it (1,1,0),
   which matters because their sheet is injected into head at runtime, after this file.
   Sizing is explicit rather than aspect-ratio: a block-level box with an explicit height and
   width:auto fills its container and drops the ratio, which would stretch the canvas.

   The canvas is now 1280x720 — the same 16:9 as waves 1 and 2 (960x540), see the VIEW_W
   comment in wave3.js — so 84vh here produces the same 83.8%-of-width presentation their
   rule does, instead of the 63% a 4:3 canvas gave. The border and glow are KEPT rather
   than zeroed: waves 1 and 2 carry their 2px purple frame into fullscreen, and dropping
   ours was the other half of why these cabinets looked like a different game. */
html:fullscreen body{padding:0}
html:fullscreen .kicker,html:fullscreen h1,html:fullscreen .controls{display:none}
html:fullscreen .game{width:100%}
html:fullscreen .frame{width:min(100vw,calc(84vh*16/9));height:min(84vh,calc(100vw*9/16));max-width:100vw;max-height:84vh;border-radius:0}
html:fullscreen .frame:after{border-radius:0}
html:fullscreen #gameCanvas{width:100%;height:100%;max-width:none}
html:-webkit-full-screen body{padding:0}
html:-webkit-full-screen .kicker,html:-webkit-full-screen h1,html:-webkit-full-screen .controls{display:none}
html:-webkit-full-screen .game{width:100%}
html:-webkit-full-screen .frame{width:min(100vw,calc(84vh*16/9));height:min(84vh,calc(100vw*9/16));max-width:100vw;max-height:84vh;border-radius:0}
html:-webkit-full-screen .frame:after{border-radius:0}
html:-webkit-full-screen #gameCanvas{width:100%;height:100%;max-width:none}
