/* ===== PsychoFlip — 1-bit aesthetic ===== */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: #0a0a14;
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  color: #e6e6f0;
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;       /* frame on top, the arena flip-controls bar below it */
  align-items: center;
  justify-content: center;
  overflow: hidden;
  letter-spacing: 0.5px;
}

/* Air-flip PoC tuning bar — sits below the game, shown only in the TEST ARENA. */
#flip-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 18px;
  align-items: center;
  justify-content: center;
  width: 960px;
  max-width: 96vw;
  box-sizing: border-box;
  margin-top: 14px;
  padding: 9px 16px;
  background: #14141e;
  border: 2px solid #2a2a3a;
  border-radius: 6px;
  font-size: 12px;
  color: #b8b8c8;
  letter-spacing: 1px;
}
#flip-controls[hidden] { display: none; }
#flip-controls .fc-title { font-weight: bold; color: #e6e6f0; letter-spacing: 2px; }
#flip-controls label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
#flip-controls input[type="range"] { width: 92px; accent-color: #e6e6f0; }
#flip-controls select { background: #0a0a14; color: #e6e6f0; border: 1px solid #33334a; padding: 2px 4px; font-family: inherit; }
#flip-controls .fc-val { min-width: 38px; color: #9fe0c0; }

/* HUD status bar — ABOVE the play frame (moved off-canvas). 1-bit palette, and a
   CONSTANT style: it does NOT invert with in-game polarity (it's dashboard chrome
   outside the world, so it stays readable). Matches the frame width. */
#hud {
  width: 960px;
  max-width: 96vw;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 10px;
  padding: 7px 16px;
  background: #0a0a14;
  box-shadow: 0 0 0 2px #e6e6f0;
  font: 14px ui-monospace, Menlo, Consolas, monospace;
  color: #e6e6f0;
  letter-spacing: 1px;
  image-rendering: pixelated;
}
#hud.hidden { display: none; }
#hud .hud-left, #hud .hud-right { display: flex; align-items: center; gap: 18px; flex: 1 1 0; }
#hud .hud-right { justify-content: flex-end; }
#hud .hud-center { display: flex; flex-direction: column; align-items: center; gap: 1px; flex: 0 0 auto; }
#hud #hud-level { font-weight: bold; letter-spacing: 2px; }
#hud #hud-objective { font-size: 11px; opacity: 0.7; min-height: 13px; }
#hud .hud-hearts { letter-spacing: 3px; font-size: 15px; }
#hud .hud-hearts .dim { opacity: 0.28; }
#hud #hud-fliptime { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; }
#hud #hud-fliptime .ft-bar { width: 84px; height: 9px; box-shadow: inset 0 0 0 1px #e6e6f0; display: inline-block; }
#hud #hud-fliptime .ft-bar i { display: block; height: 100%; background: #e6e6f0; }
#hud #hud-fliptime.hidden, #hud #hud-key.hidden, #hud #hud-shards.hidden, #hud #hud-timer.hidden, #hud #hud-speed.hidden { display: none; }
#hud #hud-speed { color: #ffd76a; font-weight: bold; }   /* fast-forward chip: visible only at >1× */
#hud #hud-pol { font-size: 17px; }

#frame {
  position: relative;
  width: 960px;
  height: 540px;
  box-shadow:
    0 0 0 4px #e6e6f0,
    0 0 0 8px #0a0a14,
    0 12px 60px #000a;
  image-rendering: pixelated;
}

canvas#game {
  display: block;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  background: #0a0a14;
}

/* ===== Overlays ===== */
.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(10,10,20,0.55);
  z-index: 10;
}
.overlay.hidden { display: none; }

/* Hub-launched dialogs (Settings, Help, Sign-in, Slots, Shop, Collection,
   Trophies, Achievements, Admin, etc.) open OVER the Player Hub. The hub
   (#menu.hub) is position:fixed z-index:45 so it escapes the 960×540 #frame and
   covers the whole viewport. A plain .overlay is position:absolute (frame-bound)
   at z-index:10, so it renders BEHIND the opaque hub — the button looks dead even
   though the dialog opened. Lift these to fixed + z-index:50 so they cover the
   hub like a real modal. Touch mode already does this for every overlay (see
   `body.show-touch .overlay` below); this brings desktop in line for hub dialogs. */
