/* Tailwind's min-h-screen class (on <body> in index.html) compiles to
   min-height: 100vh. On iOS Safari, 100vh is the "large viewport" value —
   it assumes the address bar is hidden, so it's taller than the visible
   area whenever the bar is actually showing. resizeCanvas() (js/main.js)
   sizes the canvas off window.innerHeight instead, which always reflects
   the real, currently-visible viewport — so on iOS, body ends up taller
   than the canvas by exactly the address-bar's height, and centering that
   extra space top/bottom left a black gap above the board (confirmed live
   via a user screenshot). dvh (dynamic viewport height) tracks the same
   real visible viewport window.innerHeight does, closing that gap;
   `body.min-h-screen` (element+class) is needed for specificity to beat
   Tailwind's own `.min-h-screen` rule — a bare `body {}` rule here would
   lose to it regardless of source order. Browsers without dvh support
   ignore the second declaration and keep the 100vh fallback. */
body.min-h-screen {
  min-height: 100vh;
  min-height: 100dvh;
}

/* Landscape-only gate — see js/utils/orientationGate.js. Shown/hidden via
   inline style.display from JS (checks the actual viewport aspect ratio),
   not a media query, so the base rule here just establishes the covering
   layout; display:none is the resting state until JS decides otherwise. */
#orientationGate {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: #0f172a;
  color: #fff;
  text-align: center;
  padding: 24px;
}

#orientationGate .rotate-icon {
  font-size: 3rem;
  margin-bottom: 1rem;
}

/* Power-LED dot in the top-left corner doubles as a live mouse-escape-danger
   meter, not just a static power light: GameScreen.updateEscapeDangerIndicator()
   sets `document.body.dataset.mouseDanger` ('low'/'medium'/'high', based on
   the mouse's distance to the nearest escape hole) every frame regardless of
   device — harmless on desktop since these rules are gated behind the same
   `pointer: coarse` check already used for the touch controls, so the LED
   only ever shows on an actual touch device. (The handheld-console bezel
   border that used to frame the viewport here was removed — read as an
   unwanted grey border on-device rather than a bevel.) */
