:root {
  color-scheme: dark;
}

* {
  box-sizing: border-box;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* Page can scroll vertically (PART 3) when PLAY AREA + CONTROL AREA don't
   both fit the viewport height — only individual control widgets below
   opt back into touch-action:none to stop a drag on THEM from also
   panning the page. overscroll-behavior stops the iOS rubber-band bounce
   without blocking real scrolling. */
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  background: #0a0b0c;
  touch-action: pan-y;
  overscroll-behavior-y: contain;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

/* ---------- PLAY AREA ----------
   Game viewport only. Sized by flexbox (fills whatever space CONTROL AREA
   below doesn't need) — game.js's resize() reads THIS element's own
   getBoundingClientRect(), never window.innerWidth/innerHeight, so the
   game's W/H coordinate space is entirely independent of CONTROL AREA's
   height (PART 4). min-height is a floor so it never gets crushed to
   nothing on a very short viewport — the page scrolls instead (see html/
   body above). */
#play-area {
  position: relative;
  flex: 1 1 auto;
  min-height: 220px;
  width: 100%;
  background: #131416;
  overflow: hidden;
}

#game {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #131416;
}

/* PAUSE is the one control still drawn over PLAY AREA — a system-level
   button (not MOVE/AIM/SHOT/FLASH/STEALTH/DASH), anchored clear of
   the notch/Dynamic Island via safe-area-inset-top, out of the way of
   everything else which now lives in CONTROL AREA below. */
#pause-zone {
  position: absolute;
  top: max(10px, env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  width: 64px;
  height: 26px;
  touch-action: none;
}

/* SECTION S: literally uppercase "PAUSE" (see index.html), made to stand
   out a bit more than the previous plain gray look via a pale/light blue
   (never a flashy neon blue) — border/background/size all otherwise
   unchanged so #pause-zone's layout in CONTROL PANEL is untouched. */
#pause-button {
  position: absolute;
  inset: 0;
  border-radius: 6px;
  background: rgba(170, 210, 235, 0.1);
  border: 1px solid rgba(170, 210, 235, 0.4);
  color: rgba(200, 226, 245, 0.92);
  font-family: sans-serif;
  font-weight: 700;
  font-size: 10px;
  letter-spacing: 0.08em;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  outline: none;
  padding: 0;
  text-shadow: 0 0 6px rgba(170, 210, 235, 0.5);
}

#pause-button:active,
#pause-button.active {
  background: rgba(170, 210, 235, 0.22);
}

/* SECTION F: PAUSE turns red while player.stunned is true, reverting to
   the normal pale blue above the instant STUN clears (F-1) — toggled via
   the "stunned" class in game.js's updateStunVisuals(), never a separate
   element. */
#pause-button.stunned {
  background: rgba(235, 70, 60, 0.16);
  border-color: rgba(235, 90, 80, 0.55);
  color: rgba(255, 210, 205, 0.95);
  text-shadow: 0 0 6px rgba(235, 70, 60, 0.6);
}
#pause-button.stunned:active {
  background: rgba(235, 70, 60, 0.3);
}

/* ---------- CONTROL AREA ----------
   A separate DOM region in normal document flow BELOW #play-area — never
   an absolute/fixed overlay on top of the game view (PART 1/2/9). Visually
   distinct (own background + top border) so it reads as "this is the
   control panel" without being flashy (PART 13). Never receives any game
   drawing — it has no canvas, no game.js draw() call ever touches it
   (PART 14). touch-action:pan-y on the row itself lets a drag on the
   gaps BETWEEN controls scroll the page like anywhere else; every
   individual stick/button zone below overrides back to touch-action:none
   so operating a control never also pans the page (PART 15).
   PART 11-16 (this batch): the RANGE gauge is gone; the row is now a
   2-row COLUMN — a slim SECONDARY row (STEALTH/FLASH, right-aligned) sits
   above the main PRIMARY row (MOVE / AIM / SHOT+DASH, evenly spread) — so
   FLASH (secondary row, right edge) and DASH (primary row, right edge)
   land directly above/below each other, with STEALTH just to FLASH's
   left, matching the requested "STEALTH FLASH / (blank) DASH" cluster. */
#control-area {
  position: relative; /* SECTION E: anchors #control-blackout-overlay's absolute inset:0 */
  flex: 0 0 auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: #0c0d0f;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding: 10px max(14px, env(safe-area-inset-right)) max(10px, env(safe-area-inset-bottom)) max(14px, env(safe-area-inset-left));
  /* SECTION L: was pan-y — still lets a drag on the gaps between controls
     scroll the page like before, but "manipulation" additionally tells the
     browser this whole region's gestures are handled (pan + pinch, no
     double-tap-to-zoom), which is what actually stops a fast double-tap
     anywhere in CONTROL AREA (including the gaps, not just the individual
     stick/button zones below, which were already touch-action:none) from
     triggering Safari's page zoom. Page scroll outside CONTROL AREA is
     untouched (html/body's own pan-y is unrelated to this element). */
  touch-action: manipulation;
}

/* Secondary row: STEALTH/FLASH only, pinned to the right edge — the
   smaller of the two rows, sitting above the primary row (PART 15). */
#control-secondary-row {
  flex: 0 0 auto;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  width: 100%;
}

