/* ═══════════════════════════════════════════
   reasons — beat 5 of best-boyfriend
   34 s · swipe · multi-step hold `reasons` at 9 s (N steps, N = 3–21)

   A gold thread hangs across the top of the frame as a circular arc, with
   N pegs along it. A deck of cream cards waits below; each swipe flies the
   top card up onto its peg as a mini-card. Then the garland lights, the arc
   curls into a ring (a wreath turning around "That's all of them. For
   today."), lifts to the top of the dark and dissolves into motes.

   Geometry (js/reasons.js writes every value as a custom property on the
   container, in px of the container, which is the stage):
     --reasons-acx/-acy   the arc's centre (far above the frame)
     --reasons-R          the arc's radius;  --reasons-r the wreath's
     --reasons-wcx/-wcy   the wreath's centre = the deck's centre
     --reasons-tx/-ty     arc centre minus wreath centre
     each slot: --reasons-a (its angle on the arc), --reasons-phi (on the ring)
   A slot is `translate(t) rotate(angle) translateY(-radius) rotate(-180deg)`
   in both states, so the gather interpolates centre, radius and angle
   together: at every instant the pegs sit on one circle, and the thread
   (the same circle, scaled) passes through them as it closes into a ring.

   Motion is transform and opacity only. The thread's draw is a
   transform-only wipe, its light sweep a rotation about the arc's centre,
   the wreath's turn one rotation on .reasons-turn, every glow a
   pre-painted layer whose opacity moves. Every class and keyframe is
   prefixed `reasons-`.

   What moves card by card or peg by peg (the pegs appearing, each step's
   flight and the deck rising behind it, the mini-card / halo / glint, the
   garland lighting, the dissolve and the loosen) is played by js/reasons.js
   on the Web Animations API. The rules below hold those END states with no
   transition: a CSS transition per card fires a transitionend per card, and
   the page's badge guard re-measures the whole page on every one.
   ═══════════════════════════════════════════ */

.reasons-container {
    /* The card: portrait, sized to the stage (the container is the size container). */
    --reasons-cw: min(76cqw, 300px, 39cqh);
    --reasons-ch: calc(var(--reasons-cw) * 1.12);          /* js MINI_AR matches */
    --reasons-pw: calc(var(--reasons-mw, 20px) * 0.14 + 2px); /* peg width; js matches */
    position: absolute;
    inset: 0;
    container-type: size;
    display: grid;
    grid-template-columns: 100%;
    grid-template-rows: var(--reasons-band, 24%) auto minmax(0, 1fr) auto;
    justify-items: center;
    box-sizing: border-box;
    /* At least 56 px under the hint's button: the bottom 47 px on the right
       is where the "Made with Reveel" badge rests (16 px inset, ~31 px tall),
       plus the guard's own 8 px gap. The guard cannot lift the badge over this
       stack (the hint text and the full-row deck above the button are both
       data-reveel-avoid, more than its quarter-frame cap to clear), so it
       would stand down there, dimmed, on top of "Next reason". Kept out of
       that band, the stack gives it nothing to clear: it stays put, and
       clickable. On a short frame the card, 39cqh, gives a little to it. */
    padding-bottom: max(56px, 3svh + env(safe-area-inset-bottom, 0px));
    pointer-events: none;
}

/* ───── 1. The room: the dark at both ends of the beat, and the lamp's pool ─────
   Oversized, so a camera pulled back (z -120) still finds it covering the frame. */
.reasons-room {
    position: absolute;
    inset: -40%;
    pointer-events: none;
}

.reasons-dark {
    position: absolute;
    inset: 0;
    background: var(--void);
    opacity: 0.9;
    transition: opacity 2.2s var(--ease-silk);
}

.reasons-pool {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 120vmin;
    height: 120vmin;
    margin: -60vmin 0 0 -60vmin;
    border-radius: 50%;
    background: radial-gradient(circle closest-side, var(--lamp-cone-narrow) 0%, var(--lamp-cone) 34%, rgba(246, 220, 154, 0) 100%);
    opacity: 0.4;
    transform: scale(0.6);
    transition: opacity 2.4s var(--ease-silk), transform 2.4s var(--ease-stage);
}

/* 0 s: the lamp widens back into the room. */
.reasons-container.reasons--entered .reasons-dark { opacity: 0; }
.reasons-container.reasons--entered .reasons-pool { opacity: 0; transform: scale(2); }

