/* ==========================================================================
   Math Memory — Quack Quiz
   Built phone-first. Everything above the options is allowed to shrink; the
   options themselves never go under the 48px tap target, because on a small
   screen the answers are the only thing that has to stay comfortable.
   ========================================================================== */

.screen--quiz {
  gap: var(--s3);
  overflow: hidden;
  justify-content: flex-start;
}

/* --------------------------------------------------------------------------
   Top bar: progress, score, streak
   -------------------------------------------------------------------------- */

.quiz__bar { display: flex; align-items: center; gap: 10px; }

.quiz__pips {
  display: flex;
  gap: 5px;
  flex: 1 1 auto;
  justify-content: center;
  min-width: 0;
}
.quiz__pips i {
  width: 9px; height: 9px;
  flex: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, .22);
  transition: transform .3s cubic-bezier(.2, 1.7, .4, 1), background .3s ease;
}
.quiz__pips i.is-done { background: var(--green-soft); }
/* In a test the pips keep the score. A question that went wrong reads as
   answered and nothing more — there is no red anywhere in this game. */
.quiz__pips i.is-hit  { background: var(--green-soft); }
.quiz__pips i.is-past { background: rgba(255, 255, 255, .32); }
.quiz__pips i.is-now  { background: var(--gold); transform: scale(1.7); box-shadow: 0 0 12px rgba(255, 215, 106, .8); }

/* --- the two numbers in the bar ------------------------------------------
   Stars and score are different quantities, so they are drawn as different
   things: a gold star on amber against a violet bolt on violet. Sharing the ★
   was what made them read as one number in two places. Both chips stay on one
   line — the bar never wraps. */