#help, #settings, #slots, #account, #levels,
#achievements, #trophies, #shop, #collection,
#admin, #starbattle, #boss-demo {
  position: fixed;
  z-index: 50;
}

/* Boot splash — full-bleed logo on black; click/key/timeout dismisses to menu. */
#splash { background: #000; z-index: 40; cursor: pointer; }
#splash .splash-pic { display: contents; }   /* let the chosen <img> be the flex child (keeps #splash-img sizing) */
#splash-img { max-width: 92%; max-height: 86%; object-fit: contain;
  animation: splash-in .5s ease-out both; }
@keyframes splash-in { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }
.splash-hint { position: absolute; bottom: 4%; left: 0; right: 0; text-align: center;
  color: #cfcfe0; font-size: 13px; letter-spacing: 3px; text-transform: uppercase;
  text-shadow: 0 0 5px #000, 0 0 5px #000, 0 1px 2px #000;
  animation: splash-hint-pulse 1.6s ease-in-out infinite; pointer-events: none; }
@keyframes splash-hint-pulse { 0%,100% { opacity: .3; } 50% { opacity: .85; } }

.panel {
  background: #0a0a14;
  border: 4px solid #e6e6f0;
  padding: 30px 36px;
  text-align: center;
  min-width: 380px;
  box-shadow: 6px 6px 0 #000;
}

.title {
  font-size: 36px;
  font-weight: 700;
  letter-spacing: 6px;
  color: #e6e6f0;
  margin-bottom: 4px;
}

/* Menu wordmark — the white PsychoFlip logo (assets/psychoflip-logo.svg) in
   place of the text title. Scales to the panel width; aspect ratio preserved. */
.menu-logo {
  display: block;
  width: 100%;
  max-width: 300px;
  height: auto;
  margin: 2px auto 10px;
}

.tagline {
  font-size: 12px;
  color: #a8a8b8;
  letter-spacing: 4px;
  margin-bottom: 26px;
  text-transform: uppercase;
}

.subtitle {
  font-size: 12px;
  color: #a8a8b8;
  margin-bottom: 18px;
  letter-spacing: 1px;
}

/* ===== Level intro card (the pre-level "LEVEL n — challenge" black box) ===== */
.intro-card {
  background: #000;
  min-width: 360px;
  padding: 38px 48px;
}
.intro-label {
  font-size: 13px;
  letter-spacing: 8px;
  color: #8a8a98;
  text-transform: uppercase;
}
.intro-level {
  font-size: 56px;
  font-weight: 700;
  letter-spacing: 4px;
  color: #e6e6f0;
  line-height: 1.05;
  margin: 8px 0 12px;
}
.intro-challenge {
  font-size: 16px;
  letter-spacing: 2px;
  color: #e6e6f0;
}

/* ===== Buttons ===== */
button {
  font-family: inherit;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 2px;
  border: 3px solid #e6e6f0;
  background: #0a0a14;
  color: #e6e6f0;
  padding: 12px 24px;
  margin: 6px;
  cursor: pointer;
  display: block;
  width: 240px;
  margin-left: auto;
  margin-right: auto;
  transition: transform 0.05s, background 0.1s;
}
button:hover {
  background: #e6e6f0;
  color: #0a0a14;
}
button:active {
  transform: translate(2px, 2px);
}
/* Disabled (e.g. RESURRECT when you can't afford it): dimmed, no hover-invert, no press. */
button:disabled, button:disabled:hover {
  opacity: 0.4;
  background: transparent;
  color: #e6e6f0;
  cursor: not-allowed;
}
button:disabled:active { transform: none; }
button.primary {
  border-color: #e6e6f0;
}
button.secondary {
  font-size: 11px;
}
/* Restore the `hidden` attribute for buttons — `button { display:block }` above is an
   AUTHOR rule that beats the UA `[hidden]{display:none}`, so `btn.hidden = true` was a
   no-op (e.g. the admin-only #btn-admin / signed-out #btn-account would still show). This
   higher-specificity rule makes hidden buttons actually hide. */
button[hidden] { display: none; }