/* 29–34 s: the room darkens to a single pool of light. */
.reasons-container.reasons--entered.reasons--dusk .reasons-dark {
    opacity: 0.9;
    transition: opacity 5s var(--ease-silk);
}
.reasons-container.reasons--entered.reasons--dusk .reasons-pool {
    opacity: 0.8;
    transform: scale(0.72);
    transition: opacity 5s var(--ease-silk), transform 5s var(--ease-stage);
}

/* ───── 2. The line, at the wreath's centre ───── */
.reasons-line {
    grid-row: 3;
    grid-column: 1;
    align-self: center;
    position: relative;
    margin: 0;
    max-width: min(84cqw, calc(var(--reasons-r, 104px) * 1.72));
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: clamp(1.15rem, 5.2cqw, 1.55rem);
    line-height: 1.3;
    text-align: center;
    color: var(--text-primary);
    text-shadow: 0 0 22px var(--accent-warm-glow-soft), 0 1px 0 rgba(22, 5, 9, 0.6);
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 1.2s var(--ease-silk), transform 1.6s var(--ease-expo-out);
}

.reasons-line-a,
.reasons-line-b { display: block; }

.reasons-line.reasons--on { opacity: 1; transform: none; }
.reasons-line.reasons--on.reasons--off { opacity: 0; transition: opacity 1.4s var(--ease-silk); }

/* ───── 3. The garland ───── */
.reasons-garland {
    position: absolute;
    inset: 0;
    box-sizing: border-box;
    padding-top: env(safe-area-inset-top, 0px);   /* read by js: the arc hangs below it */
    pointer-events: none;
}

/* The thread's draw: a transform-only wipe. The window (oversized, so the
   closing ring is never clipped while the camera is pulled back) slides
   right while its content slides left by the same amount. Entry state:
   the thread is drawn from the left edge to 30% of the frame (the-letter's
   exit began it); 0.8–2.4 s it finishes. */
.reasons-wipe {
    position: absolute;
    left: -30%;
    top: -30%;
    width: 160%;
    height: 160%;
    overflow: hidden;
    transform: translateX(-62.5%);
}

.reasons-wipe-inner {
    position: absolute;
    inset: 0;
    transform: translateX(62.5%);
}

.reasons-garland.reasons--drawn .reasons-wipe,
.reasons-garland.reasons--drawn .reasons-wipe-inner {
    transform: translateX(0);
    transition: transform 1.6s var(--ease-expo-out);
}

/* The thread is the arc's whole circle (only its lowest stretch is in the
   frame). Anchored at the wreath's centre, offset by --reasons-tx/-ty to the
   arc's centre; the wipe's window starts 30% left and 30% above the stage. */
.reasons-loop {
    position: absolute;
    left: var(--reasons-lx, 50%);
    top: var(--reasons-ly, 50%);
    width: 0;
    height: 0;
    transform: translate(var(--reasons-tx, 0px), var(--reasons-ty, -400px)) scale(1);
}

.reasons-loop-line,
.reasons-loop-lit {
    position: absolute;
    left: calc(-1 * var(--reasons-R, 340px));
    top: calc(-1 * var(--reasons-R, 340px));
    width: calc(2 * var(--reasons-R, 340px));
    height: calc(2 * var(--reasons-R, 340px));
    box-sizing: border-box;
    border-radius: 50%;
}

.reasons-loop-line { border: 1.5px solid var(--thread); }

.reasons-loop-lit {
    border: 2px solid var(--accent-warm-bright);
    box-shadow: 0 0 8px rgba(246, 220, 154, 0.45), inset 0 0 8px rgba(246, 220, 154, 0.3);
    opacity: 0;
}

/* The light running along the thread: a glint on an arm from the arc's
   centre, swung across (one rotation). */
.reasons-glint-orbit {
    position: absolute;
    left: var(--reasons-acx, 50%);
    top: var(--reasons-acy, -300px);
    width: 0;
    height: 0;
    transform: rotate(var(--reasons-aL, 210deg));
    opacity: 0;
}

.reasons-glint {
    position: absolute;
    left: -16px;
    top: -16px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: radial-gradient(circle, var(--light-core) 0%, rgba(246, 220, 154, 0.8) 22%, rgba(226, 177, 85, 0.28) 46%, rgba(226, 177, 85, 0) 70%);
    transform: translateY(calc(-1 * var(--reasons-R, 340px)));
}

/* The wreath's frame of reference: anchored at the wreath's centre.
   .reasons-lift carries the lift, .reasons-turn the turn (one transform). */
.reasons-lift {
    position: absolute;
    left: var(--reasons-wcx, 50%);
    top: var(--reasons-wcy, 50%);
    width: 0;
    height: 0;
    transform: translateY(0) scale(1);
}