/* Primary row: MOVE / AIM / (SHOT+DASH) — the 3 main controls, spread with
   space-between so they land at roughly the left/center/right of CONTROL
   AREA's own width (PART 14) without hand-tuned percentage math (14-2's
   own "natural fit over exact math" preference). */
#control-primary-row {
  flex: 0 0 auto;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

/* SHOT + DASH share the primary row's right-hand slot — DASH sits directly
   under FLASH above it (PART 15's "DASH: 右下"), SHOT is the big primary
   control immediately to its left. */
#control-primary-right {
  flex: 0 0 auto;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
}

/* ---------- MOVE (ACTION) STICK ----------
   PART 13-2 (this batch): MOVE is now one of the 3 large PRIMARY controls
   (MOVE/AIM/SHOT) — base/knob/touch-area all sized up together from the
   previous compact footprint. Sized to match AIM STICK (PART 3/8/13-3) —
   see the landscape override further down, which enlarges further still
   (ample width, scarce height there), and the short-landscape override,
   which pulls back toward the 44px comfortable-touch floor when height is
   extremely scarce. */
#action-stick-zone {
  position: relative;
  width: 88px;
  height: 88px;
  flex-shrink: 0;
  pointer-events: auto;
  touch-action: none;
}

#action-stick-base {
  position: absolute;
  inset: 4%;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  border: 2px solid rgba(255, 255, 255, 0.18);
  touch-action: none;
}

/* PART 13-2: "MOVE" label — purely decorative text near the top of the
   base circle (never at dead-center, so it's never fully hidden under the
   knob's own resting position) — pointer-events:none so it never
   interferes with the drag/touch handling below it. */
#action-stick-label {
  position: absolute;
  top: 8%;
  left: 0;
  right: 0;
  text-align: center;
  font-family: sans-serif;
  font-weight: 700;
  font-size: 9px;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.4);
  pointer-events: none;
  touch-action: none;
}

#action-stick-knob {
  position: absolute;
  width: 42%;
  height: 42%;
  left: 29%;
  top: 29%;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.35);
  border: 2px solid rgba(255, 255, 255, 0.5);
  touch-action: none;
  will-change: transform;
}

/* ---------- AIM STICK ----------
   Same footprint as MOVE STICK (PART 8/13-3), fully contained within
   CONTROL AREA's own height — no longer taller than the SHOT cluster next
   to it (PART 7/11). */
#aim-stick-zone {
  position: relative;
  width: 88px;
  height: 88px;
  flex-shrink: 0;
  pointer-events: auto;
  touch-action: none;
}

#aim-stick-base {
  position: absolute;
  inset: 4%;
  border-radius: 50%;
  background: rgba(80, 160, 255, 0.08);
  border: 2px solid rgba(120, 190, 255, 0.28);
  touch-action: none;
  overflow: hidden; /* clips #aim-stick-sector to the circle */
}

/* PART 9 (prior batch) removed the old +-60deg wedge — this just paints
   the whole circle as reachable now (see updateAimSectorOverlay() in
   game.js). */
#aim-stick-sector {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  touch-action: none;
}

/* PART 13-3: "AIM" label — same treatment as MOVE's own label above. */
#aim-stick-label {
  position: absolute;
  top: 8%;
  left: 0;
  right: 0;
  text-align: center;
  font-family: sans-serif;
  font-weight: 700;
  font-size: 9px;
  letter-spacing: 0.08em;
  color: rgba(180, 220, 255, 0.5);
  pointer-events: none;
  touch-action: none;
  z-index: 1;
}

#aim-stick-knob {
  position: absolute;
  width: 40%;
  height: 40%;
  left: 30%;
  top: 30%;
  border-radius: 50%;
  background: rgba(150, 205, 255, 0.4);
  border: 2px solid rgba(180, 220, 255, 0.65);
  touch-action: none;
  will-change: transform;
}

/* ---------- SHOT (FIRE) zone ----------
   PART 12: the RANGE gauge that used to live here has been removed
   entirely (no player-adjustable aim-guide length control any more — see
   AIM_GUIDE_LEN in game.js). PART 13-5/13-7: SHOT is now one of the 3
   large PRIMARY controls (same footprint as MOVE/AIM), reading as "SHOT"
   in the UI while every internal identifier (fire-button, fire(), FIRE_*)
   stays exactly as-is (13-6) — only the visible label text changed, in
   index.html. */
#fire-zone {
  position: relative;
  width: 92px;
  height: 92px;
  flex-shrink: 0;
  pointer-events: auto;
  touch-action: none;
}

/* ---------- Secondary cluster (FLASH / STEALTH / DASH) ----------
   Smaller than the 3 primary controls (PART 15-2/15-3's own size
   priority: MOVE/AIM/SHOT > FLASH/STEALTH/DASH > PAUSE), laid out via
   #control-secondary-row/#control-primary-right rather than the old 2x2
   grid — see index.html for the DOM structure. */
#flash-zone, #stealth-zone, #dash-zone, #reload-zone {
  position: relative;
  width: 56px;
  height: 56px;
  flex-shrink: 0;
  pointer-events: auto;
  touch-action: none;
}

