/* =====================================================================
   KaBoomz - UNIFIED GAMEPLAY SHELL (Batch 7).
   The shared full-viewport gameplay environment for Host Quiz / Host
   Reflex / Player Quiz / Player Reflex. Scoped to body.game-shell-live -
   nothing here leaks into Batches 1-6 or non-activity states.

   OWNERSHIP: this file owns ONLY the shared environment - the coral
   field, burst + edge confetti, genuine logo, generic semantic slots
   (meta / utilities / action / timer / content), surface variants and
   responsive shell behaviour. It NEVER names any activity-specific
   class. Activity shell adaptations live in each activity stylesheet
   (the quiz / reflex stylesheets) using body.game-shell-live as a
   context selector.

   Approved palette only: coral #FF6B4A, orange #FF922B, yellow #FFD43B,
   cyan #21C4F3, lime #7ED957, dark ink #20242C, cream #FFF7ED, white.
   NO PURPLE.
   ===================================================================== */

body.game-shell-live {
  overflow: hidden;
  /* Generic shell geometry hooks. The genuine logo's position/size and its
     fixed aspect ratio are exposed as variables so an activity can place
     its own slots clear of the logo without re-measuring the DOM. The
     logo itself is unchanged. */
  --gs-logo-top: clamp(12px, 1.8vh, 24px);
  --gs-logo-width: clamp(96px, 10vw, 190px);
  --gs-logo-aspect: 0.7416; /* genuine asset height / width */
  --gs-logo-bottom: calc(var(--gs-logo-top) + var(--gs-logo-width) * var(--gs-logo-aspect));
}

/* ---------- LOCKED PALETTE while the shell is live (NO PURPLE) ----------
   The gameplay state is the approved coral/no-purple environment. The
   page's themeable tokens are remapped here so NOTHING rendered during
   gameplay - the shell, the hosted activity content, the status layers
   and the Leave modal - can inherit the legacy purple/magenta values.
   `html body.game-shell-live` outranks `html[data-skin="..."]`, so an
   inactive Cowboy/Neon skin can never recolor this state. Batches 1-6
   outside gameplay keep their existing identity. */
