/* Splitscreen UX demo.  The stage carries hud-* (classic | bars | minimal | shared),
   div-* (none | line | color) and players-N classes; HUD values arrive as custom
   properties on each .hud (--hp, --ammo, --cd, --hurt, --hit, --pickup, --hurtdir, --drop). */

:root {
  --p0: #ff3b30;  /* P1, red  (mirrors PLAYER_COLORS in tuning.js) */
  --p1: #2f7bff;  /* P2, blue */
  --bg: #120a24;
  --ink: #ffffff;
  --shadow: 0 0.08em 0 rgba(0, 0, 0, 0.6), 0 0 0.4em rgba(0, 0, 0, 0.5);
  --font: "Segoe UI", system-ui, sans-serif;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: #000; color: var(--ink); font-family: var(--font); overflow: hidden; }

/* The game is always 16:9: the biggest 16:9 box that fits the window, centred, with black
   bars on the long sides.  Views and HUDs size themselves from the stage. */
#stage {
  position: fixed; inset: 0; margin: auto; background: var(--bg); overflow: hidden;
  width: min(100vw, calc(100vh * 16 / 9));
  height: min(100vh, calc(100vw * 9 / 16));
}

/* ---- Views -------------------------------------------------------------------------- */

.view {
  position: absolute;
  overflow: hidden;
  display: none;
  container-type: size;
  background: #000;
}
.view.on { display: block; }
.view > canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* Dividers, only drawn with two players. */
.players-2.div-line .view::after,
.players-2.div-color .view::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 5;
}
.players-2.div-line .view::after { box-shadow: inset 0 0 0 2px #0a0614; }
.players-2.div-color .view::after { box-shadow: inset 0 0 0 max(4px, 1cqmin) var(--pcolor); }

/* ---- Layout editor (P): outlines, selection, view move/resize handles ---------------- */

#edit-bar {
  /* Placed by editor.js, which moves it out of the way of the HUD and the mouse. */
  display: none; position: fixed; top: 1.2vmin; left: 30vw; z-index: 90;
  transition: left 0.35s cubic-bezier(.3,.7,.2,1), top 0.35s cubic-bezier(.3,.7,.2,1);
  width: max-content; max-width: 44vw; text-align: center; font-size: 1.55vmin; line-height: 1.5;
  padding: 0.45em 1em; border-radius: 0.5em; background: rgba(10, 6, 20, 0.92); border: 0.12em solid #ffd34d;
}
#edit-bar.on { display: block; }
#edit-bar kbd { min-width: 1.2em; margin: 0 0.1em; }
#edit-bar .inv-on { color: #ffd34d; }
.view .hud { z-index: 2; }
/* Stand-in for the first-person launcher, so the editor can drag it: centred on the
   launcher's pivot (game.js, aimViewModel), invisible except while editing. */