#fire-button {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: rgba(200, 40, 30, 0.35);
  border: 2px solid rgba(255, 120, 100, 0.6);
  color: #ffe6e0;
  font-family: sans-serif;
  font-weight: bold;
  font-size: 13px;
  letter-spacing: 0.05em;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  outline: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

#fire-button:active,
#fire-button.active {
  background: rgba(255, 60, 40, 0.6);
}

/* SECTION D: 30-shot magazine cooldown ring — same visual language as the
   STEALTH cooldown ring above (an SVG circle whose stroke-dashoffset is
   driven from JS), reused rather than a new gauge concept. */
#fire-button.depleted {
  background: rgba(90, 20, 15, 0.55);
  border-color: rgba(150, 60, 50, 0.6);
}
#fire-cooldown-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.fire-ring-bg {
  fill: none;
  stroke: rgba(255, 255, 255, 0.12);
  stroke-width: 5;
}
#fire-ring-progress {
  fill: none;
  stroke: rgba(255, 140, 110, 0.9);
  stroke-width: 5;
  stroke-linecap: round;
  transform-origin: 50% 50%;
  transform: rotate(-90deg);
}
#fire-label {
  position: relative;
  z-index: 1;
}

/* SECTION E: STUN's CONTROL PANEL blackout — covers ONLY #control-area
   (its own position:relative anchors this), toggled by game.js's
   updateStunVisuals() via the "hidden" attribute. A real, opaque-ish black
   layer physically sitting on top of MOVE/AIM/FIRE/DASH/FLASH/STEALTH
   (E-3), but never removes them from the DOM (E-1) — #pause-zone lives
   outside #control-area entirely, so PAUSE is never covered by this. */
#control-blackout-overlay {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(4, 4, 5, 0.94);
  touch-action: none;
}
#control-blackout-overlay[hidden] { display: none; }
#control-blackout-message {
  font-family: sans-serif;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.04em;
  text-align: center;
  color: rgba(255, 150, 40, 0.9);
  padding: 0 24px;
}

/* PART7 SECTION O: circular manual RELOAD button, same size/shape language
   as STEALTH/FLASH — dim by default, brightens (.usable) only while ammo is
   1-29 and no reload is already in progress (game.js toggles the class). */
#reload-button {
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.05);
  border: 2px solid rgba(140, 170, 255, 0.35);
  color: #d8e2ff;
  font-family: sans-serif;
  font-weight: bold;
  font-size: 8px;
  letter-spacing: 0.03em;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  outline: none;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: filter 120ms ease, background 120ms ease;
  opacity: 0.55;
}
#reload-button:active {
  background: rgba(140, 170, 255, 0.18);
}
#reload-button.usable {
  opacity: 1;
  background: rgba(140, 170, 255, 0.14);
  border-color: rgba(170, 195, 255, 0.8);
}
#reload-label {
  position: relative;
  z-index: 1;
}

#stealth-button {
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.05);
  border: 2px solid rgba(120, 230, 160, 0.45);
  color: #d8ffe6;
  font-family: sans-serif;
  font-weight: bold;
  font-size: 8px;
  letter-spacing: 0.03em;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  outline: none;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: filter 120ms ease, background 120ms ease;
}
#stealth-button:active {
  background: rgba(120, 230, 160, 0.18);
}
#stealth-button.ready {
  background: rgba(120, 230, 160, 0.14);
  border-color: rgba(150, 240, 180, 0.75);
}
#stealth-button.active-effect {
  background: rgba(90, 220, 140, 0.3);
  border-color: rgba(150, 255, 190, 0.9);
}
#stealth-cooldown-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.stealth-ring-bg {
  fill: none;
  stroke: rgba(255, 255, 255, 0.12);
  stroke-width: 5;
}
#stealth-ring-progress {
  fill: none;
  stroke: rgba(120, 230, 160, 0.9);
  stroke-width: 5;
  stroke-linecap: round;
  transform-origin: 50% 50%;
  transform: rotate(-90deg);
}
#stealth-label {
  position: relative;
  z-index: 1;
}

#flash-button {
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.05);
  border: 2px solid rgba(255, 225, 140, 0.45);
  color: #fff2c8;
  font-family: sans-serif;
  font-weight: bold;
  font-size: 8px;
  letter-spacing: 0.05em;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  outline: none;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: filter 120ms ease, background 120ms ease;
}
#flash-button:active {
  background: rgba(255, 225, 140, 0.18);
}
#flash-button.ready {
  background: rgba(255, 225, 140, 0.14);
  border-color: rgba(255, 235, 170, 0.75);
}
#flash-button.too-close {
  filter: brightness(0.5);
  border-color: rgba(255, 90, 80, 0.85);
  background: rgba(255, 60, 50, 0.14);
}
#flash-cooldown-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.flash-ring-bg {
  fill: none;
  stroke: rgba(255, 255, 255, 0.12);
  stroke-width: 5;
}
#flash-ring-progress {
  fill: none;
  stroke: rgba(255, 225, 120, 0.9);
  stroke-width: 5;
  stroke-linecap: round;
  transform-origin: 50% 50%;
  transform: rotate(-90deg);
}
#flash-label {
  position: relative;
  z-index: 1;
}