@media (pointer: coarse) {
  body::before {
    content: '';
    position: fixed;
    top: 15px;
    left: 20px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 30%, #9bff9f, #1ec83f 75%);
    box-shadow: 0 0 4px rgba(40, 255, 80, 0.7);
    z-index: 9991;
    pointer-events: none;
    transition: background 0.2s ease, box-shadow 0.2s ease;
  }

  body[data-mouse-danger="medium"]::before {
    background: radial-gradient(circle at 35% 30%, #fff59b, #c8961e 75%);
    box-shadow: 0 0 4px rgba(255, 200, 40, 0.75);
  }

  body[data-mouse-danger="high"]::before {
    background: radial-gradient(circle at 35% 30%, #ff9b9b, #c81e1e 75%);
    box-shadow: 0 0 5px rgba(255, 40, 40, 0.85);
  }
}

/* On-screen D-pad (movement) — see js/utils/touchControls.js. Anchored
   within the left gutter (the empty space between the viewport frame and
   the canvas's left edge), centered both horizontally and vertically
   *within that gutter's own footprint* rather than at a fixed offset from
   the viewport edge. Horizontal centering depends on the canvas's actual
   runtime position (its width isn't fixed — see resizeCanvas() in
   js/main.js), so `left` here is just a fallback; touchControls.js sets
   the real value from the canvas's bounding rect on load/resize/
   orientationchange, using the same transform: translate(-50%, -50%) this
   rule establishes. Vertical centering (top: 50%) doesn't need that same
   JS treatment — the gutter spans the full viewport height regardless of
   where the canvas sits vertically, so viewport-center is already correct.
   Hidden by default; only shown when both the pointer is coarse (touch) and
   gameplay is actually running (GameScreen adds .in-game to <body> in
   init() and removes it in cleanup()) — this keeps desktop play
   uncluttered and keeps the control off the setup screen.
   A hand-tuned CSS approximation of a supplied reference photo (rounded-
   corner + clip-path shapes, gradients, shadows) read as amateurish next
   to the actual photo — CSS shading can't reproduce a real render's
   curvature and material look. So this now uses the reference image
   itself: `assets/dpad_cross.png`, cropped tightly from the full-
   resolution (1672x941) source down to just the cross plus a small
   margin, resized to 320x320. `#dpad` just displays that image; there's
   no drawn disc, gradient, or button shape here anymore, which is also
   why there's no circular rim — the reference has none. The four
   `<button>` elements are invisible, absolutely-positioned hit zones
   layered on top at the image's own button positions (measured directly
   from the source photo's pixels, not eyeballed — see the percentages
   below) so touch targets line up with what's actually drawn; each is
   empty of visible content (no glyph) since the arrows are already baked
   into the image, and `aria-label` alone carries the accessible name.
   `.dpad-btn:active` fakes a press with a soft radial glow (the image
   itself can't change state) rather than swapping in a second image for
   a pressed look — simpler, and good enough for a touch-feedback cue. */
#dpad {
  position: fixed;
  left: 0;
  top: 50%;
  /* --dpad-scale (set by touchControls.js) shrinks the whole control
     proportionally when the gutter beside the canvas is narrower than
     this control's natural 168px, e.g. on a standard-aspect iPad
     landscape. Defaults to 1 (full size) before JS runs or on any device
     with a roomy-enough gutter. */
  transform: translate(-50%, -50%) scale(var(--dpad-scale, 1));
  z-index: 40;
  width: 168px;
  height: 168px;
  display: none;
  background-image: url('./assets/dpad_cross.png');
  background-size: 100% 100%;
  background-repeat: no-repeat;
  border-radius: 22px;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.45);
  /* iOS's long-press text-selection/lookup callout ("Copy | Search with
     Google") was popping up over the d-pad during holds — touch-action and
     user-select on .dpad-btn below weren't enough to suppress it, since
     that callout is a separate -webkit-only behavior. Set here on the
     container too (not just the individual buttons) so a press landing on
     the small gaps between them is covered as well. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

@media (pointer: coarse) {
  body.in-game #dpad {
    display: block;
  }
}

.dpad-btn {
  position: absolute;
  border: none;
  background: transparent;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  touch-action: none;
  user-select: none;
  transition: background 0.1s ease;
}

.dpad-btn:active {
  background: radial-gradient(circle, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0) 70%);
}

/* Hit-zone rectangles start from the visible shape measured off the
   source photo (percentages of the cropped 320x320 image — see the
   original bounds this grew from in git history) then grow *only* along
   each button's own outer/inner axis — up's top edge moves further up
   into the image's black margin, its bottom edge nudges toward center,
   but its left/right edges are untouched. Deliberately not grown
   sideways: the perpendicular edges are what determine how much a
   button's hit zone overlaps its two diagonal neighbors (e.g. up
   overlapping left in the corner where their zones meet near the
   center), and growing those would start stealing taps meant for the
   adjacent direction. Growing only the untouched axis makes each target
   meaningfully bigger — the actual "hard to hit" complaint — without
   introducing new cross-direction ambiguity beyond the small amount that
   already existed at the shapes' shared center point. */
.dpad-up {
  left: 36.7%;
  top: 4.2%;
  width: 26%;
  height: 44.1%;
  border-radius: 50% 50% 12px 12px;
}
.dpad-down {
  left: 37.6%;
  top: 53.1%;
  width: 25.1%;
  height: 42.8%;
  border-radius: 12px 12px 50% 50%;
}
.dpad-left {
  left: 4.3%;
  top: 37.3%;
  width: 43%;
  height: 26.7%;
  border-radius: 50% 12px 12px 50%;
}
.dpad-right {
  left: 52.8%;
  top: 37.3%;
  width: 43%;
  height: 26.7%;
  border-radius: 12px 50% 50% 12px;
}

/* Action buttons (punch/toot/meow) — these map to the same keystrokes as
   desktop ('p'/space/'m', see InputHandler.js), so touch users need direct
   access to them too, not just movement. Anchored within the right gutter
   (mirror of #dpad's left gutter above), centered both horizontally and
   vertically within that gutter's own footprint — same reasoning as
   #dpad: `left` here is a fallback, touchControls.js sets the real
   horizontal center from the canvas's bounding rect (using `left` rather
   than `right`, so both controls share one positioning scheme). Standard
   movement-left/actions-right split, visually symmetric with the d-pad.
   Deliberately kept vertically centered rather than pushed toward a
   corner: a future credits/settings/etc. icon row is planned, and the
   *top* corners are the natural home for menu-style icons (they don't
   compete with gameplay controls the way another bottom cluster would) —
   this cluster stays put so that row can be added above it later without
   a re-layout. */
#actionButtons {
  position: fixed;
  left: 0;
  top: 50%;
  /* --action-scale (set by touchControls.js) — same shrink-to-fit
     reasoning as #dpad's --dpad-scale above, against this cluster's own
     52px natural button size. */
  transform: translate(-50%, -50%) scale(var(--action-scale, 1));
  z-index: 40;
  display: none;
  flex-direction: column;
  gap: 10px;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

@media (pointer: coarse) {
  body.in-game #actionButtons {
    display: flex;
  }
}