.quiz__scorechip,
.quiz__starchip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 10px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex: none;
}
.quiz__chipicon { font-size: 13px; line-height: 1; }
.quiz__chipicon--star  { color: var(--gold); }
.quiz__chipicon--score { color: #c9a6ff; }
/* The chips also differ in tint, because two grey chips a gap apart are told
   apart only by their icon, and a child glancing up mid-question is not
   reading icons. */
.quiz__starchip  { background: rgba(255, 215, 106, .16); }
.quiz__scorechip { background: rgba(155, 109, 255, .22); }
.quiz__starchip b, .quiz__scorechip { color: #fff; }
/* The words are written out wherever the bar can hold them. On a phone it
   cannot — five things already compete for 320 usable pixels, and the pips
   are the child's place in the run, so they win. The labelling that matters
   is on the results screen, where the number is large and has room to say
   what it is; up here the gold ★ and the violet ⚡ carry it, with the screen
   reader given the words either way. */
.quiz__chipcap { display: none; }
@media (min-width: 520px) {
  .quiz__chipcap {
    display: inline;
    font: 800 9px var(--font-ui);
    letter-spacing: .08em;
    color: rgba(255, 255, 255, .58);
  }
}

/* --- the table test ------------------------------------------------------
   The same quiz, wearing the fact that it guards the path. The target is on
   screen the whole way through: a child working towards a number should be
   able to see the number. */
.quiz__testchip {
  font: 800 12px var(--font-ui);
  letter-spacing: .06em;
  background: linear-gradient(140deg, var(--gold), var(--amber));
  color: var(--ink-2);
  white-space: nowrap;
}
.quiz__goal {
  display: inline-flex; align-items: baseline; gap: 1px;
  padding: 8px 11px;
  border-radius: var(--r-chip);
  background: rgba(0, 0, 0, .25);
  font: 800 13px var(--font-ui);
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, .62);
}
.quiz__goal b { color: var(--green-soft); font-size: 15px; }

.quiz__streak {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 8px 11px;
  border-radius: var(--r-chip);
  background: rgba(0, 0, 0, .25);
  font: 800 13px var(--font-ui);
  color: rgba(255, 255, 255, .5);
  transition: color .25s ease, background .25s ease, box-shadow .25s ease;
}
.quiz__streak i { font-style: normal; filter: grayscale(1) opacity(.6); transition: filter .25s ease; }
.quiz__streak.is-on { color: #fff; }
.quiz__streak.is-on i { filter: none; }
.quiz__streak.is-hot {
  background: linear-gradient(140deg, #ff8a2b, #ff3d8b);
  color: #fff;
  box-shadow: 0 0 22px rgba(255, 138, 43, .65);
}
.quiz__streak.is-pump { animation: qzpump .45s cubic-bezier(.2, 1.8, .4, 1); }
@keyframes qzpump { 0% { transform: scale(1); } 45% { transform: scale(1.28); } 100% { transform: scale(1); } }

/* --------------------------------------------------------------------------
   Stage
   -------------------------------------------------------------------------- */

.quiz__stage {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s3);
  min-height: 0;
}

/* headroom for the speech bubble, which sits above the duck */
.quiz__duck { margin-top: 40px; }

.quiz__top {
  margin-block: auto;      /* absorbs the spare height on a tall screen */
  min-height: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s3);
}

/* answers, help and the explanation live together at the bottom of the
   screen so the layout does not jump between question shapes */
.quiz__bottom {
  margin-top: auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding-top: var(--s3);
}

/* --------------------------------------------------------------------------
   The question card
   -------------------------------------------------------------------------- */

.quiz__card {
  position: relative;
  width: 100%;
  background: linear-gradient(175deg, var(--card-front), var(--card-front-2));
  border-radius: var(--r-sheet);
  border: 3px solid #fff;
  box-shadow: 0 8px 0 rgba(0, 0, 0, .22), 0 18px 40px rgba(0, 0, 0, .3);
  padding: 18px 16px 16px;
  text-align: center;
  overflow: hidden;
  transition: box-shadow .3s ease, border-color .3s ease;
}
.quiz__card.is-in { animation: qzin .5s cubic-bezier(.2, 1.5, .4, 1) both; }
@keyframes qzin {
  0%   { transform: translateY(26px) scale(.9) rotate(-2deg); opacity: 0; }
  100% { transform: none; opacity: 1; }
}
.quiz__card.is-right {
  border-color: var(--green-soft);
  box-shadow: 0 8px 0 rgba(0,0,0,.22), 0 0 0 5px rgba(92, 240, 174, .45), 0 18px 46px rgba(18, 176, 108, .45);
}
.quiz__card.is-wrong {
  border-color: #ffb3cd;
  box-shadow: 0 8px 0 rgba(0,0,0,.22), 0 0 0 5px rgba(255, 133, 185, .4);
}

.quiz__timer {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 7px;
  background: rgba(0, 0, 0, .1);
}
.quiz__timer i {
  display: block;
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, var(--teal-2), var(--green));
  border-radius: 0 4px 4px 0;
}
.quiz__timer i.is-low {
  background: linear-gradient(90deg, #ff8a2b, #ff3d8b);
  animation: qzlow .5s ease-in-out infinite;
}
@keyframes qzlow { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }

.quiz__ask {
  font: 800 12px var(--font-ui);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-bottom: 6px;
}
.quiz__main { display: flex; justify-content: center; align-items: center; min-height: 46px; }

.eq--quiz { font-size: clamp(34px, 12vw, 52px); --eq-gap: 6px; }
.eq--quiz .is-blank {
  color: var(--ink);
  background: rgba(139, 61, 255, .12);
  border-radius: 10px;
  padding: 0 .18em;
  animation: qzblank 1.6s ease-in-out infinite;
}
@keyframes qzblank { 0%, 100% { background: rgba(139, 61, 255, .10); } 50% { background: rgba(139, 61, 255, .26); } }

.quiz__target {
  font: 600 clamp(46px, 17vw, 74px) var(--font-display);
  color: var(--eq-answer);
  line-height: 1;
}
.quiz__grouptext {
  font: 800 14px var(--font-ui);
  color: var(--muted);
}
.quiz__visual { display: flex; justify-content: center; margin-top: 10px; }
.quiz__visual:empty { display: none; margin: 0; }

/* --------------------------------------------------------------------------
   Answer options — chunky, pressable, unmistakable
   -------------------------------------------------------------------------- */

.quiz__opts {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* The gutter has to clear the 3px highlight ring on both neighbours and
     still read as a gap. At 10px the four options looked like one block. */
  gap: 14px;
}
.quiz__opts[data-n="2"] { grid-template-columns: 1fr 1fr; }

@media (min-width: 430px) {
  .quiz__opts { gap: 18px; }
}

.opt {
  min-height: 62px;
  padding: 10px 14px;
  border-radius: 20px;
  background: linear-gradient(175deg, #fffdf6, #ffeecd);
  color: var(--ink);
  box-shadow: 0 6px 0 #d8a94f, 0 12px 22px rgba(0, 0, 0, .28);
  display: flex; align-items: center; justify-content: center; gap: 8px;
  transition: transform .12s ease, box-shadow .12s ease, opacity .35s ease, filter .35s ease;
}
.opt:hover  { transform: translateY(-2px); box-shadow: 0 8px 0 #d8a94f, 0 16px 26px rgba(0,0,0,.3); }
.opt:active { transform: translateY(4px);  box-shadow: 0 2px 0 #d8a94f; }
.opt__num   { font: 600 clamp(28px, 9vw, 38px)/1 var(--font-display); }
.opt__icon  { font-size: 26px; }
.opt__label { font: 800 17px var(--font-ui); }
.eq--opt    { font-size: clamp(17px, 5.4vw, 22px); --eq-gap: 3px; }
.quiz__opts--eq .opt { min-height: 66px; }

.opt.is-out {
  opacity: .25;
  filter: grayscale(1);
  transform: scale(.9);
  box-shadow: none;
  pointer-events: none;
}
.opt.is-right {
  background: linear-gradient(175deg, #eafff4, #b6f7d8);
  box-shadow: 0 6px 0 #12b06c, 0 0 0 3px var(--green-soft), 0 0 30px rgba(92, 240, 174, .55);
  animation: qzright .55s cubic-bezier(.2, 1.7, .4, 1);
}
@keyframes qzright {
  0% { transform: scale(1); } 40% { transform: scale(1.14) rotate(-2deg); } 100% { transform: scale(1.05); }
}
.opt.is-wrong {
  background: linear-gradient(175deg, #fff0f5, #ffd3e3);
  box-shadow: 0 6px 0 #d1568c;
  animation: mmwobble .45s ease;
}
.opt.is-answer {
  background: linear-gradient(175deg, #eafff4, #b6f7d8);
  box-shadow: 0 6px 0 #12b06c, 0 0 0 3px var(--green-soft);
  animation: qzpulse 1s ease-in-out 2;
}
@keyframes qzpulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.04); } }
.opt[disabled] { cursor: default; }

/* --- the reveal ----------------------------------------------------------
   For one second after a tap, the two cards that matter — the one chosen and
   the one that was right — are the only ones at full strength. The others
   step back rather than disappearing: a child comparing their answer to the
   right one should still be able to see what else was on offer. */
.opt.is-dimmed {
  opacity: .42;
  filter: saturate(.6);
  box-shadow: 0 3px 0 rgba(0, 0, 0, .18);
  transition: opacity .32s ease, filter .32s ease, box-shadow .32s ease;
}
/* Lifted clear of its neighbours, so nothing overlaps the card being read. */
.opt.is-chosen { position: relative; z-index: 2; }

/* --------------------------------------------------------------------------
   Calm mode
   Already has a third of the particles and none of the whole-screen effects
   (js/fx.js). What is left to quieten is the movement on the cards
   themselves: the answer still changes colour and still rings, it just stops
   jumping about while it does it.
   -------------------------------------------------------------------------- */
[data-calm] .opt.is-right { animation: none; transform: none; }
[data-calm] .opt.is-wrong { animation: none; }
[data-calm] .opt.is-answer { animation: qzpulse 1.1s ease-in-out 1; }
[data-calm] .quiz__card.is-right, [data-calm] .quiz__card.is-wrong { animation: none; }

/* --------------------------------------------------------------------------
   Ask Quackers
   -------------------------------------------------------------------------- */

.quiz__hint {
  align-self: center;
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px;
  padding: 8px 18px;
  border-radius: var(--r-pill);
  background: var(--sheer-2);
  color: #fff;
  font: 800 14px var(--font-ui);
  transition: background .15s ease, transform .15s ease, opacity .2s ease;
}
.quiz__hint:hover { background: var(--sheer-3); transform: translateY(-1px); }
.quiz__hint b {
  background: var(--gold); color: #4a2c00;
  border-radius: 99px; padding: 1px 8px; font-size: 12px;
}
.quiz__hint[disabled] { opacity: .4; }

/* --------------------------------------------------------------------------
   The count-along — what a wrong answer buys you
   -------------------------------------------------------------------------- */

.quiz__explain {
  /* flex:none is load-bearing. This is the only item in the column with
     overflow:hidden, which makes it the only one the flex algorithm is
     allowed to shrink below its content — so on a short screen it collapsed
     to zero height while still holding the whole explanation. */
  flex: none;
  width: 100%;
  border-radius: var(--r-tile);
  background: rgba(0, 0, 0, .3);
  padding: 0 14px;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height .4s ease, opacity .3s ease, padding .3s ease;
  text-align: center;
}
.quiz__explain.is-on {
  max-height: 340px;
  opacity: 1;
  padding: 14px;
}
@media (max-height: 720px) {
  .quiz__explain.is-on { max-height: 240px; padding: 10px; }
  .quiz__explain .eggs__row i { width: 12px; height: 15px; }
}
.quiz__explain-head {
  font: 800 13px var(--font-ui);
  letter-spacing: .04em;
  color: var(--gold);
  margin-bottom: 10px;
}

.eggs { display: flex; flex-direction: column; gap: 7px; align-items: center; }
.eggs__row { display: flex; gap: 6px; }
.eggs__row i {
  width: 17px; height: 21px;
  border-radius: 50% 50% 46% 46% / 62% 62% 38% 38%;
  background: linear-gradient(160deg, #fff6dd, #ffd76a);
  box-shadow: inset 0 -3px 0 rgba(160, 110, 0, .18);
}
.eggs--small .eggs__row i { width: 13px; height: 16px; }
.eggs--tiny  .eggs__row i { width: 10px; height: 12px; }
.eggs--small .eggs__row, .eggs--tiny .eggs__row { gap: 4px; }
.eggs--anim .eggs__row { opacity: .18; filter: grayscale(1); transition: opacity .3s ease, filter .3s ease; }
.eggs--anim .eggs__row.is-on { opacity: 1; filter: none; }
.eggs--anim .eggs__row.is-on i { animation: qzegg .4s cubic-bezier(.2, 1.7, .4, 1) both; }
.eggs--anim .eggs__row.is-on i:nth-child(2) { animation-delay: .04s; }
.eggs--anim .eggs__row.is-on i:nth-child(3) { animation-delay: .08s; }
.eggs--anim .eggs__row.is-on i:nth-child(4) { animation-delay: .12s; }
.eggs--anim .eggs__row.is-on i:nth-child(5) { animation-delay: .16s; }
.eggs--anim .eggs__row.is-on i:nth-child(6) { animation-delay: .20s; }
.eggs--anim .eggs__row.is-on i:nth-child(7) { animation-delay: .24s; }
.eggs--anim .eggs__row.is-on i:nth-child(8) { animation-delay: .28s; }
.eggs--anim .eggs__row.is-on i:nth-child(9) { animation-delay: .32s; }
@keyframes qzegg { 0% { transform: scale(0) rotate(-25deg); } 100% { transform: none; } }

.quiz__total {
  margin-top: 10px;
  font: 600 30px var(--font-display);
  color: #fff;
  font-variant-numeric: tabular-nums;
}
.quiz__total.is-pump { animation: qzpump .35s cubic-bezier(.2, 1.8, .4, 1); }
.quiz__total.is-final { color: var(--green-soft); font-size: 26px; }

/* --------------------------------------------------------------------------
   Results
   -------------------------------------------------------------------------- */

.qres { text-align: center; display: flex; flex-direction: column; align-items: center; gap: var(--s3); }
.qres__title { font: 600 clamp(26px, 8vw, 34px) var(--font-display); color: #fff; margin: 0; }
/* The run's stars, on the same scale and the same amber as a lesson's. */
.qres__stars { font-size: 32px; letter-spacing: 4px; line-height: 1; min-height: 38px; }
/* No `opacity: 0` in the base rule and `both` rather than `forwards`: the
   delay back-fills the hidden frame, and if the animation never runs at all
   the star is simply there. A star that exists only at the end of an
   animation is a star some child never sees. */
.qres__stars i {
  display: inline-block; font-style: normal;
  color: rgba(255, 255, 255, .3);
  animation: mmpop .4s cubic-bezier(.2, 1.2, .4, 1) both;
}
.qres__stars i.is-on { color: var(--amber); }
.qres__starsline { font: 800 13px var(--font-ui); color: var(--amber); }
/* A run that won no stars is not told off for it — same line, quieter, and
   it still names the total the child has. */
.qres__starsline--none { color: rgba(255, 255, 255, .6); }

/* Points. Gold and a bolt, with the word spelled out beneath — this number
   is never stars, and at this size it has the room to say so. */
.qres__scorewrap { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.qres__score {
  display: flex; align-items: center; gap: 8px;
  font: 600 clamp(40px, 13vw, 58px) var(--font-display);
  color: var(--gold);
  line-height: 1;
  text-shadow: 0 4px 0 rgba(0, 0, 0, .28);
  font-variant-numeric: tabular-nums;
}
.qres__score-icon { font-size: .52em; color: #c9a6ff; text-shadow: none; }
.qres__scorecap {
  font: 800 11px var(--font-ui);
  letter-spacing: .14em;
  color: rgba(255, 255, 255, .55);
}
.qres__sub { font: 700 14px var(--font-ui); color: rgba(255, 255, 255, .75); }
.qres__grid { width: 100%; }

/* the egg you tap to hatch a hat */
.egg-prize {
  width: 116px; height: 142px;
  border: 0;
  border-radius: 50% 50% 46% 46% / 62% 62% 38% 38%;
  background: linear-gradient(160deg, #fffdf6, #ffd76a);
  box-shadow: inset 0 -10px 0 rgba(160, 110, 0, .16), 0 12px 30px rgba(0, 0, 0, .35);
  position: relative;
  animation: qzwobble 1.6s ease-in-out infinite;
  display: grid; place-items: center;
  font: 800 13px var(--font-ui); color: #7a5200;
}
@keyframes qzwobble {
  0%, 100% { transform: rotate(-4deg); }
  50%      { transform: rotate(4deg); }
}
.egg-prize:active { transform: scale(.94); }
.egg-prize.is-cracked { animation: none; }

.hatch { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.hatch__name { font: 600 22px var(--font-display); color: var(--gold); }

/* --------------------------------------------------------------------------
   The pond: every hat, and the one Quackers is wearing
   -------------------------------------------------------------------------- */

.pond__hero { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.pond__eggs { font: 800 14px var(--font-ui); color: var(--gold); }

/* How grown up Quackers is, and what would grow him next. */
.pond__age {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 9px 18px;
  border-radius: 999px;
  align-self: center;
  background: rgba(255, 255, 255, .09);
  border: 1.5px solid rgba(255, 255, 255, .14);
}
.pond__age-name {
  font: 600 17px var(--font-display);
  color: #fff;
}
.pond__age-note {
  font: 700 12px var(--font-ui);
  color: rgba(255, 255, 255, .62);
  text-align: center;
}
.hats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.hat-tile {
  background: var(--sheer-1);
  border-radius: var(--r-tile);
  padding: 8px 6px 10px;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  color: rgba(255, 255, 255, .5);
  transition: background .2s ease, transform .15s ease;
}
.hat-tile .dk { --duck: 74px; }
.hat-tile.is-on { color: #fff; background: rgba(255, 255, 255, .14); }
.hat-tile.is-on:hover { transform: translateY(-3px); background: rgba(255,255,255,.2); }
.hat-tile.is-worn { box-shadow: inset 0 0 0 2px var(--gold); }
.hat-tile__name { font: 800 11px var(--font-ui); text-align: center; }
.hat-tile__lock { font-size: 20px; opacity: .55; }
.hat-tile--locked .dk { filter: grayscale(1) brightness(.55); }

@media (min-width: 420px) {
  .hats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
   The trophy on the test result
   -------------------------------------------------------------------------- */

.qres__trophy {
  display: flex; align-items: center; gap: var(--s3);
  align-self: center;
  padding: 10px 18px 10px 12px;
  border-radius: 999px;
  background: linear-gradient(140deg, rgba(255, 215, 106, .96), rgba(255, 182, 46, .96));
  box-shadow: 0 4px 0 rgba(0, 0, 0, .26), 0 0 30px rgba(255, 215, 106, .45);
  animation: qzpump .5s cubic-bezier(.2, 1.8, .4, 1) .4s both;
}
.qres__trophy-icon { font-size: 26px; line-height: 1; }
.qres__trophy-name {
  font: 800 14px var(--font-ui);
  color: var(--ink-2);
  letter-spacing: .02em;
}

/* --------------------------------------------------------------------------
   Narrow phones
   The bar carries five things at 360px. The chips give up their padding
   first; the pips shrink but never vanish, and never overlap.
   -------------------------------------------------------------------------- */
@media (max-width: 420px) {
  .quiz__bar { gap: 6px; }
  .quiz__scorechip, .quiz__starchip { padding: 6px 8px; gap: 4px; }
  .quiz__pips { gap: 4px; }
  .quiz__pips i { width: 7px; height: 7px; }
}
@media (max-width: 340px) {
  .quiz__pips { gap: 2px; }
  .quiz__pips i { width: 5px; height: 5px; }
}

/* ==========================================================================
   The celebration queue
   One card on screen at a time, each with its own Next. The pile-up this
   replaces was five celebrations on five independent timers; the rule that
   prevents it coming back is structural rather than a matter of timing —
   the host holds exactly one card, and drawing the next one clears it.

   Nothing here paints over the particles: the canvas sits behind the whole
   app (css/fx.css), so confetti falls around these cards and never across
   their text.
   ========================================================================== */

.qsteps {
  width: 100%;
  margin-block: auto;
  display: flex;
  justify-content: center;
}

.qstep {
  width: 100%;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s3);
  position: relative;
  animation: qstepin .34s cubic-bezier(.2, 1.1, .4, 1) both;
}
@keyframes qstepin {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

.qstep__title {
  font: 600 clamp(24px, 7.5vw, 32px) var(--font-display);
  color: #fff;
  margin: 0;
}
/* Quackers speaks above his own head, and his bubble was landing on the
   title. The gap is the bubble's room — the same allowance the old results
   screen made for him. */
.qstep .dk-stage { margin-top: 46px; }
.qstep__body {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s3);
}
.qstep__next { width: 100%; }
/* Held back until the egg is open. Said plainly, because a button that looks
   tappable and is not reads as the game being broken. */
.qstep__next[disabled] {
  opacity: .45;
  box-shadow: 0 3px 0 rgba(0, 0, 0, .25);
  cursor: default;
  transform: none;
}
.qstep__lead { font: 700 17px var(--font-ui); color: #fff; }
.qstep__note {
  font: 600 13px/1.6 var(--font-ui);
  color: rgba(255, 255, 255, .7);
  margin: 0;
  max-width: 34ch;
}
/* "Perfect!" used to be a banner that landed on top of this card. */
.qstep__flag {
  font: 800 13px var(--font-ui);
  letter-spacing: .04em;
  color: var(--ink-2);
  background: linear-gradient(140deg, var(--gold), var(--amber));
  border-radius: var(--r-pill);
  padding: 7px 15px;
}
.qstep__big { font-size: 56px; line-height: 1; }

/* --- step dots ---------------------------------------------------------- */
.qsteps__dots {
  display: flex; justify-content: center; gap: 7px;
  padding-block: var(--s3) var(--s2);
}
.qsteps__dots i {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .22);
  transition: background .3s ease, transform .3s ease;
}
.qsteps__dots i.is-done { background: rgba(255, 255, 255, .45); }
.qsteps__dots i.is-now  { background: var(--gold); transform: scale(1.5); }

/* --- the parent's prize -------------------------------------------------
   The one screen in the game about a promise a real person made, so it is
   the one screen that gets the whole width, the largest type, and an
   instruction rather than a title. */
.qstep--prize .qstep__body { gap: var(--s2); }
.qstep__prize-art {
  width: 136px; height: 136px;
  border-radius: 26px;
  background: rgba(0, 0, 0, .28) center/cover no-repeat;
  border: 2px solid rgba(255, 215, 106, .45);
  box-shadow: 0 0 0 6px rgba(255, 215, 106, .16);
  display: grid; place-items: center;
  font-size: 64px; line-height: 1;
  position: relative; z-index: 1;
  animation: qstepart .8s cubic-bezier(.2, 1.4, .35, 1) .15s both;
}
@keyframes qstepart {
  from { opacity: 0; transform: scale(.6) rotate(-8deg); }
  to   { opacity: 1; transform: scale(1) rotate(0); }
}
.qstep__prize-art.has-photo { font-size: 0; }
/* A 📜 certificate takes the art's place on the win screen. */
.qstep__cert { position: relative; z-index: 1; max-inline-size: 250px; margin-block: 4px 10px; }
.qstep__prize-name {
  font: 700 clamp(21px, 6.4vw, 27px)/1.2 var(--font-display);
  color: #fff;
  overflow-wrap: anywhere;
}
.qstep__prize-amount {
  font: 800 28px/1 'IBM Plex Mono', monospace;
  color: var(--gold);
}
/* The sentence the whole screen exists for. */
.qstep__prize-ask {
  font: 800 15px var(--font-ui);
  letter-spacing: .02em;
  color: var(--ink-2);
  background: linear-gradient(140deg, #ffd76a, #ff8a2b);
  border-radius: var(--r-pill);
  padding: 11px 20px;
  box-shadow: 0 5px 0 rgba(0, 0, 0, .22);
  margin-top: 4px;
}
.qstep__prize-note {
  font: 600 13px/1.6 var(--font-ui);
  color: rgba(255, 255, 255, .72);
  margin: 0;
}
.qstep__rays {
  position: absolute;
  top: -10px; left: 50%;
  width: 240px; height: 240px;
  margin-left: -120px;
  z-index: 0;
  pointer-events: none;
  opacity: .45;
  background: conic-gradient(
    from 0deg,
    rgba(255, 215, 106, .5) 0deg 12deg, transparent 12deg 30deg,
    rgba(255, 215, 106, .5) 30deg 42deg, transparent 42deg 60deg,
    rgba(255, 215, 106, .5) 60deg 72deg, transparent 72deg 90deg,
    rgba(255, 215, 106, .5) 90deg 102deg, transparent 102deg 120deg,
    rgba(255, 215, 106, .5) 120deg 132deg, transparent 132deg 150deg,
    rgba(255, 215, 106, .5) 150deg 162deg, transparent 162deg 180deg,
    rgba(255, 215, 106, .5) 180deg 192deg, transparent 192deg 210deg,
    rgba(255, 215, 106, .5) 210deg 222deg, transparent 222deg 240deg,
    rgba(255, 215, 106, .5) 240deg 252deg, transparent 252deg 270deg,
    rgba(255, 215, 106, .5) 270deg 282deg, transparent 282deg 300deg,
    rgba(255, 215, 106, .5) 300deg 312deg, transparent 312deg 330deg,
    rgba(255, 215, 106, .5) 330deg 342deg, transparent 342deg 360deg);
  -webkit-mask-image: radial-gradient(circle, transparent 24%, #000 40%, transparent 74%);
  mask-image: radial-gradient(circle, transparent 24%, #000 40%, transparent 74%);
  animation: qsteprays 16s linear infinite;
}
@keyframes qsteprays { to { transform: rotate(360deg); } }

/* --- trophies and items -------------------------------------------------- */
.qstep__list, .qstep__items {
  width: 100%;
  display: flex; flex-direction: column;
  align-items: center;
  gap: 10px;
}
.qstep__trophy, .qstep__unlock {
  width: 100%;
  display: flex; align-items: center; gap: 12px;
  text-align: left;
  background: rgba(255, 255, 255, .12);
  border-radius: var(--r-tile);
  padding: 12px 14px;
}
.qstep__unlock.is-new { background: rgba(255, 215, 106, .18); }
.qstep__trophy-icon, .qstep__unlock-icon { font-size: 30px; line-height: 1; flex: none; }
.qstep__trophy-name, .qstep__unlock-name { font: 800 15px var(--font-ui); color: #fff; }
.qstep__trophy-desc, .qstep__unlock-desc {
  font: 600 12px/1.5 var(--font-ui);
  color: rgba(255, 255, 255, .66);
}

/* Calm mode: the cards arrive, they just stop sliding and spinning to do it. */
[data-calm] .qstep { animation: none; }
[data-calm] .qstep__prize-art { animation: none; }
[data-calm] .qstep__rays { animation: none; opacity: .3; }

@media (prefers-reduced-motion: reduce) {
  .qstep, .qstep__prize-art { animation: none; }
  .qstep__rays { animation: none; }
}
