/* ══════════════════════════════════════════════════════════════════════════
   BARRE — the three keyframes (verbatim, spec 01 §1) + reduced-motion guard
   Only `transform` and `opacity` are animated anywhere in the app.
   ══════════════════════════════════════════════════════════════════════ */

@keyframes riseIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@keyframes pop {
  0%   { transform: scale(.86); }
  60%  { transform: scale(1.06); }
  100% { transform: scale(1); }
}
@keyframes pulseRing {
  0%   { box-shadow: 0 0 0 0    rgba(208,99,127,.35); }
  70%  { box-shadow: 0 0 0 14px rgba(208,99,127,0); }
  100% { box-shadow: 0 0 0 0    rgba(208,99,127,0); }
}

/* Sheet entrance (layout.css) */
@keyframes sheetUp {
  from { transform: translateY(14px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* Usage map (spec 01 §1):
     riseIn    .35s — each mistake accordion card
     riseIn    .3s  — quiz explainer panel on answer
     pop       .4s  — playful-challenge counter numeral
     pop       .5s  — quiz final score numeral
     pulseRing 2.6s infinite — video-tile play ring                        */
.anim-rise   { animation: riseIn var(--dur-rise) var(--ease) both; }
.anim-rise-q { animation: riseIn .3s var(--ease) both; }
.anim-pop    { animation: pop var(--dur-pop) var(--ease); }
.anim-pop-lg { animation: pop .5s var(--ease); }
.anim-pulse  { animation: pulseRing var(--dur-pulse) infinite; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── The three keyframes the blanket guard above does not actually stop ──────
   Collapsing a duration only works for a pure fade. All three keyframes here
   move an object, and at .01ms the movement still happens — it just happens
   inside a single frame, which on a throttled phone lands as a jump or a flash
   rather than as nothing. (spec 09 §4)

   These rules name the real selectors rather than the .anim-* utilities,
   because the animations are applied by selector in components.css, layout.css
   and screens.css; the utility classes are near-unused. Keep both lists in
   step if a new element takes one of these keyframes.  css/a11y.css §5
   reinforces some of the same selectors and adds .b-sheet / .st-ring__prog.
   ────────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {

  /* riseIn is opacity 0→1 AND translateY(10px)→none. The guard leaves the
     translate in. Land them flat instead. */
  .b-mistake,          /* components.css — every mistake accordion card */
  .b-explainer,        /* components.css — the quiz explainer           */
  .b-toast,            /* layout.css                                    */
  .anim-rise,
  .anim-rise-q {
    animation: none !important;
    opacity: 1;
    transform: none;
  }

  /* Same, but this one is centred with a transform of its own — riseIn's
     `to { transform: none }` must not be what wins. */
  .b-updatepill {
    animation: none !important;
    opacity: 1;
    transform: translateX(-50%);
  }

  /* pop scales .86 → 1.06 → 1. At .01ms the element still paints at .86 for a
     frame, so the numeral flickers small-then-right. Show it at rest. */
  .s-quiz__score,      /* screens.css — the quiz score numeral */
  .anim-pop,
  .anim-pop-lg {
    animation: none !important;
    transform: none;
  }

  /* pulseRing grows a box-shadow spread 0 → 14px and back, i.e. an expanding
     object rather than a fade. Collapsing the duration turns a 2.6s pulse into
     an instantaneous 14px flash on first paint — a WORSE vestibular event than
     the pulse it replaced. Remove it and substitute a static ring, so the play
     affordance survives. */
  .b-video__ring,      /* components.css */
  .anim-pulse {
    animation: none !important;
  }
  .b-video__ring { box-shadow: 0 0 0 3px rgba(232, 169, 184, .30); }
}