/* ===== Seed + biome picker row ===== */
.seedrow {
  width: 240px;
  margin: 0 auto 6px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.seedrow input,
.seedrow select {
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  border: 2px solid #4a4a5a;
  background: #0a0a14;
  color: #e6e6f0;
  padding: 8px 10px;
  width: 100%;
  box-sizing: border-box;
  cursor: pointer;
}
.seedrow input::placeholder { color: #6a6a7a; }
.seedrow input:focus,
.seedrow select:focus {
  outline: none;
  border-color: #e6e6f0;
}

/* ===== Admin LEVEL JUMPER ===== */
.jump-panel {
  width: 240px;
  margin: 0 auto 12px;
  padding: 10px;
  border: 2px solid #4a4a5a;
  background: #0a0a14;
  box-sizing: border-box;
}
.jump-title {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 1px;
  color: #e6e6f0;
  text-align: center;
  margin-bottom: 8px;
}
.jump-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-bottom: 8px;
}
.jump-grid label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 1px;
  color: #8a8a9a;
  text-transform: uppercase;
}
.jump-grid input,
.jump-grid select {
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1px;
  border: 2px solid #4a4a5a;
  background: #14141e;
  color: #e6e6f0;
  padding: 6px 8px;
  width: 100%;
  box-sizing: border-box;
  cursor: pointer;
}
.jump-grid input:focus,
.jump-grid select:focus {
  outline: none;
  border-color: #e6e6f0;
}
.jump-panel #btn-jump { width: 100%; margin: 0; }
.jump-panel .jump-row {
  display: flex; align-items: center; gap: 7px;
  margin: 0 0 8px; font-size: 9px; font-weight: 700; letter-spacing: 1px;
  color: #8a8a9a; text-transform: uppercase; cursor: pointer; text-align: left;
}

/* ===== TEST & ADMIN console =====
   A WIDE, OPAQUE cover: the backdrop is solid (the main menu must not show through)
   and the panel is a horizontal rectangle — three columns instead of one tall stack. */
#admin { background: #0a0a14; overflow-y: auto; }
#admin .admin-panel {
  max-width: 1010px; width: 94%;
  margin: 24px 0;                     /* breathing room when the viewport is short (overlay scrolls) */
  padding: 22px 28px 26px;
  text-align: left;
  box-sizing: border-box;
}
.admin-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  margin-bottom: 16px;
}
.admin-head .title { text-align: left; }
.admin-head .subtitle { text-align: left; margin: 2px 0 0; }
.admin-head #btn-admin-close { width: auto; margin: 0; padding: 10px 26px; }
.admin-cols {
  display: grid;
  grid-template-columns: minmax(280px, 1.35fr) 1fr 1fr;
  gap: 20px;
  align-items: start;
}
.admin-sec {
  font-size: 10px; font-weight: 800; letter-spacing: 2px; color: #8a8a9a;
  text-transform: uppercase; border-bottom: 2px solid #262638;
  padding-bottom: 5px; margin: 0 0 10px;
}
/* column buttons: fill the column, compact, flush (override the global 240px centered button) */
.admin-col button { width: 100%; margin: 0 0 8px; padding: 10px 12px; font-size: 12px; letter-spacing: 1px; }
.admin-col .jump-panel { width: 100%; margin: 0; }
.admin-col .seedrow { width: 100%; margin: 0; }
.admin-col .seedrow input, .admin-col .seedrow select { width: 100%; box-sizing: border-box; }
/* short/narrow screens: columns stack and the opaque overlay scrolls */
@media (max-width: 860px) {
  .admin-cols { grid-template-columns: 1fr; }
  #admin .admin-panel { margin: 12px 0; }
}

