/* oktodrop — "midnight arcade in the abyss" (site tokens) */
:root{
  --abyss-0:#03040c; --abyss-1:#070a1c; --abyss-2:#0c1334;
  --ink:#e9f1ff; --ink-dim:#8290c0; --ink-faint:#4d5a85;
  --mag:#c061ff; --mag-deep:#7c3aed;           /* Okto-Drop accent */
  --gold:#ffd23f;
  --panel:rgba(11,17,40,.74); --edge:rgba(124,154,255,.18);
  --font-ui:'Chakra Petch', ui-sans-serif, system-ui, sans-serif;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{background:var(--abyss-0);color:var(--ink);font-family:var(--font-ui);
  display:flex;align-items:center;justify-content:center;overflow:hidden;touch-action:none}
/* Task 38 — OS touch hardening (iPhone Safari / Android Chrome): no long-press
   callout, no selection loupe, no tap flash, no rubber-band overscroll. The
   body's touch-action:none already stops native pan/zoom on descendants; the
   tappable game surfaces repeat it explicitly so no future child rule can
   re-open a native gesture. Pointer-event input is unaffected. */
html,body{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;
  -webkit-tap-highlight-color:transparent;overscroll-behavior:none}
#game,#intermission,#rotate-prompt,#mobile-controls,#hud{touch-action:none}
#stage{position:relative;width:min(100vw, calc(100vh * 580 / 720));
  height:min(100vh, calc(100vw * 720 / 580));aspect-ratio:580/720;
  background:radial-gradient(90% 70% at 50% 30%, var(--abyss-2), var(--abyss-1) 55%, var(--abyss-0));
  border-radius:6px;box-shadow:0 0 0 1px var(--edge), 0 0 44px rgba(124,97,255,.18), 0 30px 60px -30px rgba(0,0,0,.8)}
#game{width:100%;height:100%;display:block}
/* HUD (built by game.js inside #stage) — themed per era via --era-* custom
   props set by applyEraTheme() from the era palette.
   Task 44 — three-region layout: a TEXT-ONLY top strip (SCORE + LINES x/y),
   a LEFT rail with the Tidal Flush gauge (sole occupant since the quest
   gauges were retired), and a RIGHT rail (NEXT-2 queue + reserved bottom) on
   desktop/touch-wide. The phone keeps its maximized board: NEXT-2 folds into
   the strip's right end, the gauge rides the thin left rail, controls stay
   in the bottom band. Region rects are positioned inline by
   applyHudScale(); only sizes/styles live here. */
#hud{position:absolute;inset:0;pointer-events:none;z-index:3;
  --era-accent:var(--mag);--era-text:var(--ink);--era-dim:var(--ink-dim)}
#hud-top{position:absolute;display:flex;align-items:stretch;justify-content:center;gap:12px}
#hud-top .hud-box{flex:0 1 auto;padding:2px 14px;text-align:center}
#hud-top .hud-label{margin-bottom:1px}
#hud-top .hud-text div:last-child{font-size:21px}
#hud-lines-box .goal-track{width:100%;min-width:64px;margin-top:2px}
#hud-top #hud-next{margin-left:auto;align-self:center}   /* phone: queue parks at the strip's right end */
/* left rail — the flush gauge (fill height + quarter ticks), sole occupant;
   vertically centred now the quest gauges are gone */
#hud-left{position:absolute;display:flex}
#hud-gauges{flex:1;display:flex;flex-direction:column;justify-content:center;gap:6px;min-height:0}
.vgauge{position:relative;flex:1 1 0;min-height:26px;border-radius:6px;overflow:hidden;
  border:1px solid color-mix(in srgb, var(--era-accent) 38%, transparent);
  background:color-mix(in srgb, var(--era-accent) 10%, transparent)}
.vgauge::after{content:'';position:absolute;inset:0;pointer-events:none;   /* quarter tick marks */
  background:repeating-linear-gradient(to top,
    transparent 0 calc(25% - 1px),
    color-mix(in srgb, var(--era-dim) 60%, transparent) calc(25% - 1px) 25%)}