.reasons-glowfield {
    position: absolute;
    left: calc(-1 * var(--reasons-gf, 190px));
    top: calc(-1 * var(--reasons-gf, 190px));
    width: calc(2 * var(--reasons-gf, 190px));
    height: calc(2 * var(--reasons-gf, 190px));
    border-radius: 50%;
    background: radial-gradient(circle closest-side, rgba(246, 220, 154, 0) 42%, rgba(246, 220, 154, 0.2) 58%, rgba(226, 177, 85, 0.1) 74%, rgba(226, 177, 85, 0) 100%);
    opacity: 0;
}

/* Its warm heart: filled in once the line has gone (24 s), so what lingers
   round the motes in the dark is a glow, not a dark ring. Pre-painted. */
.reasons-glowfield::before {
    content: '';
    position: absolute;
    inset: 8%;
    border-radius: 50%;
    background: radial-gradient(circle closest-side, rgba(246, 220, 154, 0.2) 0%, rgba(226, 177, 85, 0.12) 46%, rgba(226, 177, 85, 0) 100%);
    opacity: 0;
}

.reasons-turn {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    transform: rotate(0deg);
}

.reasons-ring {
    position: absolute;
    left: calc(-1 * var(--reasons-r, 104px));
    top: calc(-1 * var(--reasons-r, 104px));
    width: calc(2 * var(--reasons-r, 104px));
    height: calc(2 * var(--reasons-r, 104px));
    box-sizing: border-box;
    border-radius: 50%;
    border: 1.5px solid var(--accent-warm-bright);
    box-shadow: 0 0 10px rgba(246, 220, 154, 0.35), inset 0 0 10px rgba(246, 220, 154, 0.2);
    opacity: 0;
}

.reasons-ringmotes,
.reasons-slots {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
}

.reasons-ringmote {
    position: absolute;
    left: -3px;
    top: -3px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: radial-gradient(circle, var(--light-core) 0%, rgba(246, 220, 154, 0.7) 35%, rgba(226, 177, 85, 0) 70%);
    transform: rotate(calc(var(--reasons-i, 0) * 30deg + 15deg)) translateY(calc(-1 * var(--reasons-r, 104px)));
    opacity: 0;
}

/* ───── A slot: one peg and the mini-card that hangs from it ─────
   Local frame: the peg sits on the thread at (0, 0); +y is the way the card
   hangs (down off the arc, outward off the ring). */
.reasons-slot {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    transform:
        translate(var(--reasons-tx, 0px), var(--reasons-ty, -400px))
        rotate(var(--reasons-a, 180deg))
        translateY(calc(-1 * var(--reasons-R, 340px)))
        rotate(-180deg);
}

.reasons-slot > span {
    position: absolute;
    display: block;
    pointer-events: none;
}

/* The mini-card: the card in miniature (its ratio, a foil dot, two ink lines). */
.reasons-mini {
    left: calc(var(--reasons-mw, 20px) * -0.5);
    top: calc(var(--reasons-pw) * 0.6);
    width: var(--reasons-mw, 20px);
    height: var(--reasons-mh, 22px);
    border-radius: 1.5px;
    background: var(--paper);
    box-shadow: inset 0 0 0 0.5px var(--paper-edge), 0 1px 3px rgba(22, 5, 9, 0.55);
    opacity: 0;
}

.reasons-mini::before {
    content: '';
    position: absolute;
    left: 34%;
    top: 11%;
    width: 32%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: var(--foil-gradient);
}

.reasons-mini::after {
    content: '';
    position: absolute;
    left: 20%;
    right: 20%;
    top: 54%;
    height: 22%;
    background:
        linear-gradient(var(--ink-soft), var(--ink-soft)) 0 0 / 100% 1px no-repeat,
        linear-gradient(var(--ink-soft), var(--ink-soft)) 50% 100% / 70% 1px no-repeat;
    opacity: 0.4;
}

/* Its lit glow (the garland lighting, then the wreath's): pre-painted. */
.reasons-slot-glow {
    left: calc(var(--reasons-mw, 20px) * -1.5);
    top: calc(var(--reasons-pw) * 0.6 + var(--reasons-mh, 22px) * 0.5 - var(--reasons-mw, 20px) * 1.5);
    width: calc(var(--reasons-mw, 20px) * 3);
    height: calc(var(--reasons-mw, 20px) * 3);
    border-radius: 50%;
    background: radial-gradient(circle closest-side, rgba(246, 220, 154, 0.55) 0%, rgba(226, 177, 85, 0.2) 45%, rgba(226, 177, 85, 0) 100%);
    opacity: 0;
}

