/* =============================================================================
   MysteryBox — Board, treasure chests, reveal card, prize list.
   Loaded after tokens.css and app.css. Declares no tokens, no hex literals,
   no z-index literals, no `transition: all`.

   Themed per PROJECT-BRIEF ADDENDUM 3 (pirate / treasure hunt). Every colour is read
   from a token, so Tech Lead B's palette re-point lands here without a code change.

   Board sizing maths (DESIGN-SYSTEM section 10.1 + PROJECT-BRIEF section 10.5).
   tokens.css supplies --board-cols (2 below 768px, 4 at and above) and --board-gap.
   The cap below keeps a chest at or under 200px, so the board never stretches
   edge-to-edge on a wide monitor and the chests never become enormous:

     360px  gutter 16  -> 328 avail, 2 cols, gap 12 -> chest 158px
     414px  gutter 17  -> 380 avail, 2 cols, gap 12 -> chest 184px
     480px  gutter 18  -> 444 avail, capped 412     -> chest 200px
     768px  gutter 23  -> 721 avail, 4 cols, gap 20 -> chest 165px
    1024px  gutter 28  -> 968 avail, capped 872     -> chest 200px
    1440px  gutter 32  -> board capped at 880       -> chest 199px
   ========================================================================== */

/* -----------------------------------------------------------------------------
   1. BOARD
   -------------------------------------------------------------------------- */
.screen--board {
  align-items: center;
  justify-content: center;
  gap: var(--sp-6);
}

.board__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  text-align: center;
}

.board__title { font-size: var(--fs-xl); }

.board__code {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  max-width: none;
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-pill);
  background-color: var(--c-surface-1);
  border: 1px solid var(--c-border);
}

.board__code-label {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-text-muted);
}

.board__code-value {
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--c-text);
}

.board {
  /* Component-local layout cap — not a design token. */
  --mb-tile-cap: 200px;

  display: grid;
  grid-template-columns: repeat(var(--board-cols), minmax(0, 1fr));
  gap: var(--board-gap);
  width: 100%;
  max-width: min(
    var(--board-max),
    calc(var(--board-cols) * var(--mb-tile-cap) + (var(--board-cols) - 1) * var(--board-gap))
  );
  margin-inline: auto;
}

.board__status {
  min-height: 1.5rem;
  max-width: none;
  text-align: center;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--c-cyan);
}

.board__recovery {
  display: flex;
  justify-content: center;
  gap: var(--sp-3);
}

/* -----------------------------------------------------------------------------
   2. TREASURE CHEST TILE (PROJECT-BRIEF ADDENDUM 3 section 11.2)
   A real <button type="button">, keyboard operable, focus ring never clipped
   (overflow lives on the chest parts, never on the button itself).

   Anatomy, back to front:
     .tile__chest     bob wrapper — keeps the button's own transform free for hover
     .tile__interior  the dark inside, revealed as the lid swings back
     .tile__lid       domed lid with a brass band, rotates about its top edge
     .tile__body      chest front: brass strap, number, lock plate over the seam
   -------------------------------------------------------------------------- */
.tile {
  position: relative;
  aspect-ratio: 1;
  /* The board is a flex child, so it shrinks to keep all 8 chests on screen without
     scrolling. This floor stops that shrink from ever producing a small target —
     104px is well above the 44px SC 2.5.8 minimum, and 2 x 104 + gap still fits a
     320px viewport (400% zoom). */
  min-width: 6.5rem;
  min-height: 6.5rem;
  padding: 0;
  border: none;
  background-color: transparent;
  cursor: pointer;
  perspective: 900px;
  transition:
    transform var(--dur-fast) var(--ease-out),
    opacity var(--dur-base) var(--ease-out),
    filter var(--dur-base) var(--ease-out);
  /* Staggered entry. --tile-i is set per chest by board.js. Uses `scale`/`opacity`
     (independent properties) so hover's `transform` is never fought over. */
  animation: mb-tile-in var(--dur-base) var(--ease-spring) both;
  animation-delay: calc(var(--tile-i, 0) * var(--stagger));
}

@keyframes mb-tile-in {
  from { opacity: 0; scale: 0.82; }
  to { opacity: 1; scale: 1; }
}

/* Gentle bob, like a chest riding a swell. Staggered so no two chests move in
   lockstep. Both keyframe ends are identical, so when tokens.css collapses
   animations to 1ms / 1 iteration the chest simply rests at 0. */
