/* ═══════════════════════════════════════════
   reverse-card — the finale (beat 8 of 8; the set piece is the card flip, no particles)
   Ground: data-ground="stripe" (the red scope of tokens.css). No text sits
   bare on the stripes: the hint and < RESTART > are on --chip-crimson pills,
   and the card's line is inked on the card.

   Play states are classes on .reverse-card-container, toggled by cues
   (js/reverse-card.js):
     -is-in        0 s     the card wipes in left to right (0.15-0.55 s)
     -is-wiped     0.6 s   the wipe's clip is dropped (so the 3D flip is never clipped)
     -is-breathing 1.4 s   the card breathes (after the light sweep)
     -is-calm              reduced motion: a cross-fade instead of the spin
     -is-armed     3.0 s   the hold: the hint shows, the stars twinkle
     -is-dim               the tap: the stripes dim under --burst-dim-red (focus on the card)
     -is-flipping          the lead (tap -> hit): lift, a turn and a half, the hang
     -is-inking / -is-inked  the line is inked (its last stroke on the hit)
     -is-shrunk    the back face's arrows scale/dim to the fit's
                   --reverse-card-arrow-k / -o (1 / 1 when the line fits round them)
     -is-landed    the hit: the card slams home
     -is-undim     tap + 4.0 s   the dim lifts
     -is-restart   tap + 5.0 s   < RESTART >
     -is-rest      tap + 17 s    the loops are parked: the frame is still
   ═══════════════════════════════════════════ */

.reverse-card-container {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: clamp(12px, 2.4vh, 26px);
    /* top: room for the progress tape (right) and the mute pill (left) */
    padding: calc(64px + env(safe-area-inset-top, 0px)) 16px calc(18px + env(safe-area-inset-bottom, 0px));
    /* No clip here: the hit's shake moves this container (not #stage, whose
       overflow clip would bare the body at its edges), and the ground's bleed
       must stay visible past it; #stage clips everything at the viewport. */
    overflow: visible;
    color: var(--text-primary);
    font-family: var(--font-body);
}

/* ───── The knit stripe ground ───── */
.reverse-card-ground {
    position: absolute;
    /* Over-sized past the shake (5 px) and the camera push: never an edge or a seam. */
    inset: min(-24px, -4%);
    background:
        radial-gradient(ellipse at 50% 45%, transparent 55%, rgba(58, 0, 8, 0.28) 100%),
        repeating-linear-gradient(180deg,
            var(--stripe-cherry) 0,
            var(--stripe-cherry) calc(var(--stripe-h) - 3px),
            var(--stripe-pink) calc(var(--stripe-h) + 1px),
            var(--stripe-pink) calc(var(--stripe-h) * 2 - 3px),
            var(--stripe-cherry) calc(var(--stripe-h) * 2));
    pointer-events: none;
}

/* Wool: a static feTurbulence speckle (dark fibres and pale heather), with a slight vertical streak. */
.reverse-card-knit {
    position: absolute;
    inset: 0;
    opacity: 0.6;
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='k' x='0' y='0'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.15 0.34' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.22 0 0 0 0 0.01 0 0 0 0 0.05 1.3 0 0 0 -0.5'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23k)'/%3E%3C/svg%3E"),
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='h' x='0' y='0'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9 0.5' numOctaves='2' seed='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 0.88 0 0 0 0 0.9 0 1.25 0 0 -0.66'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23h)'/%3E%3C/svg%3E");
    background-size: 220px 220px, 180px 180px;
}

/* The flip's dim (focus on the card): ramped in over 0.6 s at the tap, lifted over 0.9 s from tap + 4.0 s. */
.reverse-card-dim {
    position: absolute;
    inset: 0;
    background: var(--burst-dim-red);
    opacity: 0;
    transition: opacity 0.6s var(--ease-silk);
}
.reverse-card-is-dim .reverse-card-dim { opacity: 1; }
.reverse-card-is-dim.reverse-card-is-undim .reverse-card-dim {
    opacity: 0;
    transition: opacity 0.9s var(--ease-silk);
}