.action-btn {
  width: 64px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, rgba(138, 43, 226, 0.45), rgba(15, 15, 25, 0.6) 72%);
  border: 1px solid rgba(255, 255, 255, 0.28);
  color: #fff;
  font-size: 1.7rem;
  line-height: 1;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.15);
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  touch-action: none;
  user-select: none;
  transition: background 0.12s ease, transform 0.12s ease;
}

.action-btn:active {
  background: radial-gradient(circle at 35% 30%, rgba(138, 43, 226, 0.7), rgba(15, 15, 25, 0.7) 72%);
  transform: scale(0.9);
}

/* Settings (hamburger) menu (see js/utils/settingsMenu.js) — NOT gated to
   pointer:coarse like #dpad/#actionButtons above, since sound isn't a
   touch-only concern; this shows on desktop too, just positioned
   differently there. The toggle button reuses the action-btn purple-glow
   look for visual consistency with the other round buttons; the dropdown
   panel holds the two independent mute toggles (music, sounds — see
   js/utils/audio.js).

   Desktop default: vertically centered (top: 50%) and horizontally anchored
   to the right gutter's center via `left`, set inline by
   layoutSettingsMenuDesktop() in js/utils/settingsMenu.js using the exact
   same formula #actionButtons uses below — same "vertical line" the
   action-icon column would sit on, tracked against the canvas's actual
   position rather than a fixed viewport corner. Mobile overrides this
   (see the pointer:coarse block below) back to a fixed top-right corner —
   the action-button cluster is already crowded there, so this stays
   separate rather than joining it. */
#settingsMenu {
  position: fixed;
  left: 0;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 45;
  display: none;
}

body.in-game #settingsMenu {
  display: block;
}

@media (pointer: coarse) {
  #settingsMenu {
    left: auto;
    top: 14px;
    right: 16px;
    transform: none;
  }
}

#settingsToggle {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, rgba(138, 43, 226, 0.45), rgba(15, 15, 25, 0.6) 72%);
  border: 1px solid rgba(255, 255, 255, 0.28);
  color: #fff;
  font-size: 1.1rem;
  line-height: 1;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.15);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  user-select: none;
  cursor: pointer;
  transition: background 0.12s ease, transform 0.12s ease;
}

#settingsToggle:active {
  background: radial-gradient(circle at 35% 30%, rgba(138, 43, 226, 0.7), rgba(15, 15, 25, 0.7) 72%);
  transform: scale(0.9);
}

/* Dropdown panel — absolutely positioned under the toggle button rather
   than a fixed offset, so it stays anchored to it regardless of where
   #settingsMenu ends up. `hidden` (a real HTML attribute, toggled in JS)
   drives visibility rather than a class, since there's no animation here
   to justify a display:none-vs-opacity distinction. */
#settingsPanel {
  position: absolute;
  top: 48px;
  right: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  min-width: 170px;
  border-radius: 12px;
  background: rgba(20, 18, 30, 0.94);
  border: 1px solid rgba(255, 255, 255, 0.15);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45);
}

#settingsPanel[hidden] {
  display: none;
}

#settingsPanel button {
  padding: 9px 12px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  font-size: 0.85rem;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s ease;
}

#settingsPanel button:hover,
#settingsPanel button:active {
  background: rgba(255, 255, 255, 0.18);
}