#dash-button {
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.05);
  border: 2px solid rgba(150, 170, 255, 0.5);
  color: #e2e6ff;
  font-family: sans-serif;
  font-weight: bold;
  font-size: 8px;
  letter-spacing: 0.05em;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  outline: none;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 120ms ease;
}
#dash-button:active,
#dash-button.active {
  background: rgba(150, 170, 255, 0.3);
}

/* Landscape: this game is primarily played in landscape (PART 17) — the
   3-group row is already horizontal, so this just enlarges everything a
   little (ample width to spare) while keeping CONTROL AREA as low as
   possible when screen height is scarce (as low as ~360-400px on a phone
   in landscape). MOVE/AIM stay side by side and the button grid stays
   2x2 — only the pixel sizes change, not the structure. */
@media (orientation: landscape) {
  #control-area { gap: 6px; padding-top: 6px; padding-bottom: max(6px, env(safe-area-inset-bottom)); }
  #control-secondary-row, #control-primary-right { gap: 12px; }
  #action-stick-zone, #aim-stick-zone { width: 104px; height: 104px; }
  #fire-zone { width: 108px; height: 108px; }
  #flash-zone, #stealth-zone, #dash-zone, #reload-zone { width: 64px; height: 64px; }
}

/* Very short landscape viewports (PART 45/46) — e.g. iPhone SE/mini-class
   phones land around 300-345px tall, where #play-area's 220px floor plus
   the block above's ~127px-tall CONTROL AREA (347px combined) no longer
   fits and previously pushed CONTROL AREA below the visible viewport
   (PART 43's bug). This tier shrinks CONTROL AREA further on top of the
   sizes above and lowers PLAY AREA's own floor so both fit without
   relying on the page-scroll fallback for realistic devices — touch
   targets stay at 44px, the accepted minimum comfortable touch size, so
   they never get "impractically small" (PART 45). The page-scroll
   fallback from html/body above is kept for anything shorter than this
   tier still handles (PART 47). */
@media (orientation: landscape) and (max-height: 360px) {
  #play-area { min-height: 130px; }
  #control-area { gap: 4px; padding-top: 4px; padding-bottom: max(4px, env(safe-area-inset-bottom)); }
  #control-secondary-row, #control-primary-right { gap: 6px; }
  #action-stick-zone, #aim-stick-zone { width: 68px; height: 68px; }
  #fire-zone { width: 72px; height: 72px; }
  #flash-zone, #stealth-zone, #dash-zone, #reload-zone { width: 46px; height: 46px; }
}

/* SECTION M: portrait — the primary target orientation (per PART 14's own
   "iPhoneで自然" instruction) — height is the scarce dimension, so CONTROL
   AREA's own padding/row-gap is kept tight; MOVE/AIM/SHOT/FLASH/STEALTH/
   DASH sizes themselves are the base rules above (already sized for
   portrait) and are NOT shrunk further here (M-2 explicitly forbids
   smaller touch targets). */
@media (orientation: portrait) {
  #control-area {
    gap: 6px;
    padding: 6px max(12px, env(safe-area-inset-right)) max(6px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left));
  }
}

/* SECTION N: landscape stages aren't finished yet — block play until they
   are, without touching any of the underlying landscape CSS/AREA system
   above (kept for future reuse, per instruction). Pure media-query driven
   (no JS polling needed to decide visibility) so it's always in perfect
   sync with the actual device orientation; game.js's own render loop reads
   the SAME (orientation: landscape) media feature via matchMedia() to
   freeze update()/draw() while this is shown, and resumes instantly (no
   reload) the moment the query stops matching. z-index clears #mode-menu's
   own 10 so this covers the PAUSE menu too — everything genuinely stops. */
#landscape-block-overlay {
  display: none;
}
@media (orientation: landscape) {
  #landscape-block-overlay {
    display: flex;
    position: fixed;
    inset: 0;
    z-index: 20;
    align-items: center;
    justify-content: center;
    background: rgba(6, 8, 10, 0.97);
    padding: 24px;
  }
}
#landscape-block-message {
  color: rgba(225, 235, 240, 0.92);
  font-family: sans-serif;
  font-weight: 600;
  font-size: 16px;
  letter-spacing: 0.05em;
  text-align: center;
  max-width: 320px;
}

/* ---------- SECTION G/H/I/J: LOADING / OPENING / MAIN MENU ----------
   Each is position:fixed/inset:0, shown one at a time via [hidden]
   (game.js's screen state machine — see setScreen()) — stacked below the
   landscape-block-overlay (z-index 20) so landscape always wins over any
   of them, and #setting-panel sits above both PAUSE MENU and MAIN MENU so
   it can overlay either one. */
/* SECTION G/H (this turn): no "Loading..." text, no percent — a minimal
   horizontal progress bar only, filled from real asset-preload progress
   (see initLoadingSequence() in game.js — computeProgress()/tick() are
   unchanged; only the DISPLAY is now a bar width instead of text). */
#loading-screen {
  position: fixed;
  inset: 0;
  z-index: 14;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
  opacity: 1;
  transition: opacity 250ms ease; /* H-6: fades out naturally instead of an instant cut */
}
#loading-screen.loading-fade-out { opacity: 0; }
#loading-screen[hidden] { display: none; }
/* PART 9 SECTION D: full-bleed muted background loop, sat behind the
   existing progress bar (bar is a later sibling, so it naturally paints on
   top with no z-index needed within this one screen). */