/* The light motes each card dissolves into: one at its heart, one at its tip. */
.reasons-mote {
    left: -4px;
    top: calc(var(--reasons-pw) * 0.6 + var(--reasons-mh, 22px) * 0.5 - 4px);
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: radial-gradient(circle, var(--light-core) 0%, rgba(246, 220, 154, 0.75) 32%, rgba(226, 177, 85, 0) 70%);
    opacity: 0;
    transform: scale(0.3);
}

.reasons-mote.reasons-mote--tip {
    left: -3px;
    top: calc(var(--reasons-pw) * 0.6 + var(--reasons-mh, 22px) - 3px);
    width: 6px;
    height: 6px;
}

/* The peg's halo: pre-painted (--peg-glow), only its opacity moves. */
.reasons-peg-halo {
    left: calc(var(--reasons-pw) * -0.9);
    top: calc(var(--reasons-pw) * -0.65);
    width: calc(var(--reasons-pw) * 1.8);
    height: calc(var(--reasons-pw) * 1.8);
    border-radius: 50%;
    background: rgba(246, 220, 154, 0.5);
    box-shadow: var(--peg-glow);
    opacity: 0;
}

/* The peg: a little gold clip across the thread, pinching the card's top. */
.reasons-peg {
    left: calc(var(--reasons-pw) * -0.5);
    top: calc(var(--reasons-pw) * -0.95);
    width: var(--reasons-pw);
    height: calc(var(--reasons-pw) * 2.4);
    border-radius: 1px;
    background: linear-gradient(90deg, var(--accent-warm-deep), var(--accent-warm-bright) 45%, var(--peg) 70%, var(--accent-warm-deep));
    box-shadow: 0 1px 2px rgba(22, 5, 9, 0.6);
    opacity: 0;
    transform: scale(0.3);
}

/* The glint on arrival: a four-point star. */
.reasons-peg-glint {
    left: -12px;
    top: calc(var(--reasons-pw) * 0.25 - 12px);
    width: 24px;
    height: 24px;
    background:
        radial-gradient(circle, var(--light-core) 0%, rgba(246, 220, 154, 0.6) 14%, rgba(246, 220, 154, 0) 34%),
        linear-gradient(90deg, rgba(246, 220, 154, 0) 46%, var(--accent-warm-bright) 50%, rgba(246, 220, 154, 0) 54%),
        linear-gradient(0deg, rgba(246, 220, 154, 0) 46%, var(--accent-warm-bright) 50%, rgba(246, 220, 154, 0) 54%);
    opacity: 0;
}

/* ───── The garland, phase by phase (in film order) ───── */

/* 0.8 s: the pegs appear along the thread, 0.05 s apart
   (js drawThread: opacity 0.4 s silk, scale 0.3 -> 1 0.5 s expo-out, from 0.1 s). */
.reasons-garland.reasons--pegs .reasons-peg {
    opacity: 1;
    transform: none;
}

/* Each step: the mini-card appears as the flying card lands on it (0.9 s),
   the peg's halo lights, the glint flares (js pinMotion: mini 0.22 s at
   0.72 s, halo 0.5 s at 0.82 s, glint 0.7 s at 0.8 s). */
.reasons-slot.reasons--pinned .reasons-mini { opacity: 1; }
.reasons-slot.reasons--pinned .reasons-peg-halo { opacity: 1; }

/* 10 s: the garland lights left to right (js garlandLights: 0.7 s a peg,
   0.12 s apart, in step with the glint running along the thread). */
.reasons-garland.reasons--lit .reasons-slot-glow { opacity: 1; }

.reasons-garland.reasons--lit .reasons-loop-lit {
    opacity: 1;
    transition: opacity var(--reasons-sweep, 1.5s) linear;
}

.reasons-garland.reasons--lit .reasons-glint-orbit {
    animation: reasons-sweep var(--reasons-sweep, 1.5s) linear both;
}

/* 13–16.5 s: the arc gathers into a wreath. The slots and the thread share
   one transition, so the thread passes through every peg as it closes. */
.reasons-garland.reasons--gather .reasons-slot {
    transform:
        translate(0px, 0px)
        rotate(var(--reasons-phi, 180deg))
        translateY(calc(-1 * var(--reasons-r, 104px)))
        rotate(-180deg);
    transition: transform 3.5s var(--ease-stage);
}

.reasons-garland.reasons--gather .reasons-loop {
    transform: translate(0px, 0px) scale(var(--reasons-ls, 0.3));
    opacity: 0;
    transition: transform 3.5s var(--ease-stage), opacity 0.9s var(--ease-silk) 2.6s;
}