/* ===== Difficulty slider ===== */
.diffrow {
  width: 240px;
  margin: 0 auto 10px;
  font-size: 11px;
  letter-spacing: 1px;
  color: #a8a8b8;
  text-align: center;
}
.diffrow label { display: block; margin-bottom: 6px; }
.diffrow label b { color: #e6e6f0; }
.diffrow input[type="range"] {
  width: 100%;
  accent-color: #e6e6f0;
  cursor: pointer;
}
.diffscale {
  display: flex;
  justify-content: space-between;
  font-size: 9px;
  color: #6a6a7a;
  margin-top: 2px;
}

/* ===== Settings: key remap ===== */
#keybind-list { width: 280px; margin: 12px auto 8px; }
.keybind-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 4px 0;
  font-size: 12px;
  letter-spacing: 1px;
}
.kb-label { color: #a8a8b8; }
.kb-key {
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  border: 2px solid #4a4a5a;
  background: #0a0a14;
  color: #e6e6f0;
  padding: 5px 12px;
  min-width: 96px;
  width: auto;
  margin: 0;
  cursor: pointer;
  display: inline-block;
}
.kb-key:hover { border-color: #e6e6f0; background: #e6e6f0; color: #0a0a14; }

/* ===== Help text ===== */
.help {
  margin-top: 22px;
  font-size: 10px;
  color: #a8a8b8;
  line-height: 1.9;
  letter-spacing: 1px;
}
.help b { color: #e6e6f0; }
.tip {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid #262638;
  color: #a8a8b8;
}

/* ===== Generating overlay + keyboard hint ===== */
.pulse { animation: pulse 0.9s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
.keyhint {
  margin-top: 14px;
  font-size: 10px;
  letter-spacing: 1px;
  color: #6a6a7a;
}
.keyhint b { color: #a8a8b8; }

/* ===== Loading ===== */
.bar {
  width: 240px;
  height: 12px;
  border: 2px solid #e6e6f0;
  margin: 16px auto;
}
#loadbar {
  width: 0%;
  height: 100%;
  background: #e6e6f0;
  transition: width 0.15s;
}

/* ===== Touch / mobile on-screen controls =====
   The body gets the `show-touch` class (added by main.js) ONLY on touch
   devices — detected via matchMedia('(hover: none) and (pointer: coarse)'),
   which is true on phones/tablets and false on desktops + hover-capable touch
   laptops. So these controls never appear on desktop. Controller-style split:
   MOVEMENT (◀▶) on the LEFT, ACTIONS (Jump/Fire/Flip) on the RIGHT. Layout:
   portrait → game on top, controls in a row beneath; landscape → game centered
   with the ◀▶ column on the left and the J/F/P column on the right. */
.touchpad { display: none; }
#touch-title { display: none; }   /* shown only in portrait touch mode */

body.show-touch {
  display: grid;
  width: 100vw;
  height: 100vh;
  height: 100dvh;   /* the VISIBLE height (excludes the Safari toolbar) so bottom controls aren't hidden behind it */
  /* pad in from the notch + home indicator so nothing hides behind them */
  padding: max(6px, env(safe-area-inset-top)) 6px max(6px, env(safe-area-inset-bottom)) 6px;
  gap: 8px;   /* a touch more so the frame's glow border doesn't kiss the HUD box */
  overflow: hidden;
  align-items: center; justify-items: center;
  /* Playing, not reading: kill text selection + the iOS magnifier loupe / callout / drag-
     lift "bubble" that a button hold can trigger (it froze/selected the screen). */
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
}
body.show-touch #hud, body.show-touch #frame, body.show-touch .touchpad,
body.show-touch #banter, body.show-touch #m-objective {
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}

/* Frame: drop the fixed 960×540 and fit the game area. Aspect follows the canvas via
   --game-ar (set by main.js applyViewport) — 16:9 everywhere except a portrait phone,
   which switches to the taller narrower view. */
body.show-touch #frame {
  width: auto; height: auto;
  min-width: 0; min-height: 0;   /* the canvas's intrinsic px size must NOT force the body-grid tracks wide (it blows out the ◀▶ / J·F·P columns otherwise) */
  aspect-ratio: var(--game-ar, 16 / 9);
  box-shadow: 0 0 0 3px #e6e6f0, 0 0 0 6px #0a0a14;
  touch-action: none;   /* the letterbox border around the canvas must not pan/zoom either */
}
body.show-touch #game { touch-action: none; }

/* PsychoFlip title above the game (portrait only — see the portrait query). */
body.show-touch #touch-title {
  grid-area: title;
  align-self: end;
  text-align: center;
  font-weight: 700;
  font-size: clamp(20px, 6vw, 34px);
  letter-spacing: 6px;
  color: #e6e6f0;
}

body.show-touch .touchpad { z-index: 30; touch-action: none; }

/* Left pad = movement: two big side-by-side hit zones. Adjacent (no gap) so a thumb can
   slide ◀↔▶ across the whole surface without landing in a dead spot. */
body.show-touch #touch-left { display: flex; }
body.show-touch #touch-left .tbtn { flex: 1 1 0; }

/* Right pad = actions: Jump is a TALL zone on the INNER side; Fire (top) + Phase (bottom)
   stack in a column on the OUTER edge — matching the on-phone layout. Nested flex (each
   part flex:1, min-size:0) so the zones split the pad evenly and stay much larger than the
   caps, without the min-content track-blowout a CSS grid hit here. */
body.show-touch #touch-right { display: flex; }
body.show-touch #touch-right > .tbtn[data-act="JUMP"] { flex: 1 1 0; min-width: 0; }
body.show-touch #touch-right .tr-stack { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
body.show-touch #touch-right .tr-stack > .tbtn { flex: 1 1 0; min-height: 0; width: 100%; }

/* On touch the game frame is small, so menus/overlays cover the WHOLE viewport
   (fixed) and stay centered + readable instead of overflowing the tiny frame. */
/* Fixed to the VISIBLE viewport, not the layout viewport: on iOS the URL bar makes `inset:0`
   taller than what you see, so flex-centered content (the splash logo, panels) sits too LOW.
   dvh tracks the visible area; the vh line is the fallback for older browsers (= prior behavior). */
body.show-touch .overlay { position: fixed; z-index: 50; bottom: auto; height: 100vh; height: 100dvh; }

/* ⚠ The body IS the grid: every VISIBLE direct child of <body> must either get a
   grid-area below or be position:fixed — an unassigned child auto-places as a stray
   grid item and wrecks the whole layout. (Exactly that shipped on 2026-06-10: the
   new #hud top-bar had no area, so mobile was mangled until 2026-07-10.) */
/* Compact 2-row header. Flatten the three sections (display:contents) so their stats
   share ONE wrapping flow, drop the non-essential bits (BANK lives in the shop; the
   objective is on the level-intro card), and tighten — that lands the header in ~2 rows
   on a phone instead of 4. */
#m-objective { display: none; }   /* mobile-only goal line; shown as a 3rd HUD row on touch (below) */
body.show-touch #hud {
  grid-area: hud;
  width: 100%; max-width: 100%;
  margin: 0;
  display: grid;
  grid-template-columns: auto auto;
  grid-template-areas:
    "hleft   hleft"    /* row 1: hearts · shards · ammo   */
    "hcenter hright"   /* row 2: level (·timer) | flip · polarity */
    "mobj    mobj";    /* row 3: the level goal (so it's always visible, not just on the intro card) */
  justify-content: center; align-items: center;
  column-gap: 16px; row-gap: 2px;
  padding: 3px 8px;
  font-size: 11px; line-height: 1.2;
}
body.show-touch #hud #m-objective {
  grid-area: mobj; display: block; justify-self: center;
  max-width: 94vw; font-size: 11px; opacity: 0.72;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.show-touch #hud .hud-left   { grid-area: hleft;   display: flex; align-items: center; gap: 12px; }