.tile__chest {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  animation: mb-chest-bob 4.6s var(--ease-in-out) infinite;
  animation-delay: calc(var(--tile-i, 0) * 260ms);
}

@keyframes mb-chest-bob {
  0%, 100% { translate: 0 0; rotate: 0deg; }
  50% { translate: 0 -6px; rotate: -1.1deg; }
}

.tile__interior {
  position: absolute;
  inset-inline: 4%;
  inset-block-start: 8%;
  height: 44%;
  overflow: hidden;
  border-start-start-radius: 46%;
  border-start-end-radius: 46%;
  background-color: var(--c-base-deep);
  border: 2px solid var(--c-border-interactive);
  border-block-end: none;
}

/* Lantern light spilling out of the open chest. */
.tile__glow {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(ellipse at 50% 95%, var(--c-amber) 0%, transparent 72%);
  opacity: 0;
  scale: 0.6;
  transition:
    opacity var(--dur-reveal) var(--ease-out),
    scale var(--dur-reveal) var(--ease-spring);
}

.tile__lid {
  position: absolute;
  inset-inline: 2%;
  inset-block-start: 6%;
  height: 42%;
  overflow: hidden;
  border-start-start-radius: 48%;
  border-start-end-radius: 48%;
  border-end-start-radius: var(--r-xs);
  border-end-end-radius: var(--r-xs);
  background-image: var(--grad-tile);
  border: 2px solid var(--c-border-interactive);
  box-shadow: var(--sh-2);
  transform-origin: top center;
  backface-visibility: hidden;
  transition:
    transform var(--dur-reveal) var(--ease-spring),
    border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out),
    background-image var(--dur-fast) var(--ease-out);
}

/* Brass band across the lid. */
.tile__band {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 50%;
  width: 14%;
  translate: -50% 0;
  background-color: var(--c-amber);
  opacity: 0.72;
}

/* Decorative sheen sweeping the lid — removed outright under reduced motion via the
   data-decorative-motion hook in tokens.css. */
.tile__shine {
  position: absolute;
  inset-block: -30%;
  inset-inline-start: -60%;
  width: 40%;
  rotate: 14deg;
  background-image: linear-gradient(
    100deg,
    transparent 0%,
    var(--c-border-strong) 50%,
    transparent 100%
  );
  animation: mb-tile-shine 5s var(--ease-in-out) infinite;
  animation-delay: calc(var(--tile-i, 0) * 380ms);
}

@keyframes mb-tile-shine {
  0% { translate: 0 0; opacity: 0; }
  15% { opacity: 0.85; }
  55%, 100% { translate: 380% 0; opacity: 0; }
}

.tile__body {
  position: absolute;
  inset-inline: 2%;
  inset-block: 45% 6%;
  display: grid;
  place-items: center;
  border-radius: var(--r-xs) var(--r-xs) var(--r-md) var(--r-md);
  background-image: var(--grad-tile);
  border: 2px solid var(--c-border-interactive);
  box-shadow: var(--sh-2);
  transition:
    border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out),
    background-image var(--dur-fast) var(--ease-out);
}

/* Brass strap down the chest front, aligned with the lid band. */
.tile__strap {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 50%;
  width: 14%;
  translate: -50% 0;
  background-color: var(--c-amber);
  opacity: 0.72;
}

/* Branded number plate. It sits over the brass strap, so it carries its own dark
   ground rather than relying on bone-on-gold, which would fail AA. --c-text on
   --c-base-deep is ~15:1 in either palette. */
.tile__num {
  position: relative;
  margin-block-start: 16%;
  padding: 0.06em 0.42em 0.1em;
  border-radius: var(--r-xs);
  background-color: var(--c-base-deep);
  box-shadow: var(--sh-1);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-black);
  line-height: 1.15;
  color: var(--c-text);
}

/* Brass lock plate straddling the lid/body seam. */
.tile__lock {
  position: absolute;
  inset-block-start: -16%;
  inset-inline-start: 50%;
  translate: -50% 0;
  display: grid;
  place-items: center;
  width: 26%;
  aspect-ratio: 1;
  border-radius: var(--r-xs);
  background-color: var(--c-amber);
  box-shadow: var(--sh-1);
}

.tile__keyhole {
  width: 26%;
  height: 46%;
  border-radius: var(--r-pill) var(--r-pill) var(--r-xs) var(--r-xs);
  background-color: var(--c-ink);
  opacity: 0.75;
}