#loading-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* DARK OUT PART 11 SECTION 1-1: the visual gauge is removed outright per
   real-device feedback — game.js's own internal readiness-tracking
   (computeProgress()/tick()) is completely unchanged and still updates
   this element's width every tick, it's simply never shown to the player
   any more (loading.mp4 + TAP TO START is the only visible loading UI). */
#loading-bar-track {
  display: none;
  width: 50%; /* H-5: ~40-60% of screen width on portrait */
  max-width: 220px;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.12);
  overflow: hidden;
}
#loading-bar-fill {
  height: 100%;
  width: 0%;
  background: rgba(220, 225, 230, 0.85);
  transition: width 100ms linear;
}

#opening-screen {
  position: fixed;
  inset: 0;
  z-index: 13;
  background: #000;
  overflow: hidden;
}
#opening-screen[hidden] { display: none; }
#opening-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* DARK OUT PART 11 SECTION 1-2: real loading.mp4 frame inspection shows
   "NOW LOADING..." sitting at roughly the vertical center (~46-52% of
   frame height) — TAP TO START must sit clearly BELOW that, never
   overlapping it, so this is anchored toward the bottom instead of
   centered (was the direct cause of the real-device "DARK OUT text and TAP
   TO START overlapping" complaint, since start_display.mp4's own "DARK
   OUT" burn-in sits at that same center band too). */
#opening-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding-bottom: 20vh;
  gap: 22px;
  background: rgba(0, 0, 0, 0.15);
  touch-action: manipulation;
}
/* SECTION D: explicit [hidden] override — #opening-overlay is an ID
   selector, which otherwise outranks the browser's own default
   `[hidden]{display:none}` (an attribute selector), so without this rule
   setting .hidden=true on this element (done by setScreen() when advancing
   to MAIN MENU) would not actually hide it. Same pattern already used by
   #loading-screen/#opening-screen/#setting-panel elsewhere in this file. */
#opening-overlay[hidden] { display: none; }

/* SECTION C: sharp, industrial, futuristic red — styled with the attached
   mask artwork used purely as a REFERENCE (heavy geometric caps, wide
   tracking, hard-edged red against black), never a crop/embed of the image
   itself and never built from a flat single-color "neon tube" glow: the
   fill is a white-to-red-to-black vertical gradient (clipped to the text)
   so the letterforms read as lit metal/plating, with a tight red bloom and
   a slight forward skew for a "sharp" rather than "gothic serif" feel
   (replacing the previous Georgia/serif treatment). No new font files —
   built from the existing bold sans-serif system stack only. */
/* PART 9 SECTION D: #opening-video now plays start_display.mp4, which
   already has "DARK OUT" burned into the footage itself throughout its
   entire loop (confirmed by frame inspection) — this text overlay is kept
   in the DOM (harmless, unused) but hidden outright to avoid a duplicate
   title stacked on top of the video's own. */
#opening-title {
  display: none;
  font-family: 'Arial Narrow', 'Helvetica Neue', Arial, sans-serif;
  font-weight: 900;
  /* Sized to always fit on one line within a narrow portrait viewport
     (390px-class phones included) with room to spare for the letter-
     spacing below — #opening-screen clips overflow, so this must never
     run past the edges the way an unconstrained 15vw/0.16em combination
     did during verification. */
  font-size: clamp(30px, 10vw, 72px);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  max-width: 92vw;
  text-align: center;
  transform: skewX(-4deg);
  color: #f4211f;
  background: linear-gradient(180deg, #ffffff 0%, #ff3a2f 42%, #7a0000 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  -webkit-text-stroke: 1px rgba(15, 0, 0, 0.7);
  text-shadow:
    0 0 10px rgba(255, 30, 20, 0.65),
    0 0 26px rgba(200, 0, 0, 0.4),
    0 3px 0 rgba(0, 0, 0, 0.8);
}
#opening-tap-prompt {
  font-family: sans-serif;
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.25em;
  color: rgba(230, 220, 220, 0.85);
  animation: opening-tap-pulse 1.6s ease-in-out infinite;
}
@keyframes opening-tap-pulse {
  0%, 100% { opacity: 0.45; }
  50% { opacity: 1; }
}

/* SECTION D: the OPENING video must stay visible and be the focus behind
   MAIN MENU, so this is deliberately NOT a boxed/paneled screen (unlike the
   removed #main-menu-screen/#main-menu-panel it replaces) — plain vertical
   text floating directly over the video, with only a thin translucent
   scrim (not opaque) so the footage reads through clearly. */
/* PART 2 SECTION A: TRAINING's BASIC/SECURITY submenu shares this exact
   rule with #main-menu-overlay — same plain-text/left-aligned/no-card
   layout, zero duplicated styling. DARK OUT PART 3: BOSS SELECT
   (#boss-select-overlay) joins the same shared rule for the same reason —
   no new design system, per spec section 22. DARK OUT PART 8: SCENARIO
   SELECT (#scenario-select-overlay) joins for the same reason again. */