.vg-fill{position:absolute;left:0;right:0;bottom:0;height:0;background:var(--era-accent);
  transition:height .25s}
.vgauge.vg-flush{flex:0 0 auto;min-height:64px}          /* flush charge anchors the rail bottom */
#flush-gauge.ready{animation:flush-pulse 1.6s ease-in-out infinite}   /* RM: kill-switch → steady */
#flush-gauge.ready .vg-fill{background:var(--era-flash,#fff);
  box-shadow:0 0 10px 2px var(--era-accent)}
/* Task 5 — one-shot gain flash when a clear moves the meter. The animation
   lives on .vg-fill (never on the gauge itself) so it cannot override
   #flush-gauge.ready's flush-pulse. Animate filter only: background/box-shadow
   are owned by the .ready styling. RM: kill-switch → no flash, fill just steps. */
#flush-gauge.gain .vg-fill{animation:meter-gain .45s ease-out}
@keyframes meter-gain{0%{filter:brightness(2.6)}100%{filter:brightness(1)}}
@keyframes flush-pulse{0%,100%{box-shadow:0 0 4px 0 var(--era-accent)}
  50%{box-shadow:0 0 14px 3px var(--era-accent)}}
/* right rail — NEXT-2 queue + reserved bottom (desktop/touch-wide only) */
#hud-right{position:absolute;display:flex;flex-direction:column;gap:8px}
#hud-next-wrap{flex:0 0 auto;border:1px solid color-mix(in srgb, var(--era-accent) 30%, transparent);
  border-radius:8px;background:color-mix(in srgb, var(--era-panel, var(--panel)) 70%, transparent);
  padding:6px 0}
#hud-right #hud-next{display:block;width:96px;height:144px;margin:0 auto}
#hud-reserved{flex:1 1 0;min-height:40px;border-radius:8px;   /* styled, deliberately empty */
  border:1px dashed color-mix(in srgb, var(--era-accent) 25%, transparent);
  background:color-mix(in srgb, var(--era-panel, var(--panel)) 40%, transparent)}
/* shared box chrome + goal track */
.hud-box{background:color-mix(in srgb, var(--era-panel, var(--panel)) 88%, transparent);
  border:1px solid color-mix(in srgb, var(--era-accent) 38%, transparent);
  border-radius:8px;padding:8px;text-align:center}
.hud-label{font-size:11px;letter-spacing:.14em;color:var(--era-dim);margin-bottom:6px}
.hud-text div:last-child{font-size:19px;font-weight:600;color:var(--era-text);font-variant-numeric:tabular-nums}
.goal-track{display:block;height:4px;margin-top:5px;border-radius:2px;
  background:color-mix(in srgb, var(--era-accent) 15%, transparent);overflow:hidden}
#goal-prog{display:block;height:100%;width:0;background:var(--era-accent);transition:width .25s}
#goal-prog.full{background:var(--era-flash,#fff);box-shadow:0 0 8px 1px var(--era-accent)}
/* Task 44 phone strip: authored at text-floor sizes (label ≥10, value ≥12) */
#hud.hud-phone .hud-label{font-size:10px;letter-spacing:.06em;margin-bottom:0}
#hud.hud-phone .hud-text div:last-child{font-size:15px}
#hud.hud-phone #hud-next{width:96px;height:36px;border-radius:8px;   /* its own container — no label */
  border:1px solid color-mix(in srgb, var(--era-accent) 30%, transparent);
  background:color-mix(in srgb, var(--era-panel, var(--panel)) 70%, transparent)}
#hud.hud-phone #hud-lines-box{min-width:86px}
/* Task 44 — the phone gauge rail is ~20px wide: ticks + fill ONLY (the brief's
   preferred treatment); no count element on the flush gauge. */
@media (max-width:359px){
  #hud.hud-phone{gap:2px}
  #hud.hud-phone .hud-box{padding:1px 6px}
  #hud.hud-phone .hud-text div:last-child{font-size:13px}
  #hud.hud-phone #hud-next{width:78px;height:29px}
}
/* Task 35 — phone control band (bottom): pause/music/fullscreen chips move
   BELOW the board next to the input chip (Task 44: they stay here — the
   left rail is a 20px gauge column, far below the 44px tap floor). */