/* ───── Gold foil stars ───── */
.reverse-card-stars {
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.reverse-card-defs {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}
.reverse-card-foil-light { stop-color: var(--star-gold-light); }
.reverse-card-foil-mid { stop-color: var(--star-gold); }
.reverse-card-foil-shade { stop-color: var(--star-gold-shade); }

.reverse-card-star {
    position: absolute;
    left: var(--reverse-card-sx);
    top: var(--reverse-card-sy);
    width: var(--reverse-card-ss);
    height: var(--reverse-card-ss);
    margin: calc(var(--reverse-card-ss) / -2) 0 0 calc(var(--reverse-card-ss) / -2);
}
.reverse-card-star-art {
    position: relative;
    display: block;
    width: 100%;
    height: 100%;
    transform: rotate(var(--reverse-card-sr));
}

/* Phone (portrait): the stars at the corners, clear of the card and the thumb zone. */
.reverse-card-star-1 { --reverse-card-sx: 96%; --reverse-card-sy: 21%; --reverse-card-ss: 24vw; --reverse-card-sr: 12deg; }
.reverse-card-star-2 { --reverse-card-sx: 5%;  --reverse-card-sy: 64%; --reverse-card-ss: 13vw; --reverse-card-sr: -10deg; }
.reverse-card-star-3 { --reverse-card-sx: 9%;  --reverse-card-sy: 93%; --reverse-card-ss: 21vw; --reverse-card-sr: -18deg; }
.reverse-card-star-4 { --reverse-card-sx: 92%; --reverse-card-sy: 88%; --reverse-card-ss: 14vw; --reverse-card-sr: 20deg; }

/* The twinkle: from the hold, staggered so they never blink in unison. Never to opacity 0. */
.reverse-card-is-armed .reverse-card-star {
    animation: reverse-card-twinkle 3.2s var(--ease-breath) infinite;
}
.reverse-card-is-armed .reverse-card-star-2 { animation-delay: 0.9s; }
.reverse-card-is-armed .reverse-card-star-3 { animation-delay: 1.7s; }
.reverse-card-is-armed .reverse-card-star-4 { animation-delay: 2.4s; }

@keyframes reverse-card-twinkle {
    0%, 100% { transform: rotate(0deg) scale(1); }
    25% { transform: rotate(4deg) scale(1.04); }
    50% { transform: rotate(0deg) scale(1.08); }
    75% { transform: rotate(-4deg) scale(1.04); }
}

/* ───── The card ───── */
.reverse-card-wipe {
    position: relative;
    z-index: 1;
    flex: 0 0 auto;
    clip-path: inset(-12% 100% -12% -12%);   /* entry state: not yet wiped in */
}
.reverse-card-is-in .reverse-card-wipe {
    animation: reverse-card-wipe-in 0.4s var(--ease-expo-out) 0.15s both;
}
.reverse-card-is-wiped .reverse-card-wipe {
    clip-path: none;
    animation: none;
}

@keyframes reverse-card-wipe-in {
    from { clip-path: inset(-12% 100% -12% -12%); }
    to { clip-path: inset(-12% -12% -12% -12%); }
}

.reverse-card-breath {
    transform-origin: 50% 55%;
}
.reverse-card-is-breathing .reverse-card-breath {
    animation: reverse-card-breathe 3.6s var(--ease-breath) infinite alternate;
}

@keyframes reverse-card-breathe {
    from { transform: scale(1); }
    to { transform: scale(1.015); }
}

/* Phone: about 64vw wide, no taller than 56svh (0.69 aspect). */
.reverse-card-card {
    position: relative;
    display: block;
    width: min(64vw, 38.6vh);
    width: min(64vw, 38.6svh);
    aspect-ratio: 400 / 580;
    padding: 0;
    margin: 0;
    border: 0;
    border-radius: 6px;
    background: none;
    color: inherit;
    font: inherit;
    overflow: visible;
    perspective: 1000px;
    cursor: default;
    -webkit-tap-highlight-color: transparent;
}
.reverse-card-is-armed .reverse-card-card:not(:disabled) { cursor: pointer; }
.reverse-card-card:focus { outline: none; }
.reverse-card-card:focus-visible {
    outline: 3px solid var(--focus-ring);
    outline-offset: 6px;
}

/* The shadow under the card: pre-painted, only its transform and opacity move. */
.reverse-card-shadow {
    position: absolute;
    left: 4%;
    right: 4%;
    top: 8%;
    bottom: -6%;
    border-radius: 50%;
    background: radial-gradient(ellipse at 50% 55%, rgba(40, 0, 8, 0.55) 0%, rgba(40, 0, 8, 0.22) 45%, transparent 72%);
    opacity: 0.7;
    transform: translateY(2%);
    pointer-events: none;
}

.reverse-card-flipper {
    position: absolute;
    inset: 0;
    display: block;
    transform-style: preserve-3d;
    pointer-events: none;
}
.reverse-card-flipper .reverse-card-face {
    position: absolute;
    inset: 0;
    display: block;
    border-radius: 6px;
    overflow: hidden;
    box-shadow: var(--paper-shadow);
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}
.reverse-card-flipper .reverse-card-face-back { transform: rotateY(180deg); }

.reverse-card-art {
    display: block;
    width: 100%;
    height: 100%;
}
.reverse-card-paper { fill: var(--paper-cream); }
.reverse-card-red { fill: var(--bg-elevated); }
.reverse-card-oval {
    fill: var(--bg-elevated);
    stroke: var(--paper-cream);
}
.reverse-card-spin {
    transform-box: view-box;
    transform-origin: 0 0;
}

/* The buyer's line: felt-tip ink with a 3 px cream outline (stroke-width set by the fit). */
.reverse-card-ink-line {
    font-family: var(--font-body);
    font-weight: 700;
    fill: var(--ink-marker);
    stroke: var(--paper-cream);
    stroke-linejoin: round;
    paint-order: stroke fill;
    clip-path: inset(-40% 100% -40% -8%);    /* not yet inked */
}
.reverse-card-is-inked .reverse-card-ink-line { clip-path: inset(-40% -8% -40% -8%); }
.reverse-card-is-inking .reverse-card-ink-line {
    transition: clip-path var(--reverse-card-ink-ms, 160ms) linear var(--reverse-card-ink-delay, 0ms);
}

/* The payoff: lift toward the camera and turn a full turn and a half (0 -> 1.6 s of a
   2.33 s lead, `stage`), then hang and quiver until the hit. Sized to the real lead. */
.reverse-card-is-flipping .reverse-card-flipper {
    animation: reverse-card-flip var(--reverse-card-lead, 2.33s) linear both;
}
.reverse-card-is-flipping .reverse-card-shadow {
    animation: reverse-card-shadow-lift var(--reverse-card-lead, 2.33s) var(--ease-stage) both;
}
.reverse-card-is-flipping .reverse-card-spin {
    animation: reverse-card-spin var(--reverse-card-lead, 2.33s) var(--ease-stage) both;
}

@keyframes reverse-card-flip {
    0% {
        transform: translate3d(0, 0, 0) rotateY(0deg) rotateZ(0deg) scale(1);
        animation-timing-function: var(--ease-stage);
    }
    68.7% {
        transform: translate3d(0, -6px, 120px) rotateY(540deg) rotateZ(0deg) scale(1.12);
        animation-timing-function: ease-in-out;
    }
    74% { transform: translate3d(0, -6px, 120px) rotateY(540deg) rotateZ(0.6deg) scale(1.12); animation-timing-function: ease-in-out; }
    80% { transform: translate3d(0, -6px, 120px) rotateY(540deg) rotateZ(-0.6deg) scale(1.12); animation-timing-function: ease-in-out; }
    86% { transform: translate3d(0, -6px, 120px) rotateY(540deg) rotateZ(0.6deg) scale(1.12); animation-timing-function: ease-in-out; }
    93% { transform: translate3d(0, -6px, 120px) rotateY(540deg) rotateZ(-0.5deg) scale(1.12); animation-timing-function: ease-in-out; }
    100% { transform: translate3d(0, -6px, 120px) rotateY(540deg) rotateZ(0deg) scale(1.12); }
}
@keyframes reverse-card-shadow-lift {
    0% { transform: translateY(2%) scale(1); opacity: 0.7; }
    68.7%, 100% { transform: translateY(16%) scale(1.22); opacity: 0.38; }
}
/* The arrows turn 180° inside the oval mid-flip: the reverse. */
@keyframes reverse-card-spin {
    0%, 28% { transform: rotate(0deg); }
    62%, 100% { transform: rotate(180deg); }
}
/* The back face turns the other way and ends square, so its ink shadow falls down-right. */
.reverse-card-is-flipping .reverse-card-face-back .reverse-card-spin { animation-name: reverse-card-spin-back; }
@keyframes reverse-card-spin-back {
    0%, 28% { transform: rotate(-180deg); }
    62%, 100% { transform: rotate(0deg); }
}

/* As the ink arrives the back face's arrows take the size the fit chose:
   1 when the line fits in the zones round them, down to 0.6 for a long
   line, and 0.6 dimmed to 0.3 when one word is too long for any zone. */
.reverse-card-shrink {
    transform-box: view-box;
    transform-origin: 0 0;
}
.reverse-card-is-shrunk .reverse-card-shrink {
    transform: scale(var(--reverse-card-arrow-k, 1));
    opacity: var(--reverse-card-arrow-o, 1);
    transition: transform 0.3s var(--ease-expo-out), opacity 0.3s var(--ease-silk);
}

/* The hit: the card slams home (scale 1.12 -> 1 over 0.5 s, `snap`) and rests on its inked face. */
.reverse-card-is-landed .reverse-card-flipper {
    transform: translate3d(0, 0, 0) rotateY(540deg) rotateZ(0deg) scale(1);
    animation: reverse-card-land 0.5s var(--ease-snap) both;
}
.reverse-card-is-landed .reverse-card-shadow {
    transform: translateY(2%) scale(1);
    opacity: 0.7;
    animation: reverse-card-shadow-land 0.5s var(--ease-snap) both;
}
.reverse-card-is-landed .reverse-card-spin { transform: rotate(180deg); }
.reverse-card-is-landed .reverse-card-face-back .reverse-card-spin { transform: none; }

@keyframes reverse-card-land {
    from { transform: translate3d(0, -6px, 120px) rotateY(540deg) rotateZ(0deg) scale(1.12); }
    to { transform: translate3d(0, 0, 0) rotateY(540deg) rotateZ(0deg) scale(1); }
}
@keyframes reverse-card-shadow-land {
    from { transform: translateY(16%) scale(1.22); opacity: 0.38; }
    to { transform: translateY(2%) scale(1); opacity: 0.7; }
}

/* Calm (reduced motion, set by the module from film.reduced()): no lift and no spin;
   the blank face cross-fades to the inked one over the same lead. */
.reverse-card-is-calm .reverse-card-flipper,
.reverse-card-is-calm .reverse-card-flipper.reveel-flip {
    transform: none !important;
    animation: none !important;
}
.reverse-card-is-calm .reverse-card-shadow,
.reverse-card-is-calm .reverse-card-spin { animation: none !important; }
.reverse-card-is-calm .reverse-card-flipper .reverse-card-face-back {
    transform: none;
    opacity: 0;
}
.reverse-card-is-calm .reverse-card-ink-line { clip-path: none; }
.reverse-card-is-calm.reverse-card-is-flipping .reverse-card-flipper .reverse-card-face-back,
.reverse-card-is-calm.reverse-card-is-landed .reverse-card-flipper .reverse-card-face-back {
    opacity: 1;
    transition: opacity var(--reverse-card-lead, 2.33s) var(--ease-silk);
}
/* (the blank face stays opaque underneath, so the card never turns see-through) */

/* ───── The thumb zone: the hint, then < RESTART > ───── */
.reverse-card-controls {
    position: relative;
    z-index: 2;
    flex: 0 0 auto;
    width: 100%;
    height: 56px;
}
.reverse-card-hint,
.reverse-card-restart {
    position: absolute;
    left: 50%;
    top: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    margin: 0;
    padding: 0.55rem 1.35rem 0.6rem;
    border: 0;
    border-radius: 999px;
    background: var(--chip-crimson);
    color: var(--btn-ink-on-chip);
    font-family: var(--font-body);
    font-weight: 700;
    font-size: 1.35rem;
    line-height: 1;
    letter-spacing: var(--label-tracking);
    white-space: nowrap;
    box-shadow: 0 6px 14px rgba(58, 0, 8, 0.35), 0 1px 2px rgba(58, 0, 8, 0.3);
    opacity: 0;
    visibility: hidden;
    transform: translate(-50%, -50%) translateY(6px);
    transition: opacity 0.3s var(--ease-silk), transform 0.3s var(--ease-expo-out), visibility 0s linear 0.3s;
}
.reverse-card-hint { pointer-events: none; }

.reverse-card-is-armed .reverse-card-hint {
    opacity: 1;
    visibility: visible;
    transform: translate(-50%, -50%);
    transition: opacity 0.4s var(--ease-expo-out), transform 0.4s var(--ease-expo-out), visibility 0s;
}
.reverse-card-is-armed.reverse-card-is-flipping .reverse-card-hint,
.reverse-card-is-armed.reverse-card-is-landed .reverse-card-hint {
    opacity: 0;
    visibility: hidden;
    transform: translate(-50%, -50%) translateY(4px);
    transition: opacity 0.25s var(--ease-silk), transform 0.25s var(--ease-silk), visibility 0s linear 0.25s;
}

.reverse-card-restart { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.reverse-card-is-restart .reverse-card-restart {
    opacity: 1;
    visibility: visible;
    transform: translate(-50%, -50%);
    transition: opacity 0.4s var(--ease-expo-out), transform 0.4s var(--ease-expo-out), visibility 0s;
}
.reverse-card-restart:active { transform: translate(-50%, -50%) scale(0.97); transition: transform 80ms var(--ease-snap); }
.reverse-card-restart:focus { outline: none; }
.reverse-card-restart:focus-visible {
    outline: 3px solid var(--focus-ring);
    outline-offset: 4px;
}

/* ───── The rest: the finale has said everything; the loops are parked where they are ───── */
.reverse-card-is-rest .reverse-card-breath,
.reverse-card-is-rest .reverse-card-star {
    animation-play-state: paused;
}

/* Entry states are applied instantly (prepare / goto), never animated. */
.reverse-card-instant,
.reverse-card-instant * {
    transition: none !important;
    animation: none !important;
}

/* ───── Landscape / desktop: the reference's composition ─────
   The portrait card centred (about 52vh tall, 0.69 aspect) with the four
   stars round it, < RESTART > under it. */
@media (orientation: landscape) {
    .reverse-card-card {
        width: 35.9vh;
        width: 35.9svh;
    }
    .reverse-card-star-1 { --reverse-card-sx: 64.5%; --reverse-card-sy: 24%; --reverse-card-ss: 7.5vw; --reverse-card-sr: 8deg; }
    .reverse-card-star-2 { --reverse-card-sx: 20.5%; --reverse-card-sy: 73%; --reverse-card-ss: 5vw; --reverse-card-sr: -8deg; }
    .reverse-card-star-3 { --reverse-card-sx: 15%;   --reverse-card-sy: 93%; --reverse-card-ss: 8vw; --reverse-card-sr: -16deg; }
    .reverse-card-star-4 { --reverse-card-sx: 84.5%; --reverse-card-sy: 89%; --reverse-card-ss: 5.5vw; --reverse-card-sr: 18deg; }
}

/* Short landscape phones: keep the controls clear of the bottom edge. */
@media (orientation: landscape) and (max-height: 480px) {
    .reverse-card-container { padding-top: calc(52px + env(safe-area-inset-top, 0px)); }
    .reverse-card-hint,
    .reverse-card-restart { font-size: 1.15rem; }
}

/* ───── Reduced motion: every beat still plays, calmly ───── */
@media (prefers-reduced-motion: reduce) {
    .reverse-card-is-in .reverse-card-wipe {
        clip-path: none;
        animation: reverse-card-fade-in 0.4s var(--ease-silk) 0.15s both;
    }
    .reverse-card-is-breathing .reverse-card-breath,
    .reverse-card-is-armed .reverse-card-star {
        animation: none;
    }
    .reverse-card-hint,
    .reverse-card-restart,
    .reverse-card-is-armed .reverse-card-hint,
    .reverse-card-is-restart .reverse-card-restart {
        transform: translate(-50%, -50%);
    }
}

@keyframes reverse-card-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}