.reasons-garland.reasons--gather .reasons-ring {
    opacity: 1;
    transition: opacity 0.9s var(--ease-silk) 2.6s;
}

/* 16 s → 34 s: the wreath turns, slowly, as one transform. */
.reasons-garland.reasons--turn .reasons-turn {
    transform: rotate(130deg);
    transition: transform 18s var(--ease-breath);
}

/* 16.5 s: it glows; the glow breathes (one layer). */
.reasons-garland.reasons--glow .reasons-glowfield {
    opacity: 1;
    transition: opacity 2.2s var(--ease-silk);
    animation: reasons-breathe 3.6s var(--ease-breath) 2.2s infinite alternate;
}

/* 24–29 s: it lifts to the top of the dark ... */
.reasons-garland.reasons--lift .reasons-lift {
    transform: translateY(var(--reasons-lift-y, -200px)) scale(0.55);   /* js LIFT_SCALE */
    transition: transform 5s var(--ease-stage);
}

/* The glow does not go out with the wreath: it dims and rides up with it,
   still breathing, a warm halo for the motes it dissolves into. */
.reasons-garland.reasons--lift .reasons-glowfield {
    opacity: 0.6;
    transition: opacity 2.4s var(--ease-silk);
}

.reasons-garland.reasons--lift .reasons-glowfield::before {
    opacity: 1;
    transition: opacity 3s var(--ease-silk) 0.8s;
}

/* ... and dissolves into light motes, card by card around the ring
   (js dissolve: 0.06 s a card; mini 0.9 s / scale 1.1 s, glow, peg and halo
   0.8 s, motes 0.9 s from 0.1 s / scale 1.2 s; ring motes 1 s, 0.08 s apart). */
.reasons-garland.reasons--dissolve .reasons-mini {
    opacity: 0;
    transform: scale(0.4);
}

.reasons-garland.reasons--dissolve .reasons-slot-glow,
.reasons-garland.reasons--dissolve .reasons-peg,
.reasons-garland.reasons--dissolve .reasons-peg-halo { opacity: 0; }

.reasons-garland.reasons--dissolve .reasons-mote {
    opacity: 1;
    transform: none;
}

.reasons-garland.reasons--dissolve .reasons-ring {
    opacity: 0;
    transition: opacity 1.4s var(--ease-silk);
}

.reasons-garland.reasons--dissolve .reasons-ringmote { opacity: 0.9; }

/* 27 s: the motes loosen, drifting a little apart (js loosen: 2.2 s). */
.reasons-garland.reasons--loosen .reasons-mote {
    opacity: 0.75;
    transform: translateY(var(--reasons-drift, 12px)) scale(0.8);
}

.reasons-garland.reasons--loosen .reasons-ringmote { opacity: 0.6; }

/* 29–34 s: as the room darkens and the bokeh rests, the last motes keep
   drifting up, slowly, opening a little apart (one transform, 6.5 s, so they
   are still rising at the cut), and the glow lingers round them, fading as
   slowly. They thin, but are still there for the award to gather. */
.reasons-container.reasons--dusk .reasons-garland {
    opacity: 0.7;
    transition: opacity 5s var(--ease-silk);
}

.reasons-container.reasons--dusk .reasons-garland.reasons--lift .reasons-lift {
    transform: translateY(calc(var(--reasons-lift-y, -200px) - 4cqh)) scale(0.62);
    transition: transform 6.5s var(--ease-drift);
}

.reasons-container.reasons--dusk .reasons-garland.reasons--lift .reasons-glowfield {
    opacity: 0.4;
    transition: opacity 5s var(--ease-breath);
}

/* Each mote keeps drifting outward and swells a little as it rises
   (js dusk: 6.5 s drift; this is its end state, no transition). */
.reasons-container.reasons--dusk .reasons-garland.reasons--loosen .reasons-mote {
    transform: translateY(calc(var(--reasons-drift, 12px) * 2.2)) scale(1.3);
}

/* ───── 4. The eyebrow ───── */
.reasons-eyebrow {
    grid-row: 2;
    grid-column: 1;
    position: relative;
    margin: 0 16px 0.45rem;
    max-width: 30rem;
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 0.74rem;
    line-height: 1.5;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    text-align: center;
    text-wrap: balance;
    color: var(--accent-warm);
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 1.2s var(--ease-silk), transform 1.4s var(--ease-expo-out);
}

.reasons-eyebrow.reasons--on { opacity: 1; transform: none; }
.reasons-eyebrow.reasons--on.reasons--off { opacity: 0; transition: opacity 1s var(--ease-silk); }