body.show-touch #hud .hud-center { grid-area: hcenter; display: flex; flex-direction: row; align-items: center; gap: 10px; }
body.show-touch #hud .hud-right  { grid-area: hright;  display: flex; align-items: center; gap: 10px; }
body.show-touch #hud #hud-objective { display: none; }   /* objective is on the intro card + m-objective row */
/* BANK (spendable shards) STAYS visible on touch — you need it to judge whether you can afford
   a resurrect. Keep the stats compact so the row still fits a phone. */
body.show-touch #hud .hud-stat { font-size: 11px; }
body.show-touch #hud .hud-hearts { font-size: 13px; }
body.show-touch #hud #hud-fliptime .ft-bar { width: 54px; }
body.show-touch #flip-controls { position: fixed; }   /* arena-only tuning bar: keep it out of the grid */

/* Touch PAUSE button (desktop uses P/Esc, so it's hidden there). Lives at the right end of the
   HUD row; taps open the pause card. Overrides the global `button { width: 240px }`. */
#m-pause { display: none; }
body.show-touch #hud #m-pause {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 28px; padding: 0; margin: 0;
  border: 2px solid #e6e6f0; border-radius: 7px;
  background: rgba(10, 10, 20, 0.55); color: #e6e6f0;
  font-size: 12px; letter-spacing: 2px; line-height: 1;
  -webkit-tap-highlight-color: transparent;
}
body.show-touch #hud #m-pause:active { transform: scale(0.93); }
body.show-touch #hud #m-pause:hover { background: rgba(10, 10, 20, 0.55); color: #e6e6f0; }