#stage.phone-hud #pause-btn,#stage.phone-hud #mute-btn,#stage.phone-hud #fs-btn{
  top:auto;bottom:calc(6px + env(safe-area-inset-bottom));width:56px;padding:12px 0;font-size:11px}
#stage.phone-hud #pause-btn{right:calc(128px + env(safe-area-inset-right))}
#stage.phone-hud #mute-btn{right:calc(68px + env(safe-area-inset-right))}
#stage.phone-hud #fs-btn{right:calc(8px + env(safe-area-inset-right))}
#stage.phone-hud #input-chip{top:auto;bottom:calc(10px + env(safe-area-inset-bottom))}
/* The FLUSH fab rides the seam between board bottom and control band — an
   intentional control surface over the playfield edge (same exclusion class as
   the button pad), centered where the thumb lands. */
#stage.phone-hud #undertow-fab{right:auto;left:50%;transform:translateX(-50%);
  bottom:calc(56px + env(safe-area-inset-bottom));width:min(140px,42vw);padding:12px 0}
/* Task 35 — the descend card renders at natural size on phone (the old tiny
   --hud-scale starved it); diorama shrinks so the card fits short stages. */
#stage.phone-hud #intermission .im-panel[data-role=pre]{transform:none}
#stage.phone-hud #diorama-slot{width:min(220px,64%)}
#stage.phone-hud #intermission .im-name{font-size:22px}
#stage.phone-hud #intermission .im-goal .g-main{font-size:22px}
@media (hover:none) and (pointer:coarse){
  #stage{width:100vw;height:100vh;aspect-ratio:auto;border-radius:0;box-shadow:none}
}
/* Button pad (built in index.html; visibility driven by game.js — coarse
   pointer + settings.inputMode === 'buttons'). Fine pointers never see it. */
#mobile-controls{position:absolute;left:0;right:0;bottom:0;
  display:grid;grid-template-columns:repeat(4,1fr);gap:8px;
  padding:10px calc(10px + env(safe-area-inset-right)) calc(10px + env(safe-area-inset-bottom)) calc(10px + env(safe-area-inset-left));
  background:linear-gradient(to top, rgba(3,4,12,.88), rgba(3,4,12,0));}
#mobile-controls[hidden]{display:none}
#mobile-controls button{font-family:var(--font-ui);font-size:17px;font-weight:600;
  color:var(--ink);background:var(--panel);border:1px solid var(--edge);border-radius:10px;
  padding:14px 0;touch-action:none;user-select:none;-webkit-user-select:none}
#mobile-controls button:active{background:rgba(124,97,255,.28)}
#mobile-controls button[data-act="undertow"]{color:var(--gold);letter-spacing:.06em}
#mobile-controls button:disabled{opacity:.35}
/* Task 27 — floating FLUSH button (touch, both input modes; Task 33 renamed the
   mechanic — id/data-act stay 'undertow' for stability) + input chip.
   Fab sits bottom-right in the free strip right of the board (board spans the
   left ~60% of canvas width; vw cap keeps it clear on narrow phones), above
   the button pad when that pad is up (.pad-up). Era-styled via the --era-*
   props applyEraTheme() sets on #stage. Fine pointers never see either. */
#undertow-fab{position:absolute;right:12px;bottom:calc(16px + env(safe-area-inset-bottom));
  width:min(120px,36vw);z-index:4;font-family:var(--font-ui);
  font-size:max(12px,calc(14px * var(--hud-scale,1)));font-weight:700;
  letter-spacing:.08em;color:var(--era-text,var(--ink));cursor:pointer;
  background:color-mix(in srgb, var(--era-panel,var(--panel)) 92%, transparent);
  border:1px solid color-mix(in srgb, var(--era-accent) 55%, transparent);
  border-radius:10px;padding:14px 0;touch-action:none;user-select:none;-webkit-user-select:none;
  box-shadow:0 0 14px 1px color-mix(in srgb, var(--era-accent) 45%, transparent)}