/* ───── 5. The deck: the swipe surface, and the cards stacked in depth ───── */
.reasons-deck {
    grid-row: 3;
    grid-column: 1;
    position: relative;
    width: 100%;
    height: 100%;
    min-height: 0;
    display: grid;
    place-items: center;
    perspective: 900px;
    pointer-events: auto;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}

/* A card waits deep (translateZ -500px), unseen. Its depth class places it:
   d0 the top card, d1 / d2 the two edges showing behind, deep the rest,
   gone the one that has flown. --reasons-drag follows the thumb. */
.reasons-deck .reasons-card {
    grid-area: 1 / 1;
    position: relative;
    transform: translate3d(0, 38px, -500px);
    opacity: 0;
    visibility: hidden;
}

/* 3.2 s: the deck builds; the top card rises from depth (1.8 s). The two
   edges behind it stay unseen until it is opaque (0.9 s), then fade up
   under it: while the top card is still translucent nothing shows through
   it (no second reason, no doubled numeral ring), and no card behind is
   ever seen larger than it on its way up. */
.reasons-deck.reasons--built .reasons-card.reasons--d0 {
    transform: translate3d(0, var(--reasons-drag, 0px), 0);
    opacity: 1;
    visibility: visible;
    transition: transform 1.8s var(--ease-expo-out), opacity 0.9s var(--ease-silk), visibility 0s;
}

.reasons-deck.reasons--built .reasons-card.reasons--d1 {
    transform: translate3d(0, 20px, -60px);
    opacity: 1;
    visibility: visible;
    transition: transform 1.4s var(--ease-expo-out) 0.1s, opacity 0.6s var(--ease-silk) 0.9s, visibility 0s 0.9s;
}

.reasons-deck.reasons--built .reasons-card.reasons--d2 {
    transform: translate3d(0, 38px, -120px);
    opacity: 1;
    visibility: visible;
    transition: transform 1.4s var(--ease-expo-out) 0.2s, opacity 0.6s var(--ease-silk) 1s, visibility 0s 1s;
}

/* Each step: the next card rises from depth 0.3 s into the flight (1.3 s in
   all; js stepMotion: transform 1 s expo-out, opacity 0.6 s silk and
   visibility, all from 0.3 s). */
.reasons-deck.reasons--built.reasons--stepped .reasons-card.reasons--d0,
.reasons-deck.reasons--built.reasons--stepped .reasons-card.reasons--d1,
.reasons-deck.reasons--built.reasons--stepped .reasons-card.reasons--d2 {
    transition: none;
}

/* The flown card: its flight is on the three wrappers below; it fades into
   the mini-card on its peg as it lands (js stepMotion: the thumb's offset
   back 0.5 s expo-out, opacity 0.18 s from 0.76 s, hidden at 0.95 s). */
.reasons-deck .reasons-card.reasons--gone {
    transform: translate3d(0, var(--reasons-drag, 0px), 0);
    opacity: 0;
    visibility: hidden;
    transition: none;
}

.reasons-deck .reasons-card.reasons--gone.reasons--skip { transition: none; }

/* The thumb's drag (no lag), and a short swipe's spring back. */
.reasons-deck .reasons-card.reasons--dragging { transition: none !important; }
.reasons-deck .reasons-card.reasons--spring {
    transition: transform 0.5s var(--ease-expo-out), opacity 0.6s var(--ease-silk), visibility 0s !important;
}

/* The flight: up fast (expo-out) while the sideways travel lags (breath),
   so the card arcs up and over onto its peg, shrinking as it goes (silk);
   0.9 s each, played by js stepMotion. */
.reasons-card-fy,
.reasons-card-fx,
.reasons-card-fs { position: relative; }

.reasons-card.reasons--gone .reasons-card-fy { transform: translateY(var(--reasons-dy, -300px)); }
.reasons-card.reasons--gone .reasons-card-fx { transform: translateX(var(--reasons-dx, 0px)); }
.reasons-card.reasons--gone .reasons-card-fs { transform: rotate(var(--reasons-rot, 0deg)) scale(var(--reasons-sc, 0.08)); }

.reasons-card.reasons--gone.reasons--skip .reasons-card-fy,
.reasons-card.reasons--gone.reasons--skip .reasons-card-fx,
.reasons-card.reasons--gone.reasons--skip .reasons-card-fs { transform: none; transition: none; }

