/* =============================================================================
   MysteryBox — Player shell, controls, overlays.
   Loaded AFTER /css/tokens.css, which owns every token. This file declares none.

   House rules from DESIGN-SYSTEM.md section 11, observed throughout:
     - no hex literals (colour only ever via var(--c-*) / var(--grad-*))
     - no z-index literals (var(--z-*))
     - no `transition: all` — properties are always named
     - no !important outside the reduced-motion layer (which lives in tokens.css)
     - every interactive element ships its :focus-visible state (tokens.css paints the
       dual ring globally; components must not clip it)
   ========================================================================== */

/* -----------------------------------------------------------------------------
   1. BACKDROP LAYERS
   The background image is admin-supplied, so it is a real <img> — never a CSS url().
   -------------------------------------------------------------------------- */
.mb-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-below);
  overflow: hidden;
  pointer-events: none;
}

.mb-backdrop__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* Covers correctly in portrait and landscape without distorting. */
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}
.mb-backdrop__img.is-loaded { opacity: 1; }

/* Keeps player text readable over ANY image the admin picks. Opacity is set from
   background_overlay (0-90) as a plain number by chrome.js. */
.mb-backdrop__scrim {
  position: absolute;
  inset: 0;
  background-color: var(--c-base-deep);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}

/* No image (or a dead URL): fall back to the built-in sea-and-sky gradient
   (PROJECT-BRIEF ADDENDUM 3 section 11.2). Composed from base/surface tokens, so it
   re-points with the palette instead of hardcoding a sea colour. */
.mb-backdrop__sea {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
  background-image: linear-gradient(
    180deg,
    var(--c-surface-1) 0%,
    var(--c-base) 34%,
    var(--c-surface-2) 49%,
    var(--c-base) 56%,
    var(--c-base-deep) 100%
  );
}

.mb-backdrop.is-fallback .mb-backdrop__img { display: none; }
.mb-backdrop.is-fallback .mb-backdrop__sea { opacity: 1; }

/* Warm haze drifting over whatever the backdrop is. Purely decorative — the
   data-decorative-motion hook in tokens.css removes it under reduced motion. */
.mb-mesh {
  position: fixed;
  inset: 0;
  z-index: var(--z-below);
  pointer-events: none;
  background-image: var(--grad-mesh);
  background-size: 170% 170%;
  background-position: 50% 50%;
  opacity: 0.85;
  animation: mb-mesh-drift 28s var(--ease-in-out) infinite alternate;
}

@keyframes mb-mesh-drift {
  from { background-position: 34% 30%; }
  to { background-position: 66% 72%; }
}

/* -----------------------------------------------------------------------------
   2. APP SHELL
   -------------------------------------------------------------------------- */
.app-shell {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

.app-header {
  width: 100%;
  max-width: var(--measure-page);
  margin-inline: auto;
  padding: var(--sp-4) var(--sp-gutter) var(--sp-2);
}

.app-header__brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 1.75rem;
  max-width: none;
}

/* A small brass rivet, in keeping with the chest hardware. */
.app-header__mark {
  width: 0.75rem;
  height: 0.75rem;
  border-radius: var(--r-pill);
  background-image: var(--grad-primary);
  box-shadow: var(--glow-amber);
}

/* Height reserved up front so a slow CDN logo never shifts the header. */
.app-header__logo {
  height: 1.75rem;
  width: auto;
  max-width: min(60vw, 14rem);
  object-fit: contain;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.app-header__logo.is-loaded { opacity: 1; }

.app-header__title {
  font-family: var(--font-display);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-text-secondary);
}

.app-main {
  flex: 1 1 auto;
  display: flex;
  width: 100%;
  max-width: var(--measure-page);
  margin-inline: auto;
  padding: var(--sp-4) var(--sp-gutter) var(--sp-6);
}
.app-main:focus-visible { outline: none; box-shadow: var(--focus-ring-quiet); }

.app-screen { width: 100%; display: flex; }

.app-footer {
  width: 100%;
  max-width: var(--measure-page);
  margin-inline: auto;
  padding: var(--sp-3) var(--sp-gutter) var(--sp-4);
}

.app-footer__note {
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
  text-align: center;
  max-width: none;
}

/* -----------------------------------------------------------------------------
   3. SCREENS
   -------------------------------------------------------------------------- */
.screen {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
  width: 100%;
}

.screen--menu,
.screen--error {
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--sp-8);
}

.screen__title {
  font-size: var(--fs-2xl);
  text-align: center;
}

.screen__back { align-self: flex-start; }

.screen__body { width: 100%; }

/* -----------------------------------------------------------------------------
   4. HERO + MAIN MENU (S0)
   -------------------------------------------------------------------------- */
.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  position: relative;
}