#undertow-fab:active{background:color-mix(in srgb, var(--era-accent) 30%, transparent)}
/* Task 5 — ready pulse while the meter is spendable. Box-shadow ONLY: a
   transform here would fight #stage.phone-hud's translateX(-50%) centering.
   RM: kill-switch → steady base glow. */
#undertow-fab.ready-pulse{animation:fab-ready 1.2s ease-in-out infinite}
@keyframes fab-ready{0%,100%{box-shadow:0 0 10px 1px color-mix(in srgb, var(--era-accent) 55%, transparent)}
  50%{box-shadow:0 0 22px 4px color-mix(in srgb, var(--era-accent) 85%, transparent)}}
#undertow-fab.pad-up{bottom:calc(158px + env(safe-area-inset-bottom))}  /* clear the 2-row button pad */
#undertow-fab[hidden]{display:none}
#input-chip{position:absolute;top:calc(10px + env(safe-area-inset-top));left:calc(10px + env(safe-area-inset-left));
  z-index:4;font-family:var(--font-ui);
  font-size:max(10px,calc(11px * var(--hud-scale,1)));font-weight:600;letter-spacing:.1em;
  color:var(--era-dim,var(--ink-dim));background:color-mix(in srgb, var(--era-panel,var(--panel)) 85%, transparent);
  border:1px solid var(--edge);border-radius:999px;padding:6px 12px;touch-action:none;
  user-select:none;-webkit-user-select:none}
#input-chip:active{color:var(--era-text,var(--ink))}
#input-chip[hidden]{display:none}
/* Task 32 — touch control stack (top-right): PAUSE / MUSIC / FULLSCREEN.
   Era-styled chips, same idiom as the fab/chip; fine pointers never see them
   (desktop keeps keyboard ESC + the canvas F-pill). Pause is visible only
   while playing/paused (game.js drives that). */
#pause-btn,#mute-btn,#fs-btn{position:absolute;right:calc(10px + env(safe-area-inset-right));
  z-index:4;width:104px;font-family:var(--font-ui);
  font-size:max(10px,calc(11px * var(--hud-scale,1)));font-weight:700;letter-spacing:.06em;
  color:var(--era-text,var(--ink));cursor:pointer;touch-action:none;
  user-select:none;-webkit-user-select:none;
  background:color-mix(in srgb, var(--era-panel,var(--panel)) 88%, transparent);
  border:1px solid color-mix(in srgb, var(--era-accent) 55%, transparent);
  border-radius:10px;padding:12px 0}
#pause-btn{top:calc(8px + env(safe-area-inset-top))}
#mute-btn{top:calc(58px + env(safe-area-inset-top))}
#fs-btn{top:calc(108px + env(safe-area-inset-top))}
#pause-btn:active,#mute-btn:active,#fs-btn:active{background:color-mix(in srgb, var(--era-accent) 30%, transparent)}
#pause-btn[hidden],#mute-btn[hidden],#fs-btn[hidden]{display:none}

/* Rotate prompt — same query string as the JS listener (repo convention). */
#rotate-prompt{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:rgba(3,4,12,.92);color:var(--ink);font-size:20px;font-weight:700;letter-spacing:.14em;z-index:5}
#rotate-prompt[hidden]{display:none}

/* ===== Task 13 + Task 30: campaign flow ===== */
/* Intermission overlay — TWO panels (Task 30): the pre-level descend card
   (data-role=pre: phase-descend dive → phase-reveal diorama → phase-card →
   phase-ready) and the post-clear beat (data-role=post:
   phase-cleared → phase-stats). Timings live in game.js DESCEND_PHASES /
   POST_PHASES. #diorama-slot is the Task 20 slot, pre-level since Task 30.
   Task 26 — the art owns the ENTIRE descend: the pre panel + #diorama-slot
   are lit from phase-descend (screen entry) through phase-ready (countdown);
   the D3 text bands compose above/below the slot, never replacing it.
   Task 27 — the post-clear beat carries the JUST-CLEARED era's art
   (#diorama-slot-post, mounted in goalReached via the same startImArt
   funnel): lit from phase-cleared (with the STAGE CLEARED message) through
   phase-stats; the next descend's exchange then animates cleared→next. */