/* DARK OUT PART 11 SECTION 5-1: real start_display.mp4 frame inspection
   shows "DARK OUT" burned into the footage at roughly the vertical center
   (~46-56% of frame height, the exact same band loading.mp4's own "NOW
   LOADING..." occupies) — real-device feedback confirmed the MENU items
   were overlapping it there. Anchored toward the bottom instead of
   centered so the whole 4-item group sits clearly below the logo. */
#main-menu-overlay, #training-select-overlay, #boss-select-overlay, #scenario-select-overlay, #main-scenario-sub-overlay, #secret-scenario-sub-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  /* SECTION O: left-aligned instead of centered — O-2's own safe margin
     (5-10vw on a 390px-class portrait phone) keeps it clear of the screen
     edge; horizontal placement is unaffected by PART 11's vertical change
     just above. */
  align-items: flex-start;
  justify-content: flex-end;
  padding-bottom: 12vh;
  gap: 21px; /* PART 11 SECTION 5-3: 30px * 0.70 first-pass, compacting the 4-item group */
  padding-left: 8vw;
  background: rgba(0, 0, 0, 0.2);
  touch-action: manipulation;
}
#main-menu-overlay[hidden], #training-select-overlay[hidden], #boss-select-overlay[hidden], #scenario-select-overlay[hidden], #main-scenario-sub-overlay[hidden], #secret-scenario-sub-overlay[hidden] { display: none; }
/* HOTFIX SECTION 11: BOSS SELECT has 6 rows total (title + 4 targets + BACK)
   vs SCENARIO SELECT's 4 (title + 2 + BACK) — under the SHARED bottom-
   anchored rule above (justify-content:flex-end), more rows above a
   flush-to-bottom BACK button pushes the whole group's TOP edge higher up
   the screen, which is exactly why BOSS SELECT's title was landing inside
   the DARK OUT logo band (~46-56vh) even after the previous session's fix
   (which only restored the shared bottom-anchor, without accounting for
   BOSS SELECT's own larger row count). A byte-for-byte identical title Y
   AND identical BACK Y is not achievable at once with 2 extra full-height
   rows in between at real button font-size (the math: fitting 4 real-height
   rows in the same span SCENARIO's 2 rows use would need a negative gap) —
   so this reclaims vertical room instead: a smaller (but still clearly
   separated) inter-row gap and a smaller bottom margin, calibrated so the
   title clears the logo band with real margin across the 3 required test
   viewports (390x844/375x667/320x568) and BACK stays fully on-screen with
   its own safe margin. SCENARIO/TRAINING SELECT keep the original 21px
   gap/12vh margin via the shared rule above, completely untouched. */
#boss-select-overlay {
  gap: 6px;
  padding-bottom: 2vh;
}
.main-menu-item {
  font-family: 'Arial Narrow', 'Helvetica Neue', Arial, sans-serif;
  font-weight: 700;
  font-size: 16px; /* PART 11 SECTION 5-2: 20px * 0.82 first-pass, still comfortably readable on iPhone portrait */
  letter-spacing: 0.3em;
  text-transform: uppercase;
  text-align: left; /* O-3 */
  color: rgba(235, 235, 238, 0.88);
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(230, 60, 50, 0);
  padding: 4px 10px 8px;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: color 120ms ease, border-color 120ms ease, text-shadow 120ms ease;
}
/* Selection state is only a subtle red glow / thin underline / brightness
   change (SECTION D's own explicit instruction) — never a boxed/panel
   highlight. */
.main-menu-item:active {
  color: #ffffff;
  border-bottom-color: rgba(230, 60, 50, 0.85);
  text-shadow: 0 0 14px rgba(230, 40, 30, 0.75);
}
/* DARK OUT PART 3 SECTION 4/28: ROID1/ROID2/ADAM in BOSS SELECT — shown
   (never hidden) but visually muted so tapping them doesn't look like it
   did anything (their click handlers are no-ops — see game.js
   startBossBattle()). Never a paywall/lock-icon treatment (section 5). */
.main-menu-item-locked {
  opacity: 0.45;
  cursor: default;
}
.main-menu-item-locked:active {
  color: rgba(235, 235, 238, 0.88);
  border-bottom-color: rgba(230, 60, 50, 0);
  text-shadow: none;
}
/* POST-v2.0 SECTION 5-3: a small, restrained "LOCKED" hint next to SECRET
   SCENARIO while unset — never silent/no-feedback, never a large badge. */
.locked-label {
  display: inline-block;
  margin-left: 0.6em;
  font-size: 0.6em;
  letter-spacing: 0.15em;
  color: rgba(230, 60, 50, 0.75);
  vertical-align: middle;
}
.locked-label[hidden] { display: none; }
/* DARK OUT PART 3 SECTION 22: BOSS SELECT's own minimal title — same
   font-family/letter-spacing/uppercase convention as .main-menu-item
   above, just non-interactive and in the existing DARK OUT red accent. */