.hero__brand {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Height is reserved up front so a slow CDN logo cannot shift the menu. */
  min-height: clamp(4.5rem, 3rem + 8vw, 7rem);
}

.hero__logo {
  height: clamp(4.5rem, 3rem + 8vw, 7rem);
  width: auto;
  max-width: min(100%, 26rem);
  object-fit: contain;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.hero__logo.is-loaded { opacity: 1; }

.hero__wordmark {
  font-size: var(--fs-3xl);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-tight);
  line-height: var(--lh-tight);
  text-transform: uppercase;
}

.hero__tagline {
  max-width: 34ch;
  margin-inline: auto;
  font-size: var(--fs-md);
  color: var(--c-text-secondary);
  text-wrap: balance;
}

.hero__spark {
  color: var(--c-amber);
  opacity: 0.85;
}

.menu__actions {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  width: min(100%, 22.5rem);
}

/* Tertiary action sits apart from the two primary decisions. */
.menu__tertiary {
  margin-block-start: var(--sp-4);
  padding-block-start: var(--sp-4);
  border-block-start: 1px solid var(--c-border-subtle);
}

.menu__whatsapp { color: var(--c-lime); }

.menu__notice {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  max-width: 40ch;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-lg);
  background-color: var(--c-warning-tint);
  color: var(--c-amber);
  font-size: var(--fs-sm);
}

@media (min-width: 768px) {
  /* Desktop is a first-class layout, not a stretched phone: the actions sit on a
     composed surface panel so the centre of a wide screen still reads as designed. */
  .menu__actions {
    width: min(100%, 24rem);
    padding: var(--sp-6);
    border-radius: var(--r-2xl);
    background-color: var(--c-surface-1);
    border: 1px solid var(--c-border);
    box-shadow: var(--sh-2), var(--sh-inset);
  }
}

/* Small screens: tighten the vertical rhythm so all 8 chests fit without scrolling. */
@media (max-width: 479px) {
  .screen { gap: var(--sp-4); }
  .app-main { padding-block: var(--sp-2) var(--sp-4); }
  .app-header { padding-block: var(--sp-3) var(--sp-1); }
}

/* -----------------------------------------------------------------------------
   5. BUTTONS (DESIGN-SYSTEM section 9.1)
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--control-h);
  min-width: var(--target-min);
  padding-inline: var(--sp-6);
  border: none;
  border-radius: var(--r-lg);
  font-family: var(--font-ui);
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  line-height: 1.1;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  box-shadow: var(--sh-1);
  transition:
    transform var(--dur-instant) var(--ease-out),
    box-shadow var(--dur-instant) var(--ease-out),
    background-color var(--dur-instant) var(--ease-out),
    color var(--dur-instant) var(--ease-out),
    opacity var(--dur-instant) var(--ease-out),
    filter var(--dur-instant) var(--ease-out);
}

.btn--primary { background-image: var(--grad-primary); color: var(--c-ink); }
.btn--secondary {
  background-color: var(--c-surface-2);
  color: var(--c-text);
  border: 1.5px solid var(--c-border-interactive);
}
.btn--ghost {
  background-color: transparent;
  color: var(--c-text-secondary);
  box-shadow: none;
}

.btn--sm {
  min-height: var(--control-h-sm);
  padding-inline: var(--sp-4);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
}
.btn--lg {
  min-height: var(--control-h-lg);
  padding-inline: var(--sp-8);
  font-size: var(--fs-md);
}
.btn--block { width: 100%; }

.btn__icon { flex: none; }

/* Hover is a warm lantern glow, and is gated so touch never gets a stuck state. */
@media (hover: hover) {
  .btn:hover { transform: translateY(-2px); }
  .btn--primary:hover {
    background-image: var(--grad-primary-hover);
    box-shadow: var(--glow-amber);
  }
  .btn--secondary:hover { border-color: var(--c-amber); box-shadow: var(--glow-amber); }
  .btn--ghost:hover { background-color: var(--c-surface-1); color: var(--c-text); }
  .menu__whatsapp:hover { color: var(--c-lime); background-color: var(--c-success-tint); }
}

.btn:active { transform: translateY(0) scale(0.98); box-shadow: var(--sh-inset); }

.btn:disabled,
.btn[aria-disabled='true'] {
  opacity: 0.45;
  filter: saturate(0.4);
  cursor: not-allowed;
  pointer-events: none;
  transform: none;
}

/* Loading: the label stays in place (no layout shift), the spinner joins it. */
.btn__spinner {
  display: none;
  flex: none;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--r-pill);
}
.btn.is-loading .btn__spinner {
  display: block;
  animation: mb-spin 700ms linear infinite;
}

/* -----------------------------------------------------------------------------
   6. FIELDS (DESIGN-SYSTEM section 9.2)
   -------------------------------------------------------------------------- */