/* Each .tbtn is the HIT ZONE — big and transparent, so a thumb that lands off-centre
   still registers. The visible graphic is the smaller .cap inside it (the letter is never
   obscured). Zones fill their pad cells (sized below); caps stay a comfortable fixed size. */
body.show-touch .tbtn {
  width: auto; height: auto;   /* override the global `button { width: 240px }` — sizing comes from flex below */
  margin: 0; padding: 0; border: 0; background: none;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; touch-action: none;
  -webkit-appearance: none; appearance: none;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
body.show-touch .tbtn .cap {
  width: 15vmin; height: 15vmin;
  min-width: 52px; min-height: 52px;
  max-width: 84px; max-height: 84px;
  display: flex; align-items: center; justify-content: center;
  border: 3px solid #e6e6f0; border-radius: 16px;
  background: rgba(10, 10, 20, 0.55); color: #e6e6f0;
  font-size: 30px; font-weight: 700; line-height: 1;
  transition: background 60ms linear, transform 60ms linear;
}
/* Cancel the desktop hover-invert (some touch browsers fire :hover on tap). */
body.show-touch .tbtn:hover .cap { background: rgba(10, 10, 20, 0.55); color: #e6e6f0; }
body.show-touch .tbtn.held .cap { background: #e6e6f0; color: #0a0a14; transform: scale(0.93); }   /* JS toggles while pressed */

/* Phone-sized menu / death / win panels so they don't overflow. */
body.show-touch .panel { min-width: 0; width: min(92vw, 380px); padding: 18px 16px; }
body.show-touch .title { font-size: 26px; }
body.show-touch .help, body.show-touch .tip { display: none; }   /* keyboard help is irrelevant on touch */

/* Banter (in-level chatter). Desktop drops it BELOW the 960 frame; on a phone that
   tiny-frame offset lands right in the controls. Re-place it as a full-width readable
   bar (position per orientation, below). It's a child of #frame (its offset parent),
   pointer-events:none, so it never blocks play. */
body.show-touch #banter {
  left: 0; right: 0; width: auto; max-width: none; transform: none; margin: 0;
  padding: 6px 10px; gap: 8px; font-size: 12px; border-radius: 4px;
}
body.show-touch #banter .bn-head { width: 30px; height: 30px; }
body.show-touch #banter .bn-msg  { font-size: 12px; }

/* Notifications (achievement toasts): fit the viewport + clear the notch. Orientation
   places them (portrait: top-centre in the dead space; landscape: compact top-right). */
body.show-touch #toaster .toast { min-width: 0; max-width: min(340px, calc(100vw - 16px)); padding: 8px 12px; }

/* Portrait: HUD, game (full width), controls in a row below. No game title — the
   header uses that space (the title is redundant on the play screen). */
@media (orientation: portrait) {
  body.show-touch {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto 1fr;   /* HUD (top) · game · controls fill the rest */
    grid-template-areas:
      "hud   hud  "
      "game  game "
      "left  right";
  }
  body.show-touch #frame { grid-area: game; width: min(100%, calc(64vh * var(--game-ar, 1.778))); }
  /* Controls sit toward the bottom but lifted a bit for thumb reach (100dvh + the body's
     safe-area padding already keep them above the Safari bar + home indicator). */
  body.show-touch #touch-left,
  body.show-touch #touch-right { align-self: stretch; justify-self: stretch; width: 100%; min-width: 0; margin: 0; box-sizing: border-box; }
  body.show-touch #touch-left  { grid-area: left;  padding: 4px 8px 3vh 12px; }
  body.show-touch #touch-right { grid-area: right; padding: 4px 12px 3vh 8px; }
  /* Banter OVERLAID at the bottom of the play area (pointer-events:none) — there's no gap below
     the frame in portrait, so `top:100%` used to land right on the ◀▶/J/F/P buttons. */
  body.show-touch #banter { top: auto; bottom: 6px; margin-top: 0; }
  /* Toasts drop in BELOW the HUD header (they're low-priority) — not over the stats.
     ~60px clears the compact 3-row header; the safe-area inset matches the body padding. */
  body.show-touch #toaster { top: calc(env(safe-area-inset-top) + 66px); left: 8px; right: 8px; align-items: center; }
  body.show-touch #toaster .toast { width: 100%; }
}

/* ===== PLAYER HUB on a portrait phone =====
   The hub is a fixed 1010×600 desktop card that main.js scales-to-fit — on a ~375px screen
   that's ~0.35×, so every label is unreadable. On touch portrait we DROP the scale and reflow:
   full-width, auto-height, vertically scrollable, single-column slots, 2-up vault, bigger type. */
@media (orientation: portrait) {
  body.show-touch #menu.hub { align-items: flex-start; overflow-y: auto; -webkit-overflow-scrolling: touch; }
  body.show-touch #menu.hub .hub-card {
    width: 100%; min-height: 100%; height: auto; flex-shrink: 1;
    transform: none !important;                /* kill the shrink-to-fit scale */
    border: none; box-shadow: none; background-size: 32px 32px;
    padding: max(10px, env(safe-area-inset-top)) 14px calc(22px + env(safe-area-inset-bottom));
    gap: 4px;
  }
  /* Flex regions were sized to FILL the fixed 600px height — let them size to content + scroll. */
  body.show-touch #menu.hub .hub-main,
  body.show-touch #menu.hub #hub-hero,
  body.show-touch #menu.hub .hub-slots,
  body.show-touch #menu.hub .hero-grid { flex: none; min-height: 0; }

  /* Utility row + nav: wrap, larger tap targets. */
  body.show-touch #menu.hub .hub-util { flex-wrap: wrap; }
  body.show-touch #menu.hub .hub-eyebrow { font-size: 12px; }
  body.show-touch #menu.hub .hub-nav { flex-wrap: wrap; gap: 6px; }
  body.show-touch #menu.hub .navbtn { font-size: 12px; padding: 9px 11px; }

  /* Logo: stack the flanking taglines under a moderate logo. */
  body.show-touch #menu.hub .hub-logo { grid-template-columns: 1fr; gap: 4px; margin-top: 10px; padding-bottom: 12px; }
  body.show-touch #menu.hub .hub-logo img { height: 52px; justify-self: center; }
  body.show-touch #menu.hub .hub-flank { text-align: center !important; font-size: 10px; letter-spacing: 0.3em; }

  /* Status strip. */
  body.show-touch #menu.hub .hub-statusbar { flex-wrap: wrap; gap: 6px 14px; margin-top: 10px; }
  body.show-touch #menu.hub .hub-statusbar .si > span { font-size: 13px; }

  /* Section heads + Daily. */
  body.show-touch #menu.hub .hub-sectionhead { flex-wrap: wrap; gap: 8px; }
  body.show-touch #menu.hub .hub-sectionlabel { font-size: 12px; }
  body.show-touch #menu.hub .daily-btn { font-size: 12px; padding: 10px 12px; }

  /* Slots: one per row, readable. */
  body.show-touch #menu.hub .hub-slots { grid-template-columns: 1fr; gap: 12px; }
  body.show-touch #menu.hub .slot-no { font-size: 12px; }
  body.show-touch #menu.hub .slot-name { font-size: 26px; }
  body.show-touch #menu.hub .slot-depth { font-size: 13px; }
  body.show-touch #menu.hub .chip2 { font-size: 12px; padding: 4px 9px; }
  body.show-touch #menu.hub .slot-go { font-size: 15px; padding: 14px; }
  body.show-touch #menu.hub .slot-go.primary span { font-size: 11px; }
  body.show-touch #menu.hub .slot-last { font-size: 12px; }
  body.show-touch #menu.hub .slot-erase { font-size: 11px; padding: 5px 10px; }
  body.show-touch #menu.hub .diff-name { font-size: 20px; }
  body.show-touch #menu.hub .diff-sub { font-size: 12px; }
  body.show-touch #menu.hub .diff-ends { font-size: 11px; }
  body.show-touch #menu.hub .diff-label { font-size: 12px; }
  body.show-touch #menu.hub .slot.empty { padding: 22px; }
  body.show-touch #menu.hub .slot-plus { font-size: 34px; }

  /* Guest PLAY hero: stack, big button. */
  body.show-touch #menu.hub .hero-grid { grid-template-columns: 1fr; }
  body.show-touch #menu.hub .play-big { font-size: 34px; padding: 30px 0; }
  body.show-touch #menu.hub .play-big small { font-size: 12px; }

  /* The Vault: two per row, comfortable tap targets. */
  body.show-touch #menu.hub #hub-vault { grid-template-columns: 1fr 1fr; gap: 10px; }
  body.show-touch #menu.hub .hub-tile { height: auto; min-height: 70px; padding: 12px 14px; }
  body.show-touch #menu.hub .hub-tile-name { font-size: 14px; }
  body.show-touch #menu.hub .hub-tile-sub { font-size: 11px; }
}

/* Landscape: HUD across the top; game centered, J/F/P left, ◀▶ right below it. */
@media (orientation: landscape) {
  body.show-touch {
    /* Side columns size to their button groups; the game gets what's left. */
    grid-template-columns: auto 1fr auto;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "hud  hud  hud"
      "left game right";
  }
  /* Letterbox the game into the centre column. Cap the height to 84% so there's
     padding above + below the game (and the side button groups sit clear of the
     screen edges). */
  body.show-touch #frame { grid-area: game; width: auto; height: auto; max-width: 100%; max-height: 84%; }
  body.show-touch #touch-left  { grid-area: left;  margin-left: 10px; }
  body.show-touch #touch-right { grid-area: right; margin-right: 10px; }
  /* Little room below the frame here → overlay banter on the play area's bottom edge. */
  body.show-touch #banter { top: auto; bottom: 6px; left: 6px; right: 6px; margin: 0; }
  /* Toasts compact, top-right, below the HUD row + notch. */
  body.show-touch #toaster { top: max(8px, env(safe-area-inset-top)); right: 10px; }
  /* Phone held sideways → cover the game with the "rotate to portrait" notice
     (main.js pauses the run underneath). PsychoFlip Mobile is portrait-only. */
  body.show-touch #rotate-notice { display: flex; }
}

/* Rotate-to-portrait notice. Hidden except on a landscape TOUCH device (rule above). */
#rotate-notice {
  display: none;
  position: fixed; inset: 0; z-index: 200;
  flex-direction: column; align-items: center; justify-content: center; gap: 16px;
  padding: 32px; text-align: center;
  background: #0a0a14; color: #e6e6f0;
  font: 700 16px/1.5 ui-monospace, Menlo, Consolas, monospace; letter-spacing: 1px;
}
#rotate-notice .rn-icon { font-size: 46px; line-height: 1; animation: rn-tip 1.8s ease-in-out infinite; }
#rotate-notice .rn-sub  { font-weight: 400; font-size: 12px; opacity: .65; letter-spacing: 2px; }
@keyframes rn-tip { 0%, 60%, 100% { transform: rotate(0deg); } 30% { transform: rotate(-90deg); } }