html body.player,
html body.game-shell-live {
  --color-background: #FF6B4A;
  --color-background-mid: #E85A3A;
  --color-background-deep: #C9482C;
  --gradient-stage: linear-gradient(160deg, #FF6B4A 0%, #E85A3A 45%, #C9482C 100%);
  --gradient-stage-base: linear-gradient(160deg, #FF6B4A 0%, #E85A3A 45%, #C9482C 100%);
  --gradient-surface: linear-gradient(180deg, rgba(201, 72, 44, 0) 0%, rgba(201, 72, 44, 0.9) 30%);

  --color-primary: #FFD43B;
  --color-on-primary: #20242C;
  --color-accent: #FFD43B;
  --color-accent-shadow: #FF922B;
  --color-accent-2: #21C4F3;
  --color-secondary: #FF922B;
  --color-focus: #FFD43B;
  --color-surface-inverse: #20242C;

  --scrim-rgb: 32 36 44;
  --stage-scrim-rgb: 32 36 44;
  /* Derived scrim/selection tokens are resolved at :root, so they must be
     redeclared here too - otherwise the legacy purple stage scrim (used by
     the activity overlays) would survive the raw-token remap. */
  --color-scrim-stage: rgb(32 36 44 / 0.55);
  --color-scrim-stage-deep: rgb(32 36 44 / 0.94);
  --color-scrim-ink: rgb(32 36 44 / 0.55);
  --color-scrim-ink-soft: rgb(32 36 44 / 0.6);
  --color-scrim-modal: rgb(32 36 44 / 0.7);
  --color-scrim-card: rgb(32 36 44 / 0.78);
  --color-kick: rgb(32 36 44 / 0.18);
  --color-kick-hover: rgb(32 36 44 / 0.32);
  --color-selection-soft: rgb(255 212 59 / 0.25);
  --color-success-soft: rgb(126 217 87 / 0.16);
  /* Shadow tokens are also :root-resolved composites - redeclare so no
     legacy purple-ink or pink shadow survives on gameplay-state controls. */
  --shadow-button: 0 4px 0 rgb(32 36 44 / 0.45);
  --shadow-button-pressed: 0 1px 0 rgb(32 36 44 / 0.45);
  --shadow-chip: 0 5px 0 rgb(32 36 44 / 0.45);
  --shadow-raised: 0 6px 20px rgba(0, 0, 0, 0.4);
  --shadow-text-glow: 0 3px 14px rgb(32 36 44 / 0.5);
  --shadow-brand: 3px 3px 0 #FF922B, 6px 6px 0 rgb(32 36 44 / 0.35);
  --shadow-brand-small: 2px 2px 0 #FF922B;
  --shadow-brand-single: 3px 3px 0 #FF922B;
  --shadow-pop: 4px 4px 0 #FF922B;

  --palette-1: #FFD43B;
  --palette-2: #21C4F3;
  --palette-3: #21C4F3;
  --palette-4: #FF922B;
  --palette-5: #7ED957;

  --answer-a: #7ED957;
  --answer-b: #21C4F3;
  --answer-c: #FFD43B;
  --answer-d: #FFF7ED;
  --answer-e: #A78BFA;
  --answer-f: #F472B6;

  --gradient-cta: linear-gradient(180deg, #FF6B4A, #E85A3A);
  --shadow-pop-ink: 4px 4px 0 #20242C;
  --fire-shadow: #FF922B;
}

/* ---------- the shell root ----------
   The root never consumes pointer input: clicks on the coral field
   fall through. Only the interactive slots opt back in. */
body.game-shell-live .gs-root {
  position: fixed;
  inset: 0;
  z-index: 900; /* above page chrome, BELOW the countdown overlay (9999) */
  background: #FF6B4A;
  pointer-events: none;
}

/* The content region is full-bleed coral; the host's interactive chrome
   (logo, meta, utilities, action, timer) must sit ABOVE it so a real
   click on the action button or utilities is theirs, and the decorative
   field never captures it. */
body.game-shell-live .gs-root .gs-logo { z-index: 4; }
body.game-shell-live .gs-root .gs-meta { z-index: 5; }
body.game-shell-live .gs-root .gs-utilities { z-index: 5; }
body.game-shell-live .gs-root .gs-action { z-index: 5; }
body.game-shell-live .gs-root .gs-timer { z-index: 5; }
body.game-shell-live .gs-root .gs-content { z-index: 2; }

body.game-shell-live .gs-root .gs-rays,
body.game-shell-live .gs-root .gs-confetti {
  pointer-events: none;
}

/* ---------- pointer model (real interaction) ----------
   Content, the progression action and the utilities, and EVERY
   descendant inside them, receive real pointer input. This is what makes
   Quiz options, Reflex tiles and host buttons actually clickable. */
body.game-shell-live .gs-root .gs-content,
body.game-shell-live .gs-root .gs-content *,
body.game-shell-live .gs-root .gs-action,
body.game-shell-live .gs-root .gs-action *,
body.game-shell-live .gs-root .gs-utilities,
body.game-shell-live .gs-root .gs-utilities * {
  pointer-events: auto;
}

/* ---------- environment: game-show rays (wedges) ---------- */
body.game-shell-live .gs-root .gs-rays {
  position: absolute;
  left: 50%;
  top: 54%;
  width: 170vmax;
  height: 170vmax;
  transform: translate(-50%, -50%);
  background: repeating-conic-gradient(
    from 0deg at 50% 50%,
    rgba(255, 146, 43, 0.16) 0deg 8deg,
    rgba(255, 146, 43, 0.0) 8deg 16deg);
  -webkit-mask: radial-gradient(closest-side, transparent 22%, #000 46%, transparent 82%);
  mask: radial-gradient(closest-side, transparent 22%, #000 46%, transparent 82%);
  opacity: 0.7;
  animation: gs-ray-spin 120s linear infinite;
}

@keyframes gs-ray-spin { from { transform: translate(-50%, -50%) rotate(0deg); } to { transform: translate(-50%, -50%) rotate(360deg); } }

/* ---------- environment: restrained edge confetti ----------
   Small hand-positioned decorations at the edges (rectangles, diamonds,
   bars/slashes, occasional starbursts, a limited number of dots). The
   centre stays clean - nothing overlaps controls or activity text. */
body.game-shell-live .gs-root .gs-confetti > span {
  position: absolute;
  display: block;
}

body.game-shell-live .gs-root .c-dot { width: 9px; height: 9px; border-radius: 50%; }
body.game-shell-live .gs-root .c-rect { width: 18px; height: 9px; border-radius: 2px; }
body.game-shell-live .gs-root .c-diamond { width: 11px; height: 11px; border-radius: 2px; transform: rotate(45deg); }
body.game-shell-live .gs-root .c-bar { width: 22px; height: 4px; border-radius: 2px; transform: rotate(55deg); }
body.game-shell-live .gs-root .c-star { width: 14px; height: 14px; clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%); }

/* edge placement (top-left cluster) */
body.game-shell-live .gs-root .gs-confetti span:nth-child(1) { left: 2.4%; top: 9%; background: #FFD43B; }
body.game-shell-live .gs-root .gs-confetti span:nth-child(2) { left: 3.4%; top: 52%; background: #21C4F3; }
body.game-shell-live .gs-root .gs-confetti span:nth-child(3) { left: 1.2%; top: 31%; background: #FFF7ED; }
body.game-shell-live .gs-root .gs-confetti span:nth-child(4) { left: 4.6%; top: 78%; background: #7ED957; }
/* top-right cluster */
body.game-shell-live .gs-root .gs-confetti span:nth-child(5) { right: 2.2%; top: 12%; background: #FFD43B; }
body.game-shell-live .gs-root .gs-confetti span:nth-child(6) { right: 4.4%; top: 44%; background: #21C4F3; opacity: 0.85; }
body.game-shell-live .gs-root .gs-confetti span:nth-child(7) { right: 1.6%; top: 70%; background: #FFF7ED; }
body.game-shell-live .gs-root .gs-confetti span:nth-child(8) { right: 3.8%; top: 6%; background: #7ED957; }
body.game-shell-live .gs-root .gs-confetti span:nth-child(9) { right: 2.9%; bottom: 8%; background: #FF922B; opacity: 0.9; }

/* ---------- logo (genuine asset, aspect preserved; host top-left) ---------- */
body.game-shell-live .gs-root .gs-logo {
  position: absolute;
  left: clamp(16px, 1.6vw, 34px);
  top: var(--gs-logo-top);
  width: var(--gs-logo-width);
  height: auto;
  max-height: 22vh;
  object-fit: contain;
}

/* ---------- progression band: timer | activity centre | action ----------
   Owner amendment 2026-09-11. Inactive by default (display:none): the
   timer/action slots keep their original absolute placement for every
   surface that does not supply a band element. When an activity supplies
   one, the band becomes a flex row: the side slots keep their protected
   widths (flex: 0 0 auto via their own min-widths), the centre takes the
   remaining space, and all three share one vertical centre however many
   lines the centre wraps to. --gs-band-h (set by the shell's observer)
   lets the content region start below the COMPLETE row. */
body.game-shell-live .gs-root .gs-band {
  position: absolute;
  left: clamp(16px, 1.6vw, 34px);
  right: clamp(16px, 1.6vw, 34px);
  top: var(--gs-band-top, calc(var(--gs-logo-top) + var(--gs-logo-width) * var(--gs-logo-aspect) + 12px));
  z-index: 5;
  display: none;
  align-items: center;
  gap: clamp(14px, 1.6vw, 28px);
}
body.game-shell-live .gs-root.gs-band-live .gs-band { display: flex; }

/* the moved slots become flex items in the row */
body.game-shell-live .gs-root.gs-band-live .gs-timer,
body.game-shell-live .gs-root.gs-band-live .gs-action {
  position: static;
  top: auto;
  left: auto;
  right: auto;
  transform: none;
}

body.game-shell-live .gs-root .gs-band-center {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---------- metadata (top centre) ---------- */
body.game-shell-live .gs-root .gs-meta {
  position: absolute;
  left: 50%;
  top: clamp(12px, 2vh, 26px);
  transform: translateX(-50%);
  max-width: min(58vw, 900px);
  padding: 9px clamp(16px, 1.4vw, 28px);
  border-radius: 999px;
  background: rgba(255, 247, 237, 0.94);
  color: #20242C;
  font-weight: 800;
  font-size: clamp(15px, 1.5vw, 26px);
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- host utilities (top right) ---------- */
body.game-shell-live .gs-root .gs-utilities {
  position: absolute;
  right: clamp(16px, 1.6vw, 34px);
  top: clamp(12px, 1.8vh, 24px);
  display: flex;
  gap: clamp(8px, 0.8vw, 14px);
}

body.game-shell-live .gs-root .gs-util {
  width: clamp(38px, 3.2vw, 52px);
  height: clamp(38px, 3.2vw, 52px);
  border-radius: 50%;
  border: 3px solid #FFFFFF;
  background: #FFF7ED;
  color: #20242C;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 3px 0 rgba(160, 34, 12, 0.35);
}

body.game-shell-live .gs-root .gs-util:hover { filter: brightness(1.06); }
body.game-shell-live .gs-root .gs-util:active { transform: translateY(2px); }
body.game-shell-live .gs-root .gs-util:focus-visible {
  outline: 3px solid #FFD43B;
  outline-offset: 2px;
}

body.game-shell-live .gs-root .gs-util.gs-active { background: #FFD43B; }

/* approved speaker on/off glyphs (reused from the Lobby/Instruction
   controls), toggled by the .muted class */
body.game-shell-live .gs-root .gs-util .gs-ic {
  width: 22px;
  height: 22px;
}
body.game-shell-live .gs-root .gs-util.muted .gs-ic-on { display: none; }
body.game-shell-live .gs-root .gs-util:not(.muted) .gs-ic-off { display: none; }

/* ---------- progression action (top right, below utilities) ----------
   EXACTLY ONE primary control. Secondary controls stay in the activity
   presentation and are never styled here. */
body.game-shell-live .gs-root .gs-action {
  position: absolute;
  right: clamp(16px, 1.6vw, 34px);
  /* Generic hook: an activity may move the action via --gs-action-top. */
  top: var(--gs-action-top, calc(clamp(12px, 1.8vh, 24px) + clamp(48px, 4vw, 68px)));
  min-width: clamp(150px, 11vw, 250px);
  min-height: clamp(52px, 8vh, 96px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Owner-approved progression button (owner correction 2026-09-30): a
   NORMAL yellow KaBoomz button - no thick permanent white outline and no
   decorative drop shadow. Keyboard focus is still indicated, but only
   while the button actually has focus (:focus-visible); the press uses a
   restrained transform feedback that never moves the surrounding
   layout. Geometry (slot width/height) is untouched. */
body.game-shell-live .gs-root .gs-action > * {
  appearance: none;
  cursor: pointer;
  border: 0;
  background: #FFD43B;
  color: #20242C;
  font-weight: 800;
  font-size: clamp(1.05rem, 1.7vw, 1.55rem);
  padding: 0 clamp(20px, 1.6vw, 34px);
  height: clamp(52px, 8vh, 96px);
  min-width: clamp(150px, 11vw, 250px);
  border-radius: clamp(14px, 1.5vw, 22px);
  box-shadow: none;
}
body.game-shell-live .gs-root .gs-action > *:hover:not(:disabled) { filter: brightness(1.05); }
body.game-shell-live .gs-root .gs-action > *:active:not(:disabled) {
  transform: translateY(2px);
  box-shadow: none;
}
body.game-shell-live .gs-root .gs-action > *:focus-visible {
  outline: 3px solid #FFD43B;
  outline-offset: 3px;
}
body.game-shell-live .gs-root .gs-action > *:disabled {
  cursor: default;
  opacity: 1;
  filter: saturate(0.45) brightness(0.97);
  box-shadow: none;
}

/* ---------- host timer slot (left, below the logo) ----------
   A distinct, readable timer surface: a cream chrome ring around coral.
   The moved timer keeps its activity classes; this is the surface it
   sits on (value/labels stay activity-owned). */
body.game-shell-live .gs-root .gs-timer {
  position: absolute;
  left: clamp(20px, 2.2vw, 48px);
  /* Generic positioning hook: an activity may align the slot with its own
     upper-right action via --gs-timer-top (Quiz does). */
  top: var(--gs-timer-top, calc(clamp(12px, 1.8vh, 24px) + clamp(120px, 17vw, 260px)));
  min-width: clamp(140px, 14vw, 230px);
  display: flex;
  align-items: center;
  justify-content: center;
}

body.game-shell-live .gs-root .gs-timer > * {
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  color: #20242C;
  background: #FFF7ED;
  border: 4px solid rgba(255, 255, 255, 0.85);
  border-radius: clamp(16px, 2vw, 28px);
  padding: clamp(8px, 1.2vh, 16px) clamp(16px, 2vw, 34px);
  box-shadow: 0 4px 0 rgba(160, 34, 12, 0.35), 0 8px 20px rgba(160, 34, 12, 0.22);
  font-size: clamp(2.4rem, 6vw, 4.4rem);
  line-height: 1;
}

/* ---------- central activity-content region ---------- */
body.game-shell-live .gs-root .gs-content {
  position: absolute;
  left: clamp(10px, 1.6vw, 34px);
  right: clamp(10px, 1.6vw, 34px);
  /* Generic hook: an activity may clear its own top band (logo + slots)
     via --gs-content-top. */
  top: var(--gs-content-top, calc(clamp(12px, 1.8vh, 24px) + clamp(72px, 8vh, 120px)));
  bottom: clamp(10px, 2vh, 34px);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The hosted hero fills the usable region (activity-specific scale hooks
   live in the activity stylesheets). */
body.game-shell-live .gs-root .gs-content > * {
  width: min(78vw, 1280px);
  max-width: 100%;
  max-height: 100%;
  margin: 0 auto;
}

/* activity-mount stays as the activity's type-agnostic DOM home: collapse
   it while the shell hosts the hero (ids still resolve inside the shell) */
body.game-shell-live #activity-mount {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* legacy host page chrome (account bar) is never part of gameplay */
body.game-shell-live.game-shell-host .host-top { display: none; }

/* ---------- reduced motion: same geometry, no motion ---------- */
@media (prefers-reduced-motion: reduce) {
  body.game-shell-live .gs-root .gs-rays,
  body.game-shell-live .gs-root .gs-confetti > span {
    animation: none !important;
    transition: none !important;
    transform: none !important;
  }
}

/* ---------- safe-area padding (never changes viewport dimensions) ---------- */
body.game-shell-live .gs-root {
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* ====================================================================
   PLAYER SURFACE variant (body.game-shell-live.game-shell-player)
   One canonical selector per surface - no body/root name mixing.
   ==================================================================== */

/* player shows none of the host chrome: no metadata, no utilities, no
   action, no timer. Class-driven (never inline display). */
body.game-shell-live.game-shell-player .gs-meta,
body.game-shell-live.game-shell-player .gs-utilities,
body.game-shell-live.game-shell-player .gs-action,
body.game-shell-live.game-shell-player .gs-timer {
  display: none;
}

/* player logo: genuinely centred near the top */
body.game-shell-live.game-shell-player .gs-logo {
  left: 50%;
  top: calc(env(safe-area-inset-top) + clamp(12px, 2.5vh, 28px));
  transform: translateX(-50%);
  width: clamp(140px, 46vw, 210px);
  max-height: 15vh;
}

/* player content fills the useful height of the phone (below the logo).
   The bottom inset RESERVES space for the always-visible Leave control
   so the activity can never sit underneath it. */
body.game-shell-live.game-shell-player .gs-content {
  left: clamp(12px, 6vw, 44px);
  right: clamp(12px, 6vw, 44px);
  top: calc(env(safe-area-inset-top) + clamp(88px, 22vh, 170px));
  bottom: calc(env(safe-area-inset-bottom) + clamp(72px, 12vh, 104px));
}

body.game-shell-live.game-shell-player .gs-content > * {
  width: min(92vw, 520px);
}

/* ---------- live status layers above the shell (NO PURPLE) ----------
   Reconnect, host-warning and toast must be SEEN during gameplay, so they
   sit above the shell but below the Leave modal (950) and the blocking
   countdown (9999). Styling flows from the remapped tokens above (ink
   backgrounds, yellow accents). */
body.game-shell-live .reconnect-banner,
body.game-shell-live .host-banner {
  z-index: 930;
}
body.game-shell-live .toast {
  z-index: 925;
  /* keep clear of the Leave control so a toast never blocks it */
  bottom: calc(env(safe-area-inset-bottom) + 4.75rem);
}

/* the Leave control is core player functionality: visible above the
   shell, comfortable target, cream on coral */
body.game-shell-live .leave-btn {
  z-index: 920;
  color: #FFF7ED;
  text-shadow: 0 1px 0 rgba(160, 34, 12, 0.5);
}

/* Owner correction 2026-09-30 (checker item 6): Leave game is PLAYER
   functionality. On a HOST surface it is redundant (End game is the
   approved exit) and could collide with the final results; it is never
   rendered on host gameplay screens. */
body.game-shell-live.game-shell-host .leave-btn { display: none; }

/* suspend keeps the live game MOUNTED and VISIBLE (dimmed by the Leave
   modal's scrim) but inert behind the confirmation - never a blank page */
body.game-shell-live .gs-root.gs-suspended {
  pointer-events: none;
}

/* ---------- small-height guard: keep proportions, never flatten ---------- */
@media (max-height: 500px) {
  body.game-shell-live.game-shell-host .gs-timer {
    top: clamp(12px, 1.8vh, 24px);
    left: 50%;
    transform: translateX(-50%);
    min-width: auto;
  }
}

/* ---------- compact phone chrome (no-scroll promise) ----------
   On a small phone the logo and the Leave reserve are the two biggest
   non-gameplay consumers of height. Shrink the genuine logo (aspect kept)
   and tighten the reserves so the approved maximum question + answers fit
   with no page or stage scroll and no clipped text. Larger phones (>=640px
   wide or >=721px tall) keep the standard composition. */
@media (max-width: 480px) and (max-height: 720px) {
  body.game-shell-live.game-shell-player .gs-logo {
    top: calc(env(safe-area-inset-top) + clamp(4px, 1vh, 10px));
    width: clamp(76px, 26vw, 120px);
    max-height: none;
  }
  body.game-shell-live.game-shell-player .gs-content {
    top: calc(env(safe-area-inset-top) + 70px);
    /* 60px keeps the last card (including its bottom border) clear of the
       Leave control's top edge on compact phones (owner contract: no
       overlap with controls; verified by the worst-case suite). The 56px
       Quiz-answering-only correction lives in activities/quiz/quiz.css,
       scoped with :has() to the answering state, so Reflex, pre-go,
       confirmation, reveal and every other compact player screen keep this
       shared default. */
    bottom: calc(env(safe-area-inset-bottom) + 60px);
  }
}