.field__label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--c-text-secondary);
}

.field__hint {
  margin-block: var(--sp-1) var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
  max-width: none;
}

.field__control { position: relative; }

.field__input {
  width: 100%;
  min-height: var(--control-h);
  padding: var(--sp-2) var(--sp-4);
  background-color: var(--c-surface-1);
  border: 1.5px solid var(--c-border-interactive);
  border-radius: var(--r-lg);
  color: var(--c-text);
  /* Never below 16px on mobile — prevents iOS zoom-on-focus. */
  font-size: 1rem;
  transition:
    border-color var(--dur-base) var(--ease-out),
    background-color var(--dur-base) var(--ease-out);
}

.field__input--code {
  font-family: var(--font-mono);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-align: center;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums slashed-zero;
}

@media (hover: hover) {
  .field__input:hover { border-color: var(--c-border-strong); }
}
.field__input:focus-visible { border-color: var(--c-cyan); }

/* Invalid outranks the focus border so the error state stays visible while the
   player is retyping. The dual focus ring still paints on top (SC 2.4.11). */
.field__input.is-invalid,
.field__input.is-invalid:focus-visible {
  border-color: var(--c-danger);
  background-color: var(--c-danger-tint);
}

.field__input:disabled {
  color: var(--c-text-disabled);
  cursor: not-allowed;
}

.field__error {
  margin-block-start: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--c-danger);
  max-width: none;
}
.field__error:empty { margin-block-start: var(--sp-0); }

.field__extra {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-block-start: var(--sp-3);
}
.field__extra:empty { margin-block-start: var(--sp-0); }

/* -----------------------------------------------------------------------------
   7. MODAL / BOTTOM SHEET (DESIGN-SYSTEM section 9.4)
   -------------------------------------------------------------------------- */
body.is-modal-open { overflow: hidden; }

.modal-scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: var(--sp-8) 0 0;
  background-color: var(--c-scrim);
  backdrop-filter: blur(8px);
  animation: mb-fade-in var(--dur-base) var(--ease-out) both;
}

@supports not ((backdrop-filter: blur(8px)) or (-webkit-backdrop-filter: blur(8px))) {
  .modal-scrim { background-color: var(--c-scrim-solid); }
}

@keyframes mb-fade-in { from { opacity: 0; } to { opacity: 1; } }

.modal {
  position: relative;
  z-index: var(--z-modal);
  width: 100%;
  max-height: 92dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--sp-5) var(--sp-5) var(--sp-8);
  background-color: var(--c-surface-2);
  border-start-start-radius: var(--r-2xl);
  border-start-end-radius: var(--r-2xl);
  box-shadow: var(--sh-3);
  animation: mb-sheet-in var(--dur-slow) var(--ease-out) both;
}
.modal:focus-visible { outline: none; box-shadow: var(--focus-ring-quiet), var(--sh-3); }

@keyframes mb-sheet-in {
  from { translate: 0 100%; opacity: 0; }
  to { translate: 0 0; opacity: 1; }
}
@keyframes mb-modal-in {
  from { scale: 0.96; opacity: 0; }
  to { scale: 1; opacity: 1; }
}

@media (min-width: 768px) {
  .modal-scrim { align-items: center; padding: var(--sp-8); }
  .modal {
    max-width: min(560px, calc(100vw - var(--sp-8)));
    max-height: min(85dvh, 60rem);
    border-radius: var(--r-2xl);
    padding: var(--sp-8);
    animation-name: mb-modal-in;
    animation-timing-function: var(--ease-spring);
  }
}

.modal__closebar { display: flex; justify-content: flex-end; }

.modal__close {
  display: grid;
  place-items: center;
  width: var(--target-min);
  height: var(--target-min);
  border-radius: var(--r-pill);
  color: var(--c-text-secondary);
  cursor: pointer;
  transition: background-color var(--dur-instant) var(--ease-out), color var(--dur-instant) var(--ease-out);
}
@media (hover: hover) {
  .modal__close:hover { background-color: var(--c-surface-3); color: var(--c-text); }
}

.modal__body { display: flex; flex-direction: column; gap: var(--sp-4); }

.modal__eyebrow { color: var(--c-pink); }

.modal__title { font-size: var(--fs-xl); }

.modal__actions {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin-block-start: var(--sp-4);
}

.modal__actions--stack { margin-block-start: var(--sp-4); gap: var(--sp-2); }

.code-form { display: flex; flex-direction: column; }

/* -----------------------------------------------------------------------------
   8. TOASTS (DESIGN-SYSTEM section 9.7)
   -------------------------------------------------------------------------- */