/* ===== MY LEVELS browser (player-built levels) ===== */
.levels-panel { min-width: 460px; max-width: 92vw; }
.levels-list {
  width: 420px; max-width: 86vw; max-height: 46vh; overflow-y: auto;
  margin: 6px auto 16px; text-align: left;
  border-top: 1px solid #262638; border-bottom: 1px solid #262638;
}
.levels-empty {
  color: #6a6a7a; text-align: center; padding: 30px 8px;
  line-height: 1.8; letter-spacing: 1px; font-size: 12px;
}
.level-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 6px; border-bottom: 1px solid #1c1c2e;
}
.level-row:last-child { border-bottom: none; }
.level-info { min-width: 0; }
.level-name {
  font-size: 13px; font-weight: 700; letter-spacing: 1px; color: #e6e6f0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 210px;
}
.level-meta { font-size: 10px; color: #6a6a7a; letter-spacing: 1px; margin-top: 3px; text-transform: capitalize; }
.level-actions { display: flex; gap: 5px; flex-shrink: 0; }
/* Compact inline buttons — override the global block/240px button rule. */
.level-btn {
  display: inline-block; width: auto; margin: 0;
  font-size: 10px; letter-spacing: 1px; padding: 7px 11px; border-width: 2px;
}
.level-btn.primary { background: #e6e6f0; color: #0a0a14; }
.level-btn.primary:hover { background: #0a0a14; color: #e6e6f0; }
.level-btn.danger { border-color: #ff6a6a; color: #ff6a6a; padding: 7px 9px; }
.level-btn.danger:hover { background: #ff6a6a; color: #0a0a14; }
.levels-foot { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
body.show-touch .levels-panel { min-width: 0; width: min(94vw, 460px); }