.boss-select-title {
  font-family: 'Arial Narrow', 'Helvetica Neue', Arial, sans-serif;
  font-weight: 700;
  font-size: 22px;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: rgba(230, 60, 50, 0.9);
}
/* POST-v2.0 SECTION 1/6: the PART 11-era top-anchored override this rule
   used to carry (justify-content:flex-start; padding-top:58vh) pushed BOSS
   SELECT's BACK button below the fold on shorter real-device viewports —
   confirmed via measurement at 375x667 (BACK rendered fully off-screen,
   top-anchoring at 58vh plus 6 rows of content overflowing past the
   viewport bottom with nothing to clamp it back on screen). Bottom-
   anchoring (the shared rule above, same as SCENARIO SELECT/MAIN SUB
   MENU/SECRET SUB MENU) guarantees BACK always sits exactly padding-bottom
   (12vh) from the actual viewport bottom regardless of row count or
   viewport height, which both fixes the regression and satisfies section
   6's "BACK position unified across every SELECT-family menu" requirement
   literally (identical padding-bottom on every one of them). The one
   tradeoff — BOSS SELECT's title floats higher (closer to the DARK OUT
   logo band) than SCENARIO SELECT's own title on tall viewports, since it
   has more rows above BACK — is purely cosmetic text-over-video overlap,
   not a functional/navigation-blocking issue like the BACK regression was. */

/* SECTION Q/R: RESULT — a real DOM screen (like MAIN MENU), shown after the
   canvas-drawn "GAME CLEAR!!" overlay finishes. Kept modest/plain rather
   than boxy, in the same DARK OUT visual language as the rest of this
   pass. */
#result-screen {
  position: fixed;
  inset: 0;
  z-index: 13;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0a0b0c;
}
#result-screen[hidden] { display: none; }
#result-panel {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 14px;
  min-width: 240px;
  padding: 10px 20px;
}
#result-title {
  font-family: 'Arial Narrow', 'Helvetica Neue', Arial, sans-serif;
  font-weight: 900;
  font-size: 30px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  text-align: center;
  color: #ffffff;
  text-shadow: 0 0 12px rgba(230, 30, 20, 0.6);
  margin-bottom: 6px;
}
.result-stat {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  padding-bottom: 8px;
}
.result-stat-label {
  font-family: sans-serif;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.2em;
  color: rgba(210, 215, 220, 0.65);
}
.result-stat-value {
  font-family: sans-serif;
  font-weight: 700;
  font-size: 18px;
  letter-spacing: 0.05em;
  color: #ffffff;
}
#result-rank.result-stat-value,
#result-screen #result-rank {
  color: #f4211f;
  text-shadow: 0 0 10px rgba(230, 30, 20, 0.55);
}
/* PART 9 SECTION A-2/A-3: strengthened from the original 13px/600 weight —
   still restrained (a light red glow, never a neon effect), centered
   (unlike the action buttons below, which go left-aligned), with slightly
   more breathing room above/below so it reads clearly between RANK and the
   action buttons. */
#result-thanks {
  font-family: sans-serif;
  font-weight: 800;
  font-size: 16px;
  letter-spacing: 0.12em;
  text-align: center;
  color: rgba(255, 255, 255, 0.96);
  text-shadow: 0 0 8px rgba(230, 30, 20, 0.35);
  margin: 14px 0 10px;
}
/* PART 9 SECTION A-1: BACK TO TOP MENU (<button>) and ARTIST PAGE (<a>) sit
   on the same #result-panel flex column as the PLAY TIME/ACCURACY/DAMAGE
   TAKEN/RANK rows above, but .mode-btn's own shared padding (6px 10px) and
   each element's own UA-default text alignment left them starting at
   different X positions instead of lining up with those labels' own flush-
   left edge. Scoped to just these two IDs (never touching global .mode-btn,
   which PAUSE MENU/GAME OVER also use) — zeroes the horizontal padding/
   margin and forces explicit left alignment so button vs anchor default
   differences can't diverge again the same way. */
#result-back-btn,
#result-artist-btn {
  display: block;
  width: 100%;
  align-self: stretch;
  text-align: left;
  padding-left: 0;
  padding-right: 0;
  margin-left: 0;
}
/* SECTION M: GAME OVER — a real DOM screen (never a canvas overlay on the
   frozen frame, unlike GAME CLEAR), entered the instant PLAYER LIFE hits 0
   on a finite setting. Same restrained white/red/black DARK OUT language
   as RESULT — no cheap rainbow effects, per the spec's own instruction. */
#game-over-screen {
  position: fixed;
  inset: 0;
  z-index: 13;
  display: flex;
  align-items: stretch;
  justify-content: center;
  background: #0a0b0c;
}
#game-over-screen[hidden] { display: none; }
/* SECTION I (this turn): the MENU (RETRY/QUIT/ARTIST PAGE) is left-aligned
   — same 8vw safe margin / plain-text treatment as OPENING's own MODE
   SELECT (I-4/I-5) — while the title itself stays centered (I-6, via its
   own align-self override below), never a centered button stack (I-3). */
#game-over-panel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 18px;
  width: 100%;
  padding: 10px 8vw;
}
#game-over-title {
  align-self: center;
  font-family: 'Arial Narrow', 'Helvetica Neue', Arial, sans-serif;
  font-weight: 900;
  font-size: 34px;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  text-align: center;
  color: #ffffff;
  text-shadow: 0 0 14px rgba(230, 30, 20, 0.65);
  margin-bottom: 10px;
}

/* SECTION E/I: shared SETTING overlay — its own fixed layer (moved out of
   #mode-menu), above both PAUSE MENU and MAIN MENU. */