/* The card itself: cream paper, a claret numeral in a gold-foil ring, the reason in oxblood. */
.reasons-card-face {
    position: relative;
    box-sizing: border-box;
    width: var(--reasons-cw);
    height: var(--reasons-ch);
    padding: 1.05rem 1.05rem 1.15rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    border-radius: 12px;
    background: var(--paper);
    box-shadow: inset 0 0 0 1px var(--paper-edge), inset 0 0 30px var(--paper-shade), var(--paper-shadow);
    overflow: hidden;
}

.reasons-card-face::before {
    content: '';
    position: absolute;
    inset: 7px;
    border: 1px solid var(--paper-edge);
    border-radius: 7px;
    pointer-events: none;
}

.reasons-card-num {
    flex: none;
    position: relative;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: var(--foil-gradient);
    box-shadow: 0 1px 2px rgba(50, 13, 22, 0.25);
}

.reasons-card-num-text {
    width: calc(100% - 4px);
    height: calc(100% - 4px);
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: var(--paper);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 1.05rem;
    line-height: 1;
    font-variant-numeric: lining-nums;
    color: var(--ink-script);
}

/* The reason: fitted by js (1.5rem down to 1.05rem, up to 6 lines). Its box
   is sized by the card (flex 1 1 0, min-height 0), never by the text, so it
   is contained: each trial size the fit lays out stays inside this box. */
.reasons-card-text {
    position: relative;
    flex: 1 1 0;
    min-height: 0;
    width: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    contain: strict;
}

.reasons-card-copy {
    margin: auto 0;               /* centred, but an overflow never pushes out of the top */
    font-family: var(--font-display);
    font-weight: 400;
    font-size: 1.5rem;
    line-height: 1.32;            /* js LINE_H */
    color: var(--ink);
    text-align: center;
    text-wrap: balance;
    overflow-wrap: break-word;
}

/* The cards behind are a step darker, the further back the darker
   (pre-painted; a step brightens them 0.9 s from 0.3 s, js stepMotion). */
.reasons-card-dim {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: var(--void);
    opacity: 0;
    pointer-events: none;
}

.reasons-card.reasons--d1 .reasons-card-dim { opacity: 0.16; }
.reasons-card.reasons--d2 .reasons-card-dim { opacity: 0.3; }
.reasons-card.reasons--deep .reasons-card-dim { opacity: 0.3; }

/* ───── 6. The hint and its button ─────
   The 16 px over the hint lifts the deck (and the card and the wreath, both
   centred on it) 8 px, so on a 640 px frame the chevrons' nudge still
   clears the cards behind the top one. */
.reasons-hint {
    grid-row: 4;
    grid-column: 1;
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.7rem;
    padding: calc(0.6rem + 16px) 16px 0;
    pointer-events: none;
}

.reasons-hint-text {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    opacity: 0;
    transition: opacity 0.8s var(--ease-silk);
}

.reasons-hint.reasons--on .reasons-hint-text { opacity: 1; }
.reasons-hint .reasons-hint-text.reasons--off { opacity: 0; }

.reasons-hint-copy {
    margin: 0;
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 0.74rem;
    line-height: 1.3;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    text-align: center;
    color: var(--accent-warm);
}

.reasons-chevs {
    display: grid;
    justify-items: center;
    height: 24px;
}

.reasons-chev {
    width: 13px;
    height: 13px;
    margin-top: -6px;
    border-left: 2px solid var(--accent-warm);
    border-top: 2px solid var(--accent-warm);
    transform: rotate(45deg);
    animation: reasons-nudge 1.6s var(--ease-breath) infinite;
}

.reasons-chev + .reasons-chev { opacity: 0.45; animation-delay: 0.15s; }

/* Looping ornaments are parked while hidden. */
.reasons-hint:not(.reasons--on) .reasons-chev,
.reasons-hint-text.reasons--off .reasons-chev { animation: none; }

.reasons-next {
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 0.88rem;
    line-height: 1;
    color: var(--text-primary);
    background: var(--glass);
    border: 1px solid var(--btn-ghost-border);
    border-radius: 999px;
    padding: 0.8rem 1.45rem;
    min-height: 44px;
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.6s var(--ease-silk), visibility 0s linear 0.6s;
}

.reasons-hint.reasons--on .reasons-next {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity 0.6s var(--ease-silk), visibility 0s;
}

.reasons-next:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 3px;
}

/* ───── Entry states are applied instantly (prepare, a re-render) ───── */
.reasons-container.reasons--instant,
.reasons-container.reasons--instant *,
.reasons-container.reasons--instant *::before,
.reasons-container.reasons--instant *::after {
    transition: none !important;
    animation: none !important;
}

/* ───── Keyframes ───── */
@keyframes reasons-nudge {
    50% { transform: translateY(-7px) rotate(45deg); }
}