/* --- Interaction states ----------------------------------------------------- */
/* Hover is a warm lantern glow and gold rim-light. Gated so touch never sticks. */
@media (hover: hover) {
  .tile:not(:disabled):not([aria-disabled='true']):hover { transform: translateY(-5px); }
  .tile:not(:disabled):not([aria-disabled='true']):hover .tile__lid,
  .tile:not(:disabled):not([aria-disabled='true']):hover .tile__body {
    border-color: var(--c-amber);
    background-image: var(--grad-tile-hover);
    box-shadow: var(--glow-amber);
  }
}

.tile:not(:disabled):not([aria-disabled='true']):active { transform: scale(0.955); }

/* Focus ring must sit above neighbouring chests so it is never visually clipped. */
.tile:focus-visible { z-index: var(--z-raised); }

/* --- Locked states (applied synchronously the instant a chest is clicked) ---- */

.tile--asleep {
  opacity: 0.35;
  filter: grayscale(0.6);
  cursor: not-allowed;
}
.tile--asleep .tile__chest { animation: none; }
.tile--asleep .tile__shine { display: none; }
.tile--asleep .tile__lid,
.tile--asleep .tile__body { box-shadow: none; }

/* The chosen chest stays at full opacity so the player sees which one they picked,
   rattling as though something inside wants out. */
.tile--chosen { z-index: var(--z-raised); }
.tile--chosen .tile__lid,
.tile--chosen .tile__body {
  border-color: var(--c-amber);
  box-shadow: var(--glow-amber), var(--sh-3);
}
.tile--chosen .tile__chest {
  animation: mb-chest-rattle 560ms var(--ease-in-out) infinite;
}

@keyframes mb-chest-rattle {
  0%, 100% { rotate: 0deg; translate: 0 0; }
  25% { rotate: -2.2deg; translate: -1px 0; }
  75% { rotate: 2.2deg; translate: 1px 0; }
}

/* --- Opened ----------------------------------------------------------------- */
/* The lid swings back on its hinge and lantern light floods out. Under reduced
   motion every duration is 1ms, so this becomes an instant crossfade — the state
   change is still fully conveyed (DESIGN-SYSTEM section 7.2 rule 5). */
.tile--opening .tile__chest { animation: none; }
.tile--opening .tile__lid {
  transform: rotateX(-118deg);
  border-color: var(--c-amber);
}
.tile--opening .tile__body {
  border-color: var(--c-amber);
  box-shadow: var(--glow-amber), var(--sh-3);
}
.tile--opening .tile__glow { opacity: 1; scale: 1.3; }

/* Non-chosen chests NEVER show prize art or any hint of their contents — there is
   deliberately no rule here that could ever paint one. */

/* -----------------------------------------------------------------------------
   3. PRIZE REVEAL CARD (DESIGN-SYSTEM section 9.11)
   Identical structure and prominence for win and zonk.
   -------------------------------------------------------------------------- */
.prize {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Tight enough that the card plus all three follow-up actions fit without
     scrolling on a 700px-tall laptop viewport (acceptance criterion 17). */
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-4);
  text-align: center;
  background-color: var(--c-surface-2);
  border: 2px solid var(--c-tier-common);
  border-radius: var(--r-2xl);
  box-shadow: var(--sh-2), var(--sh-inset);
}

.prize--jackpot { border-color: var(--c-tier-jackpot); }
.prize--grand { border-color: var(--c-tier-grand); }
.prize--common { border-color: var(--c-tier-common); }
.prize--zonk { border-color: var(--c-tier-zonk); }

/* The single permitted use of --glow-strong. */
.prize--win { box-shadow: var(--glow-strong), var(--sh-2); }
/* Zonk gets a calm flourish in the same family as a common win — never grey or sad. */
.prize.is-sparkle { box-shadow: var(--glow-cyan), var(--sh-2); }

/* Reduced-motion celebratory fallback: a single scale/opacity pop, no coin burst. */
.prize.is-pop { animation: mb-pop var(--dur-slow) var(--ease-spring) both; }

@keyframes mb-pop {
  0% { scale: 0.9; opacity: 0.55; }
  60% { scale: 1.03; }
  100% { scale: 1; opacity: 1; }
}

.reveal__headline {
  max-width: none;
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-wide);
  line-height: var(--lh-snug);
  text-transform: uppercase;
}
.reveal__headline--win { color: var(--c-amber); }
.reveal__headline--zonk { color: var(--c-violet-text); text-transform: none; }