.hud .vmgrab { position: absolute; left: 50%; top: 80.15%; width: 26cqh; height: 30cqh; transform: translate(-50%, -50%); }
.editing .hud .vmgrab { background: rgba(255, 255, 255, 0.06); }
.editing .view, .view.has-placed { overflow: visible; }   /* moved elements may sit outside */
.view.ux-front { z-index: 5; }                             /* the view being edited on top */
.vedit { display: none; position: absolute; inset: 0; z-index: 1; cursor: move; outline: 2px dashed rgba(255, 255, 255, 0.6); outline-offset: -2px; }
.editing .vedit { display: block; }
.vh { position: absolute; width: 14px; height: 14px; background: #ffd34d; border: 2px solid #000; border-radius: 3px; }
.vh.n, .vh.s { left: calc(50% - 7px); cursor: ns-resize; }
.vh.e, .vh.w { top: calc(50% - 7px); cursor: ew-resize; }
.vh.n, .vh.ne, .vh.nw { top: -7px; }
.vh.s, .vh.se, .vh.sw { bottom: -7px; }
.vh.e, .vh.ne, .vh.se { right: -7px; }
.vh.w, .vh.nw, .vh.sw { left: -7px; }
.vh.ne, .vh.sw { cursor: nesw-resize; }
.vh.nw, .vh.se { cursor: nwse-resize; }
.editing .hud [data-ux] { pointer-events: auto; cursor: grab; outline: 1px dashed rgba(255, 255, 255, 0.7); outline-offset: 3px; }
.editing .hud [data-ux]:hover { outline-color: #fff; }
.editing .hud [data-ux].ux-selected { outline: 2px solid #ffd34d; }
/* Placed by custom code (option 4's merging minimaps): not draggable. */
.editing .hud [data-ux].ux-custom { pointer-events: none; outline: 1px dotted rgba(255, 211, 77, 0.6); }
/* Vertex mode (V): corner handles above everything, and the selection box. */
#view-outlines { display: none; position: absolute; inset: 0; width: 100%; height: 100%; z-index: 29; pointer-events: none; overflow: visible; }
.editing #view-outlines { display: block; }
#view-outlines polygon { fill: none; stroke: rgba(255, 255, 255, 0.75); stroke-width: 2; stroke-dasharray: 6 4; }
.editing .view.warped .vedit { outline: none; }   /* the outline above shows the real shape */
#vtx-layer { display: none; position: absolute; inset: 0; z-index: 30; cursor: crosshair; }
.editing.vertex #vtx-layer { display: block; }
.editing.vertex .vh { display: none; }
.vtx { position: absolute; width: 10px; height: 10px; margin: -7px 0 0 -7px; background: #fff; border: 2px solid #000; border-radius: 50%; cursor: move; }
.vtx.vcorner { width: 12px; height: 12px; margin: -8px 0 0 -8px; background: #ffd34d; border-radius: 3px; }
.vtx.sel { background: #ff3bd0; box-shadow: 0 0 0 3px rgba(255, 59, 208, 0.45); }
.vtx.linked { background: #ff9be8; box-shadow: 0 0 0 3px rgba(255, 59, 208, 0.3); } /* follows the selection */
.vtx-marquee { display: none; position: absolute; border: 1px dashed #fff; background: rgba(255, 255, 255, 0.08); pointer-events: none; }
/* A view reshaped in vertex mode: only its clipped canvas shows. */
.view.warped { background: transparent; overflow: visible; }
.view.warped::after { display: none; }
/* Option 4's merged minimap (hud.js, MergedMinimap): over the map area, above the views. */
.merged-minimap { display: none; position: absolute; z-index: 6; pointer-events: none; }
/* Overlapping views cross-fade (main.js, blendOverlap): no backing or dividers in the way. */
.view.blending { background: transparent; }
.view.blending::after { display: none; }
body.editing-layout #notices { display: none; }

/* ---- Per-view HUD ------------------------------------------------------------------- */

.hud {
  position: absolute; inset: 0; pointer-events: none;
  font-size: clamp(12px, 5cqmin, 72px);
  text-shadow: var(--shadow);
  font-weight: 800;
  /* A little room for TV overscan. */
  --safe: 4cqmin;
}
.hud > * { position: absolute; }


/* Bottom left: the health bar (a fixed frame; the red fill shrinks to the left, with the
   number inside) and the level octagon beside it. */
.leftcluster { left: var(--safe); bottom: var(--safe); display: flex; align-items: center; gap: 0.3em; }
.healthbar {
  position: relative; width: 6.5em; height: 0.95em; border-radius: 0.22em; overflow: hidden;
  background: rgba(12, 12, 20, 0.72); box-shadow: 0 0 0 0.07em rgba(255, 255, 255, 0.85), 0 0.05em 0.2em rgba(0, 0, 0, 0.5);
}
.healthbar .hb-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: calc(var(--hp) * 100%);
  background: linear-gradient(#ff6b5e, #e3261b 55%, #b5160e); transition: width 0.15s ease-out;
}
.healthbar .hb-num {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 0.68em; color: #fff; letter-spacing: 0.04em;
  text-shadow: 0 0.06em 0 rgba(0, 0, 0, 0.7), 0 0 0.25em rgba(0, 0, 0, 0.6);
}
.hud.low .healthbar .hb-fill { animation: pulse 0.6s infinite alternate; }
@keyframes pulse { to { opacity: 0.55; } }
.level { width: 1.45em; height: 1.45em; overflow: visible; text-shadow: none; filter: drop-shadow(0 0.05em 0.12em rgba(0, 0, 0, 0.6)); }
.level .oct { fill: #fff; }
.level .oct-inner { fill: var(--pcolor); }
.level text { fill: #fff; text-anchor: middle; font-family: "Segoe UI", system-ui, sans-serif; font-weight: 800; }
.level .lvl-num { font-size: 48px; }
.level .lvl-label { font-size: 19px; letter-spacing: 1px; }

/* Right of the launcher: rocket count and invul skill, in a row.  (The grenade skill
   flanks the launcher on the left; see the grenade section.) */
.cluster { right: var(--safe); bottom: var(--safe); display: flex; align-items: flex-end; gap: 0.35em; }
.stat { display: flex; flex-direction: column; line-height: 1; }
.stat .label { font-size: 0.4em; letter-spacing: 0.15em; color: var(--pcolor); filter: brightness(1.3); }
.stat .num { color: color-mix(in srgb, var(--pcolor) 30%, white); }
.stat .num { font-size: 1.6em; }
.stat .bar { display: none; }
.hud.empty .ammo .num { color: #ff5a5a; }
.ammo .num { transform: scale(calc(1 + var(--pickup) * 0.3)); transform-origin: left bottom; }

/* Crosshair with the reload ring around it. */
.crosshair { left: 50%; top: 50%; width: 1.4em; height: 1.4em; transform: translate(-50%, -50%); }
.crosshair .dot {
  position: absolute; left: 50%; top: 50%; width: 0.18em; height: 0.18em;
  transform: translate(-50%, -50%); border-radius: 50%; background: #fff;
  box-shadow: 0 0 0 0.05em #000;
}
.crosshair .cd-ring {
  position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(var(--pcolor) calc((1 - var(--cd)) * 360deg), rgba(255,255,255,0.15) 0);
  -webkit-mask: radial-gradient(circle, transparent 58%, #000 60%, #000 72%, transparent 74%);
          mask: radial-gradient(circle, transparent 58%, #000 60%, #000 72%, transparent 74%);
  opacity: calc(0.25 + var(--cd) * 0.75);
}

.hitmarker {
  left: 50%; top: 50%; width: 2.2em; height: 2.2em; transform: translate(-50%, -50%) rotate(45deg);
  opacity: var(--hit);
  background:
    linear-gradient(#fff, #fff) center top / 0.12em 35% no-repeat,
    linear-gradient(#fff, #fff) center bottom / 0.12em 35% no-repeat,
    linear-gradient(#fff, #fff) left center / 35% 0.12em no-repeat,
    linear-gradient(#fff, #fff) right center / 35% 0.12em no-repeat;
}

.dmg-arrow {
  left: 50%; top: 50%; width: 0; height: 0; opacity: var(--hurt);
  transform: rotate(var(--hurtdir));
}
.dmg-arrow i {
  position: absolute; left: -0.9em; top: -5em; width: 1.8em; height: 1em;
  background: #ff3030; clip-path: polygon(50% 0, 100% 100%, 0 100%);
  filter: drop-shadow(0 0 0.2em #000);
}

.flash {
  inset: 0; opacity: calc(var(--hurt) * 0.45);
  background: radial-gradient(ellipse at center, transparent 30%, #ff1a1a 100%);
}
.vignette { inset: 0; opacity: 0; }

.leaving {
  left: 50%; top: 30%; transform: translateX(-50%); text-align: center; font-size: 0.6em;
  display: flex; flex-direction: column; gap: 0.3em; opacity: calc(var(--drop) * 10);
}
.leaving .bar { width: 8em; height: 0.35em; background: rgba(255,255,255,0.25); border-radius: 1em; overflow: hidden; }
.leaving .bar i { display: block; height: 100%; width: calc(var(--drop) * 100%); background: #fff; }

/* ---- Right-hand group placement ---------------------------------------------------------
   The health bar is always bottom left.  The right-hand group (grenade, rockets, invul)
   sits in the bottom-right corner by default ('corners'); 'flank' starts it just right of
   the launcher (which always takes the same share of the view's height, so the gap is in
   cqh); 'outer' moves P1's group to the top, beside the minimap. */

.stats-flank .cluster { right: auto; left: calc(50% + var(--flank)); }
.hud { --flank: 9cqh; }

.players-2.stats-outer .view.p0 .cluster { bottom: auto; top: var(--safe); right: calc(var(--safe) + var(--minimap) + 24px + 0.6em); align-items: flex-start; }
.players-2.stats-outer .view.p0 .ammo { flex-direction: column-reverse; }

/* ---- Minimap: top right of every view, rotated so up is the player's forward ---------- */

.hud { --minimap: min(32cqh, 14cqw); }
/* The canvas is 24px bigger than the map: room on every side for a 1px gap and the
   time-of-day dial (an 8px ring with 1.5px black edges), so the dial rings the map without
   covering it (see hud.js). */
.minimap { top: var(--safe); right: var(--safe); width: calc(var(--minimap) + 24px); height: calc(var(--minimap) + 24px); }

/* ---- Deep water: a countdown back to spawn, and a flash when it happens -------------- */

.deep {
  left: 50%; top: 22%; transform: translateX(-50%); display: none; text-align: center;
  flex-direction: column; align-items: center; gap: 0.15em; font-size: 0.7em;
}
.deep b { color: #7fd8ff; letter-spacing: 0.1em; }
.deep span { font-size: 0.7em; }
.deep .bar { width: 8em; height: 0.35em; background: rgba(255,255,255,0.25); border-radius: 1em; overflow: hidden; }
.deep .bar i { display: block; height: 100%; width: calc((1 - var(--deep)) * 100%); background: #7fd8ff; }
.hud.in-deep .deep { display: flex; }
.hud.in-deep .vignette { opacity: calc(0.3 + var(--deep) * 0.6); background: radial-gradient(ellipse at center, transparent 40%, rgba(10, 60, 140, 0.9) 100%); }
.respawn-flash { inset: 0; background: #fff; opacity: var(--respawn); }

/* ---- The invul skill: Y button and hourglass, to the right of the rocket count ---------
   hud.js shapes the sand. */

.skill {
  height: 1.6em; display: flex; align-items: center; gap: 0.18em; transform-origin: 50% 60%;
  text-shadow: none; /* the HUD's text shadow would otherwise double the SVG "Y" */
}
/* A dark round plate behind the hourglass, ringed in the player's colour, for legibility. */
.skill .badge {
  display: grid; place-items: center; width: 1.6em; height: 1.6em; border-radius: 50%;
  background: radial-gradient(circle, rgba(16, 20, 34, 0.9) 58%, rgba(16, 20, 34, 0.65) 100%);
  box-shadow: 0 0 0 0.055em var(--pcolor), 0 0.04em 0.18em rgba(0, 0, 0, 0.6);
}
.skill .ybtn { width: 0.78em; height: 0.78em; transition: filter 0.2s, opacity 0.2s; }
.skill .ybtn circle { fill: #f5c400; stroke: #000; stroke-width: 3; }
.skill .ybtn text { font: 800 24px "Segoe UI", system-ui, sans-serif; fill: #1a1a1a; text-anchor: middle; }
.skill.cooling .ybtn { filter: grayscale(1) brightness(0.65); opacity: 0.55; }
.skill .glass { height: 1.25em; width: 0.84em; overflow: visible; transform-origin: 50% 50%; }
.skill .frame { fill: rgba(255, 255, 255, 0.14); stroke: #fff; stroke-width: 2.5; stroke-linejoin: round; }
.skill .cap { fill: var(--pcolor); stroke: #000; stroke-width: 1.5; }
.skill .sand { fill: #ffd36b; }
.skill .stream { stroke: #ffd36b; stroke-width: 1.8; stroke-dasharray: 2 2.5; opacity: 0; }
/* Draining: the sand shimmers, grains fall, and electricity crackles (hud.js draws bolts). */
.skill.cooling .stream { opacity: 1; animation: grains 0.25s linear infinite; }
@keyframes grains { to { stroke-dashoffset: -4.5; } }
.skill.cooling .sand { animation: sand-shimmer 0.45s ease-in-out infinite alternate; }
@keyframes sand-shimmer { to { fill: #fff0b8; } }
.skill .bolt {
  fill: none; stroke: #d9f6ff; stroke-width: 1.3; stroke-linejoin: round; stroke-linecap: round;
  filter: drop-shadow(0 0 1.2px #8fe3ff) drop-shadow(0 0 3px #2f9bff);
}
/* Nearly drained: the hourglass pulses in size and colour. */
.skill.ending .glass { animation: skill-pulse 0.28s ease-in-out infinite alternate; }
@keyframes skill-pulse {
  from { transform: scale(1); }
  to { transform: scale(1.22); filter: drop-shadow(0 0 0.12em #fff) hue-rotate(-35deg) brightness(1.5); }
}
/* Fired: a quick pop.  Ready again: a half-second white glint round the whole element. */
.skill.fired { animation: skill-pop 0.35s ease-out; }
@keyframes skill-pop { from { transform: scale(1.45); } to { transform: scale(1); } }
.skill.ready-flash { animation: skill-shine 0.5s ease-out; }
@keyframes skill-shine {
  0% { filter: drop-shadow(0 0 0 #fff); }
  35% { filter: drop-shadow(0 0 0.06em #fff) drop-shadow(0 0 0.06em #fff) drop-shadow(0 0 0.35em #fff); }
  100% { filter: drop-shadow(0 0 0 rgba(255, 255, 255, 0)); }
}

/* ---- The grenade skill: a WWII "pineapple" grenade, just left of the launcher ---------
   Same draining language as the invul hourglass: yellow drains out over the cooldown
   (shimmer and crackle), pulses near the end, then snaps back full with a glint. */

.gskill {
  right: calc(50% + var(--flank)); bottom: var(--safe);  /* just left of the launcher */
  height: 1.6em; display: flex; align-items: center; gap: 0.18em; text-shadow: none; transform-origin: 50% 60%;
}
.hud-minimal .gskill { bottom: 28%; font-size: 0.75em; }
/* The button to press: an Xbox left trigger (controllers are the primary input). */
.gskill .ltbtn { width: 0.86em; height: 0.78em; transition: filter 0.2s, opacity 0.2s; }
.gskill .ltbtn path { fill: #2b2e36; stroke: #fff; stroke-width: 2.5; }
.gskill .ltbtn text { font: 800 17px "Segoe UI", system-ui, sans-serif; fill: #fff; text-anchor: middle; }
.gskill.cooling .ltbtn { filter: brightness(0.65); opacity: 0.55; }
.gskill .badge {
  display: grid; place-items: center; width: 1.6em; height: 1.6em; border-radius: 50%;
  background: radial-gradient(circle, rgba(16, 20, 34, 0.9) 58%, rgba(16, 20, 34, 0.65) 100%);
  box-shadow: 0 0 0 0.055em var(--pcolor), 0 0.04em 0.18em rgba(0, 0, 0, 0.6);
}
.gskill .nade { height: 1.3em; width: 0.87em; overflow: visible; transform-origin: 50% 55%; }
.gskill .body { fill: #4a5530; stroke: #12140c; stroke-width: 2; }
.gskill .fill { fill: #ffd36b; }
.gskill .grid { fill: none; stroke: rgba(10, 12, 6, 0.75); stroke-width: 1.6; stroke-linecap: round; }
.gskill .fuze { fill: #8b8f96; stroke: #12140c; stroke-width: 1.5; }
.gskill .lever { fill: #a3a8b0; stroke: #12140c; stroke-width: 1.5; }
.gskill .pin { fill: none; stroke: #d8dce2; stroke-width: 1.8; }
.gskill.cooling .fill { animation: sand-shimmer 0.45s ease-in-out infinite alternate; }
.gskill .bolt {
  fill: none; stroke: #d9f6ff; stroke-width: 1.3; stroke-linejoin: round; stroke-linecap: round;
  filter: drop-shadow(0 0 1.2px #8fe3ff) drop-shadow(0 0 3px #2f9bff);
}
.gskill.ending .nade { animation: skill-pulse 0.28s ease-in-out infinite alternate; }
.gskill.fired { animation: skill-pop 0.35s ease-out; }
.gskill.ready-flash { animation: skill-shine 0.5s ease-out; }

/* ---- HUD style: bars ---------------------------------------------------------------- */

.hud-bars .stat .num { font-size: 0.7em; }
.hud-bars .stat .bar {
  display: block; width: 7em; height: 0.45em; margin-top: 0.2em;
  background: rgba(0,0,0,0.45); border-radius: 0.3em; overflow: hidden;
  box-shadow: 0 0 0 0.06em rgba(255,255,255,0.6);
}
.hud-bars .stat .bar i { display: block; height: 100%; }
.hud-bars .ammo .bar i { width: calc(var(--ammo) * 100%); background: #ffb21f; }

/* ---- HUD style: minimal --------------------------------------------------------------
   No health bar (health is only a red vignette); the right-hand group sits small, centred
   above the launcher. */

.hud-minimal .leftcluster { display: none; }
.hud-minimal .vignette {
  opacity: calc((1 - var(--hp)) * 1.1);
  background: radial-gradient(ellipse at center, transparent 45%, rgba(200,0,20,0.9) 100%);
}
.hud-minimal .cluster { right: auto; left: 50%; bottom: 28%; transform: translateX(-50%); font-size: 0.75em; }
.hud-minimal .ammo { align-items: center; }
.hud-minimal .ammo .label { display: none; }
.hud-minimal .ammo .num { font-size: 0.8em; opacity: 0.9; }

/* ---- HUD style: shared --------------------------------------------------------------- */

#shared-hud { display: none; }
/* The shared HUD hides the per-view rocket count (it's on the seam), keeping the rest. */
.players-2.hud-shared .ammo { visibility: hidden; }
.players-2.hud-shared #shared-hud.on {
  display: flex; position: absolute; z-index: 10; transform: translate(-50%, -50%);
  gap: 1vmin; pointer-events: none; font-weight: 800; font-size: clamp(14px, 2.6vmin, 48px);
}
#shared-hud.vertical { flex-direction: column; }
#shared-hud .chip {
  display: flex; gap: 0.7em; align-items: center; padding: 0.35em 0.8em; border-radius: 0.5em;
  background: rgba(10, 6, 20, 0.85); border: 0.15em solid var(--pc);
}
#shared-hud .p0 { --pc: var(--p0); }
#shared-hud .p1 { --pc: var(--p1); }
#shared-hud .chip b { color: var(--pc); }

/* ---- Overlays ----------------------------------------------------------------------- */

#attract, #join-prompt { display: none; pointer-events: none; }
#attract.on {
  display: flex; position: absolute; inset: 0; flex-direction: column; align-items: center; justify-content: center;
  background: radial-gradient(circle at 30% 30%, var(--p0) 0, transparent 40%),
              radial-gradient(circle at 70% 70%, var(--p1) 0, transparent 45%), var(--bg);
  font-size: 3vmin; text-align: center;
}
#attract h1 { font-size: 2.6em; margin: 0 0 0.3em; text-shadow: var(--shadow); }
#attract .small, #help .small { opacity: 0.7; font-size: 0.75em; }
#join-prompt.on {
  display: block; position: absolute; right: 3vmin; bottom: 3vmin; z-index: 10;
  font-size: 2vmin; padding: 0.5em 1em; border-radius: 0.5em;
  background: rgba(10, 6, 20, 0.7); border: 0.12em solid var(--p1); animation: pulse 1s infinite alternate;
}

#banner {
  position: fixed; top: 4vmin; left: 50%; transform: translate(-50%, -20px); z-index: 50;
  font-size: 3vmin; font-weight: 800; padding: 0.4em 1.1em; border-radius: 0.5em;
  background: rgba(10, 6, 20, 0.85); opacity: 0; transition: opacity 0.2s, transform 0.2s; pointer-events: none;
}
#banner.on { opacity: 1; transform: translate(-50%, 0); }
body.editing-layout #banner { top: 12vmin; }   /* below the edit bar */
#banner small { display: block; text-align: center; font-size: 0.55em; font-weight: 600; opacity: 0.8; }

#help {
  display: none; position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 60;
  width: min(90vw, 900px); max-height: 90vh; overflow: auto;
  background: rgba(10, 6, 20, 0.92); border-radius: 1em; padding: 1.2em 1.8em; font-size: 2vmin;
}
#help.on { display: block; }
#help h2 { margin: 0.4em 0; font-size: 1.2em; }
#help ul { list-style: none; padding: 0; margin: 0 0 0.6em; columns: 2; }
#help li { padding: 0.15em 0; }
#help li.cur { color: #ffe14a; }
#diag {
  display: none; position: fixed; inset: 3vmin; z-index: 70; overflow: auto;
  background: rgba(8, 5, 16, 0.94); border-radius: 1em; padding: 1em 1.6em; font-size: 1.6vmin;
}
#diag.on { display: block; }
#diag h2 { margin: 0 0 0.5em; }
#diag h3 { margin: 1em 0 0.3em; font-size: 1.1em; opacity: 0.8; }
#diag .cols { display: grid; grid-template-columns: 1fr 1.6fr; gap: 2em; }
#diag table { border-collapse: collapse; }
#diag td { padding: 0.15em 1.2em 0.15em 0; vertical-align: top; }
#diag td:first-child { opacity: 0.7; white-space: nowrap; }
#diag .pad { background: rgba(255,255,255,0.06); border-radius: 0.6em; padding: 0.6em 0.9em; margin-bottom: 0.8em; }
#diag .pad-head { font-size: 1.15em; margin-bottom: 0.3em; }
#diag h4 { margin: 0.6em 0 0.2em; font-size: 0.95em; opacity: 0.8; }
#diag .badge { margin-left: 0.6em; padding: 0.05em 0.5em; border-radius: 0.3em; font-size: 0.8em; color: #000; font-weight: 800; }
#diag .badge.p0 { background: var(--p0); }
#diag .badge.p1 { background: var(--p1); }
#diag .badge.idle { background: #888; }
#diag .mono { font-family: ui-monospace, monospace; white-space: pre-wrap; }
#diag .small { font-size: 0.8em; opacity: 0.7; }
#diag .ok { color: #5dff8f; }
#diag .warn { color: #ffd34d; }
#diag .bad { color: #ff5a5a; }

/* All warnings and prompts live in one bottom-centre stack (index.html #notices): any
   that are showing stack upwards with a gap, so two can never overlap.  Add new ones there. */
#notices {
  position: fixed; left: 50%; bottom: 3vmin; transform: translateX(-50%); z-index: 80;
  display: flex; flex-direction: column; align-items: center; gap: 1vmin;
  width: max-content; max-width: 60vw; pointer-events: none; /* clear of the join prompt */
}
.notice {
  display: none; text-align: center; font-size: 1.9vmin; padding: 0.45em 1.1em; border-radius: 0.5em;
  background: rgba(10, 6, 20, 0.88); border: 0.12em solid #ffd34d;
}
.notice.on { display: block; }
#focus-warning { background: #ffd34d; color: #000; font-weight: 800; font-size: 2.2vmin; pointer-events: auto; cursor: pointer; }
#mouse-resume { font-weight: 800; font-size: 2.2vmin; border-color: var(--p0); }

kbd {
  display: inline-block; min-width: 1.6em; text-align: center; padding: 0 0.3em; margin-right: 0.4em;
  border-radius: 0.3em; background: #fff; color: #000; font-weight: 800; font-family: inherit;
}

/* ---- Gameplay panel (~ then G; gameplay-panel.js) ------------------------------------- */
#gameplay-panel {
  display: none; position: fixed; top: 2vh; right: 1.5vw; bottom: 2vh; width: min(560px, 46vw); z-index: 120;
  flex-direction: column; background: rgba(10, 6, 20, 0.95); border: 2px solid #ffd34d; border-radius: 10px;
  font-size: 13px; color: #f2f2f2; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6);
}
#gameplay-panel.on { display: flex; }
#gameplay-panel .gp-head { display: flex; align-items: baseline; gap: 8px; padding: 10px 12px; border-bottom: 1px solid #3a3050; }
#gameplay-panel .gp-head b { font-size: 16px; }
#gameplay-panel .gp-sub { opacity: 0.6; font-size: 11px; }
#gameplay-panel .gp-buttons { margin-left: auto; display: flex; gap: 6px; }
#gameplay-panel button { font: inherit; padding: 3px 10px; border-radius: 5px; border: 0; background: #3a4256; color: #fff; cursor: pointer; }
#gameplay-panel button[data-act="save"] { background: #2f7b3f; }
#gameplay-panel button:hover { filter: brightness(1.25); }
#gameplay-panel .gp-list { flex: 1; overflow-y: auto; padding: 4px 12px 10px; }
#gameplay-panel .gp-group { margin: 12px 0 4px; font-weight: 800; color: #ffd34d; text-transform: uppercase; font-size: 11px; letter-spacing: 0.06em; }
#gameplay-panel .gp-row { display: grid; grid-template-columns: 9.5em 1fr 6.5em 4.5em; align-items: center; gap: 8px; padding: 2px 4px; border-radius: 4px; }
#gameplay-panel .gp-row:hover { background: rgba(255, 255, 255, 0.06); }
#gameplay-panel .gp-row.changed .gp-label { color: #ffd34d; }
#gameplay-panel .gp-row.changed .gp-label::after { content: " •"; }
#gameplay-panel .gp-applies { font-style: normal; font-size: 9px; opacity: 0.6; border: 1px solid currentColor; border-radius: 3px; padding: 0 3px; }
#gameplay-panel input[type=range] { width: 100%; accent-color: #ffd34d; }
#gameplay-panel input[type=number] { width: 100%; box-sizing: border-box; font: inherit; background: #1d1830; color: #fff; border: 1px solid #4a4060; border-radius: 4px; padding: 2px 4px; }
#gameplay-panel .gp-unit { opacity: 0.6; font-size: 11px; }
#gameplay-panel .gp-hint { padding: 10px 12px; border-top: 1px solid #3a3050; min-height: 5.5em; line-height: 1.45; }
#gameplay-panel .gp-key { opacity: 0.45; font-family: monospace; font-size: 11px; }
#gameplay-panel .gp-extra { opacity: 0.6; font-size: 11px; }