@keyframes reasons-sweep {
    0% { transform: rotate(var(--reasons-aL, 210deg)); opacity: 0; }
    8% { opacity: 1; }
    90% { opacity: 1; }
    100% { transform: rotate(var(--reasons-aR, 150deg)); opacity: 0; }
}

@keyframes reasons-breathe {
    from { transform: scale(1); }
    to { transform: scale(1.06); }
}

/* Reduced motion: the arc and the ring trade places under a fade. */
@keyframes reasons-swap {
    0% { opacity: 1; }
    40% { opacity: 0; }
    55% { opacity: 0; }
    100% { opacity: 1; }
}

/* ───── Reduced motion: plays in full, calmer ─────
   No wipe, flight, travel, turn or lift: the thread fades in, a swiped card
   fades out and the next fades up in place, the peg lights fade in, the
   garland lights all at once, the wreath cross-fades in from the arc, and
   it dissolves into motes where it stands. */
@media (prefers-reduced-motion: reduce) {
    .reasons-pool,
    .reasons-container.reasons--entered .reasons-pool,
    .reasons-container.reasons--entered.reasons--dusk .reasons-pool { transform: none; }

    .reasons-line,
    .reasons-line.reasons--on,
    .reasons-eyebrow,
    .reasons-eyebrow.reasons--on { transform: none; }

    .reasons-wipe,
    .reasons-wipe-inner,
    .reasons-garland.reasons--drawn .reasons-wipe,
    .reasons-garland.reasons--drawn .reasons-wipe-inner { transform: none; transition: none; }

    .reasons-loop { opacity: 0.35; }
    .reasons-garland.reasons--drawn .reasons-loop { opacity: 1; transition: opacity 1.6s var(--ease-silk); }
    .reasons-garland.reasons--gather .reasons-loop {
        transform: translate(var(--reasons-tx, 0px), var(--reasons-ty, -400px)) scale(1);
        opacity: 0;
        transition: opacity 0.8s var(--ease-silk);
    }

    .reasons-peg,
    .reasons-garland.reasons--pegs .reasons-peg { transform: none; }

    /* The deck: one card at a time, in place. */
    .reasons-deck .reasons-card,
    .reasons-deck.reasons--built .reasons-card.reasons--d1,
    .reasons-deck.reasons--built .reasons-card.reasons--d2 {
        transform: translate3d(0, var(--reasons-drag, 0px), 0);
        opacity: 0;
        visibility: hidden;
    }

    .reasons-deck.reasons--built .reasons-card.reasons--d0 {
        transform: translate3d(0, var(--reasons-drag, 0px), 0);
        transition: opacity 0.9s var(--ease-silk), visibility 0s, transform 0.5s var(--ease-expo-out);
    }

    /* A step (js stepMotion, reduced): the flown card fades out (0.6 s), the
       next fades up in place from 0.3 s (0.6 s); no flight, no glint; the
       mini-card and halo fade in (0.6 s from 0.3 s / 0.4 s). */
    .reasons-card.reasons--gone .reasons-card-fy,
    .reasons-card.reasons--gone .reasons-card-fx,
    .reasons-card.reasons--gone .reasons-card-fs { transform: none; }

    /* The garland lights all at once (js garlandLights: 1 s). */
    .reasons-garland.reasons--lit .reasons-loop-lit { transition: opacity 1s var(--ease-silk); }
    .reasons-garland.reasons--lit .reasons-glint-orbit { animation: none; }

    /* The wreath cross-fades in from the arc: the slots jump while faded out. */
    .reasons-garland.reasons--gather .reasons-slot {
        transition: transform 0s linear 0.9s;
        animation: reasons-swap 2s var(--ease-silk) both;
    }
    .reasons-garland.reasons--gather .reasons-ring { transition: opacity 1s var(--ease-silk) 1s; }

    .reasons-garland.reasons--turn .reasons-turn { transform: none; transition: none; }
    .reasons-garland.reasons--glow .reasons-glowfield { animation: none; }
    .reasons-garland.reasons--lift .reasons-lift,
    .reasons-container.reasons--dusk .reasons-garland.reasons--lift .reasons-lift { transform: none; transition: none; }

    .reasons-garland.reasons--dissolve .reasons-mini { transform: none; }
    .reasons-mote,
    .reasons-garland.reasons--dissolve .reasons-mote,
    .reasons-garland.reasons--loosen .reasons-mote,
    .reasons-container.reasons--dusk .reasons-garland.reasons--loosen .reasons-mote { transform: none; }

    .reasons-chev { animation: none; }
}