#intermission{position:absolute;inset:0;z-index:6;display:flex;align-items:center;justify-content:center;
  background:rgba(3,4,12,.82);pointer-events:none}   /* tap-skip targets the canvas — the veil must not swallow it */
#intermission.hidden{display:none}
#intermission .im-panel{text-align:center;font-family:var(--font-ui);width:min(480px,100%);
  padding:0 12px}
/* only the active role's panel is visible */
#intermission .im-panel[data-role=pre],#intermission .im-panel[data-role=post]{display:none}
#intermission.phase-descend .im-panel[data-role=pre],#intermission.phase-reveal .im-panel[data-role=pre],
#intermission.phase-card .im-panel[data-role=pre],#intermission.phase-ready .im-panel[data-role=pre]{display:block}
#intermission.phase-cleared .im-panel[data-role=post],#intermission.phase-stats .im-panel[data-role=post]{display:block}
/* Task 28 — the pre-level card scales with the HUD column */
#intermission .im-panel[data-role=pre]{transform:scale(var(--hud-scale,1));transform-origin:center}
/* cumulative child reveal within each panel */
#intermission .im-cleared,#intermission .im-stars,#intermission .im-stats,
#diorama-slot,#diorama-slot-post,#intermission .im-hintline,#intermission .im-kicker,#intermission .im-name,
#intermission .im-sub,#intermission .im-mech,#intermission .im-goal,#intermission .im-flush,
#intermission .im-credit,#intermission .im-ready,#intermission .im-hint{opacity:0;
  transition:opacity .4s ease}
#intermission.phase-cleared .im-cleared{opacity:1}
#intermission.phase-stats .im-stars,#intermission.phase-stats .im-stats{opacity:1}
/* Task 27 — the cleared era's art is lit for the WHOLE post-clear beat (with
   the message at P1, with stars + stats at P2); torn down only at the next
   descend/complete/map exit (hideIntermission → stopImArt, the one funnel) */
#intermission.phase-cleared #diorama-slot-post,
#intermission.phase-stats #diorama-slot-post{opacity:1}
/* Task 26 — the art slot (with its hintline caption) stays lit through EVERY
   descend phase: D1 entry → D2 → D3 card → D4 countdown (was reveal-only —
   the slot faded out the moment the D3 card text appeared) */
#intermission.phase-descend #diorama-slot,#intermission.phase-descend .im-hintline,
#intermission.phase-reveal #diorama-slot,#intermission.phase-reveal .im-hintline,
#intermission.phase-card #diorama-slot,#intermission.phase-card .im-hintline,
#intermission.phase-ready #diorama-slot,#intermission.phase-ready .im-hintline{opacity:1}
#intermission.phase-card .im-kicker,#intermission.phase-card .im-name,
#intermission.phase-card .im-sub,#intermission.phase-card .im-mech,
#intermission.phase-card .im-goal,#intermission.phase-card .im-flush,
#intermission.phase-card .im-credit{opacity:1}
#intermission.phase-ready .im-ready,#intermission.phase-ready .im-hint{opacity:1}
/* post-clear beat */
#intermission .im-cleared{font-size:26px;font-weight:700;letter-spacing:.12em;color:#e9f1ff}
#intermission .im-stars{font-size:30px;color:#ffd873;margin-top:8px;letter-spacing:.2em}
#intermission .im-stats{font-size:13px;color:#8290c0;margin-top:10px;line-height:1.9}
#intermission .im-stats b{color:#e9f1ff}
/* pre-level descend card */
#diorama-slot{width:min(480px,100%);margin:0 auto;border:1px solid rgba(143,208,255,.35);
  border-radius:10px;background:rgba(10,18,34,.6);overflow:hidden}
#diorama-slot canvas{display:block;width:100%;height:auto}
#diorama-slot span{font-size:11px;color:#5f6f92;letter-spacing:.06em}
/* Task 27 — the post-clear art slot: the SAME plate grammar as the descend
   slot, composed under the STAGE CLEARED message (the post panel also stacks
   stars + stats below, hence the breathing margin) */