#setting-panel {
  position: fixed;
  inset: 0;
  z-index: 16;
  display: flex;
  align-items: center;
  justify-content: center;
  /* POST-v1.0 SECTION 19-2: fully opaque solid black while SETTING shows —
     real-device feedback found the old semi-transparent scrim let the
     gameplay/menu video underneath show through and hurt legibility. Never
     a partial-alpha value again, from either entry point (MAIN MENU/PAUSE). */
  background: #000000;
}
#setting-panel[hidden] { display: none; }

/* ---------- Mode select / PAUSE menu ----------
   SECTION U: moved away from the previous "bank/settings-app" look (a
   bordered, drop-shadowed card with per-item boxed buttons) — now a dark,
   semi-transparent full-screen scrim with plain text items directly on it,
   so the paused gameplay frame underneath stays partially visible. */
#mode-menu {
  position: fixed;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(4, 5, 6, 0.62);
  z-index: 10;
}
#mode-menu.open {
  display: flex;
}
#mode-menu-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
  min-width: 220px;
  padding: 0;
  background: transparent;
  border: none;
  box-shadow: none;
}
#mode-menu-title {
  color: rgba(210, 225, 235, 0.75);
  font-family: sans-serif;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.35em;
  text-align: center;
  margin-bottom: 4px;
}
.mode-btn {
  font-family: sans-serif;
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none; /* SECTION N: this class is now also used on <a> elements (RESULT/GAME OVER's own ARTIST PAGE links) */
  color: rgba(220, 232, 240, 0.85);
  background: transparent;
  border: none;
  padding: 6px 10px;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: color 120ms ease, text-shadow 120ms ease;
}
.mode-btn:active {
  color: #ffffff;
  text-shadow: 0 0 10px rgba(200, 220, 235, 0.6);
}
#mode-restart-btn {
  color: rgba(232, 200, 150, 0.85);
}
#mode-quit-btn {
  color: rgba(235, 120, 110, 0.85);
}

/* SECTION G: only ever visible while player.stunned is true (see
   showModeMenu() in game.js) — red, bold (heavier than the other .mode-btn
   items' own 600 weight), with a gentle blink (never a harsh strobe). */
#mode-reboot-btn {
  color: #ff4a3c;
  font-weight: 800;
  animation: mode-reboot-blink 900ms ease-in-out infinite;
}
#mode-reboot-btn[hidden] { display: none; }
@keyframes mode-reboot-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

/* SECTION E/I/U: SETTING's own panel, also kept modest (not an oversized
   card) — a thin border for legibility around the life-option grid only,
   no heavy drop shadow. Shared by both PAUSE MENU's and MAIN MENU's own
   SETTING entry points. */
/* POST-v1.0 SECTION 19-3: de-boxed to the same plain-text-over-background
   convention as SCENARIO SELECT — no card background/border, no filled
   life-option buttons. Shared by both PAUSE MENU's and MAIN MENU's own
   SETTING entry points; the underlying data (playerMaxLife) is untouched. */
#setting-panel-inner {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 18px;
  min-width: 200px;
  padding: 0;
  background: transparent;
  border: none;
}
#setting-life-label {
  color: rgba(230, 60, 50, 0.9);
  font-family: 'Arial Narrow', 'Helvetica Neue', Arial, sans-serif;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  text-align: center;
  margin-top: 4px;
}
#setting-life-options {
  display: flex;
  gap: 14px;
  justify-content: center;
}
.life-option-btn {
  flex: 1;
  font-family: 'Arial Narrow', 'Helvetica Neue', Arial, sans-serif;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
  color: rgba(235, 235, 238, 0.88);
  background: transparent;
  border: none;
  border-bottom: 2px solid rgba(230, 60, 50, 0);
  padding: 10px 2px;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: color 120ms ease, border-color 120ms ease, text-shadow 120ms ease;
}
.life-option-btn:active {
  color: #ffffff;
  border-bottom-color: rgba(230, 60, 50, 0.85);
  text-shadow: 0 0 14px rgba(230, 40, 30, 0.75);
}
.life-option-btn.selected {
  color: #ffffff;
  border-bottom-color: rgba(150, 240, 190, 0.85);
  text-shadow: 0 0 10px rgba(150, 240, 190, 0.55);
}
#mode-resume-btn {
  color: rgba(160, 225, 180, 0.9);
}

/* ==========================================================================
   PART 9 SECTION G: shared EVENT MOVIE PLAYER overlay — one instance reused
   for every SYSTEM/EVENT movie. Sits above everything (mode-menu/landscape-
   block are both z-index 20) so it can freeze/cover LOADING, MENU, and
   gameplay alike. object-fit:contain (never `cover`) so no source footage
   is ever cropped — matches the "zero source cropping" requirement.
   ========================================================================== */
#event-movie-overlay {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
}
#event-movie-overlay[hidden] { display: none; }
#event-movie-video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* SECTION J: iOS play()-rejection fallback — a plain tap target, never a
   permanent UI element (only shown while [hidden] is explicitly removed by
   playEventMovie()'s own play().catch() handler in game.js). */
#event-movie-tap-fallback {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-family: sans-serif;
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.2em;
  color: #fff;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.6);
  padding: 16px 28px;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
#event-movie-tap-fallback[hidden] { display: none; }