.reveal__subtext {
  color: var(--c-text-secondary);
  font-size: var(--fs-sm);
}

/* Round plate — the treasure coins are circular with transparency, so a circular
   well flatters them. aspect-ratio reserves the space up front, so a slow or dead
   CDN image never shifts the card. */
.prize__media {
  position: relative;
  display: grid;
  place-items: center;
  width: min(10.5rem, 44vw);
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--r-pill);
  background-color: var(--c-surface-1);
  border: 2px solid var(--c-border);
  box-shadow: var(--sh-inset);
}

/* <picture> is a pass-through wrapper: the <img> must position against .prize__media. */
.prize__picture { display: contents; }

.prize__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: var(--sp-3);
  object-fit: contain;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.prize__img.is-loaded { opacity: 1; }

/* Tier-coloured placeholder — the fallback for a missing, unsafe or dead image URL. */
.prize__placeholder {
  display: grid;
  place-items: center;
  font-size: var(--fs-3xl);
  line-height: 1;
  color: var(--c-tier-common);
  opacity: 0.75;
  transition: opacity var(--dur-base) var(--ease-out);
}
.prize__media--jackpot .prize__placeholder,
.prizecard__media--jackpot .prize__placeholder { color: var(--c-tier-jackpot); }
.prize__media--grand .prize__placeholder,
.prizecard__media--grand .prize__placeholder { color: var(--c-tier-grand); }
.prize__media--common .prize__placeholder,
.prizecard__media--common .prize__placeholder { color: var(--c-tier-common); }
.prize__media--zonk .prize__placeholder,
.prizecard__media--zonk .prize__placeholder { color: var(--c-tier-zonk); }

.prize__media.is-loaded .prize__placeholder,
.prizecard__media.is-loaded .prize__placeholder { opacity: 0; }

.prize__name {
  font-size: var(--fs-xl);
  line-height: var(--lh-tight);
}

.prize__meta {
  display: grid;
  gap: var(--sp-1);
  width: 100%;
  padding-block-start: var(--sp-3);
  border-block-start: 1px solid var(--c-border-subtle);
}

.prize__meta-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  font-size: var(--fs-sm);
}

.prize__meta-row dt {
  color: var(--c-text-muted);
  font-weight: var(--fw-semibold);
}

.prize__meta-row dd {
  color: var(--c-text);
  font-weight: var(--fw-bold);
  text-align: end;
}

/* -----------------------------------------------------------------------------
   4. MY PRIZES LIST (S5)
   -------------------------------------------------------------------------- */
.screen--prizes { align-items: stretch; }

.prizelist__status {
  max-width: none;
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
  text-align: center;
  margin-block-end: var(--sp-4);
}

.prizelist {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: 1fr;
  list-style: none;
  padding: 0;
  margin: 0;
}

@media (min-width: 768px) {
  .prizelist { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1200px) {
  .prizelist { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.prizecard {
  display: flex;
  gap: var(--sp-4);
  padding: var(--sp-4);
  background-color: var(--c-surface-1);
  border: 1px solid var(--c-border);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-2), var(--sh-inset);
  transition: border-color var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}

.prizecard.is-checking { opacity: 0.82; }
.prizecard.is-verified { border-color: var(--c-border-strong); opacity: 1; }
.prizecard.is-unverified { border-color: var(--c-amber); opacity: 1; }

.prizecard__media {
  position: relative;
  flex: none;
  /* Without this the flex row stretches the round coin well into a tall pill. */
  align-self: flex-start;
  display: grid;
  place-items: center;
  width: 5.5rem;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--r-pill);
  background-color: var(--c-surface-2);
  border: 1px solid var(--c-border);
}

.prizecard__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: var(--sp-1);
  object-fit: contain;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.prizecard__img.is-loaded { opacity: 1; }

.prizecard__media .prize__placeholder { font-size: var(--fs-xl); }

.prizecard__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-2);
  min-width: 0;
  flex: 1 1 auto;
}

.prizecard__name {
  font-size: var(--fs-md);
  line-height: var(--lh-snug);
}

.prizecard__meta {
  display: grid;
  gap: var(--sp-1);
  width: 100%;
  font-size: var(--fs-xs);
}

.prizecard__meta .prize__meta-row { font-size: var(--fs-xs); }

.prizecard__state {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
}

.prizecard__note {
  width: 100%;
  max-width: none;
  font-size: var(--fs-xs);
  color: var(--c-text-secondary);
}