#diorama-slot-post{width:min(480px,100%);margin:14px auto 0;border:1px solid rgba(143,208,255,.35);
  border-radius:10px;background:rgba(10,18,34,.6);overflow:hidden}
#diorama-slot-post canvas{display:block;width:100%;height:auto}
#intermission .im-hintline{font-size:11px;font-style:italic;color:#5f6f92;margin-top:6px}
#intermission .im-kicker{font-size:11px;letter-spacing:.3em;color:#8290c0;margin-top:12px}
#intermission .im-name{font-size:26px;font-weight:700;color:var(--era-accent,#8fd0ff);margin-top:2px}
#intermission .im-sub{font-size:12px;color:#8290c0;margin-top:2px}
#intermission .im-mech{font-size:12px;font-style:italic;color:#aebadb;margin-top:6px}
/* Task 5 — the Tidal Flush rule under the mechanic line (accent ties it to the gauge) */
#intermission .im-flush{font-size:12px;color:var(--era-accent,#8fd0ff);margin-top:6px}
#intermission .im-goal{margin:10px auto 0;padding:8px 12px;max-width:340px;border:1px solid var(--era-accent,#8fd0ff);
  border-radius:8px;background:rgba(0,0,0,.35);text-align:left}
#intermission .im-goal .g-label{display:block;font-size:10px;letter-spacing:.3em;color:var(--era-accent,#8fd0ff)}
#intermission .im-goal .g-main{display:block;font-size:26px;font-weight:700;color:var(--era-text,#e9f1ff);line-height:1.15}
#intermission .im-goal .g-prog{display:block;font-size:10px;color:#8290c0}
#intermission .im-credit{font-size:10px;color:#5f6f92;margin-top:8px}
#intermission .im-ready{font-size:20px;font-weight:700;letter-spacing:.3em;color:#c061ff;margin-top:14px}
#intermission .im-ready #im-count{color:var(--era-accent,#8fd0ff);font-size:26px;vertical-align:middle}
#intermission .im-hint{font-size:11px;color:#61708f;margin-top:10px}
/* D1/P3 descend veil — the depth counter floats over the canvas dive */
#intermission #descend-veil{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:10px;opacity:0;pointer-events:none;
  transition:opacity .3s ease}
/* Task 26 — the art slot owns the overlay's center from D1 entry, so the
   depth counter rides ABOVE it (it was dead-center over an empty screen when
   D1 had no panel); the veil fades out with the D1→D2 flip either way */
#intermission.phase-descend #descend-veil{opacity:1;justify-content:flex-start;
  padding-top:clamp(18px,7vh,72px)}
#intermission.phase-descend{background:transparent}   /* the canvas dive IS the backdrop */
#intermission #descend-veil .dv-label{font-family:var(--font-ui);font-size:11px;
  letter-spacing:.4em;color:#61708f}
#intermission #descend-veil #depth-counter{font-family:var(--font-ui);font-size:34px;font-weight:700;
  letter-spacing:.06em;color:var(--era-text,#e9f1ff);font-variant-numeric:tabular-nums;
  text-shadow:0 0 18px var(--era-accent,#8fd0ff)}
/* Tutorial hint toast — era 0 first attempt, once each (oktodrop_seen_tutorial) */
#hint-toast{position:absolute;left:50%;bottom:18%;transform:translateX(-50%);z-index:7;
  font-family:var(--font-ui);font-size:14px;font-weight:600;letter-spacing:.05em;color:#e9f1ff;
  background:rgba(10,18,34,.85);border:1px solid rgba(143,208,255,.4);border-radius:8px;
  padding:8px 16px;pointer-events:none;opacity:0;transition:opacity .3s ease}
#hint-toast.show{opacity:1}
#hint-toast[hidden]{display:none}

/* Task 24 — reduced-motion kill-switch: gauge/goal pulses, toast fades all
   snap to their end state. Canvas motion (plankton drift) is gated
   separately in game.js via the same media query. */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  #hint-toast.show { opacity: 1; }
}