.toast-region {
  position: fixed;
  z-index: var(--z-toast);
  inset-block-end: var(--sp-4);
  inset-inline: var(--sp-4);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  pointer-events: none;
}

@media (min-width: 768px) {
  .toast-region {
    inset-inline: auto var(--sp-6);
    align-items: flex-end;
  }
}

.toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  max-width: min(26rem, calc(100vw - var(--sp-8)));
  min-height: 3.5rem;
  padding: var(--sp-3) var(--sp-4);
  background-color: var(--c-surface-3);
  border-radius: var(--r-lg);
  border-inline-start: 4px solid var(--c-info);
  box-shadow: var(--sh-3);
  animation: mb-rise var(--dur-base) var(--ease-out) both;
  transition: opacity var(--dur-base) var(--ease-out);
}

.toast--error { border-inline-start-color: var(--c-danger); }
.toast--error .toast__icon { color: var(--c-danger); }
.toast--info .toast__icon { color: var(--c-cyan); }
.toast--success .toast__icon { color: var(--c-success); }

.toast__icon { flex: none; display: grid; place-items: center; }

.toast__msg {
  flex: 1 1 auto;
  margin: 0;
  max-width: none;
  font-size: var(--fs-sm);
  color: var(--c-text);
}

.toast__close {
  flex: none;
  display: grid;
  place-items: center;
  width: var(--target-min);
  height: var(--target-min);
  border-radius: var(--r-pill);
  color: var(--c-text-secondary);
  font-size: var(--fs-lg);
  line-height: 1;
  cursor: pointer;
}
@media (hover: hover) {
  .toast__close:hover { color: var(--c-text); background-color: var(--c-surface-2); }
}

.toast.is-leaving { opacity: 0; }

/* -----------------------------------------------------------------------------
   9. BADGES, CHIPS
   Rope-bound tags with a wax-seal glyph (ADDENDUM 3 section 11.2) rather than neon
   pills. Every tier badge still carries colour + label + glyph (SC 1.4.1), and the
   tier hues sit on --c-surface-3 where each measures >= 5.1:1.
   -------------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 1.75rem;
  padding-inline: var(--sp-3);
  border-radius: var(--r-sm);
  background-color: var(--c-surface-3);
  /* Dashed edge reads as rope binding on a luggage tag. */
  border: 2px dashed currentColor;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

.badge--jackpot { color: var(--c-tier-jackpot); }
.badge--grand { color: var(--c-tier-grand); }
.badge--common { color: var(--c-tier-common); }
.badge--zonk { color: var(--c-tier-zonk); }

/* Wax seal: the tier glyph stamped into a disc of the tier colour. Two elements,
   because `currentColor` always resolves to an element's own colour — the seal takes
   the inherited tier fill, the glyph inside takes ink. Decorative (aria-hidden), so it
   carries no contrast requirement of its own. */
.badge__seal {
  display: grid;
  place-items: center;
  width: 1.3em;
  height: 1.3em;
  border-radius: var(--r-pill);
  background-color: currentColor;
}

.badge__glyph {
  color: var(--c-ink);
  font-size: 0.8em;
  line-height: 1;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 1.625rem;
  padding-inline: var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
}

.chip--ok { color: var(--c-success); background-color: var(--c-success-tint); }
.chip--warn { color: var(--c-amber); background-color: var(--c-warning-tint); }
.chip--pending { color: var(--c-text-muted); background-color: var(--c-surface-3); }

/* -----------------------------------------------------------------------------
   10. EMPTY + ERROR STATES (DESIGN-SYSTEM section 9.8)
   -------------------------------------------------------------------------- */
.empty,
.errorstate {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  max-width: 44ch;
  margin-inline: auto;
  padding: var(--sp-12) var(--sp-6);
  text-align: center;
}

.empty__glyph {
  color: var(--c-violet-400);
  /* Subtle violet halo, derived from the icon's own token colour — no literal. */
  filter: drop-shadow(0 0 16px currentColor);
  opacity: 0.8;
}

.empty__title { font-size: var(--fs-xl); }
.empty__text { color: var(--c-text-secondary); }

.errorstate__glyph { color: var(--c-amber); }
.errorstate__title { font-size: var(--fs-xl); }
.errorstate__message {
  color: var(--c-text-secondary);
  font-size: var(--fs-md);
}

/* -----------------------------------------------------------------------------
   11. CONFETTI CANVAS
   Sits above the reveal dialog so the burst is actually visible. It is inert
   (pointer-events:none, aria-hidden) and tokens.css hides it entirely under
   prefers-reduced-motion, where confetti.js also refuses to run.
   -------------------------------------------------------------------------- */
.mb-confetti {
  position: fixed;
  inset: 0;
  z-index: var(--z-toast);
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.mb-confetti.is-active { opacity: 1; }
