/* ═══════════════════════════════════════════
   special-delivery — beat 1 of birthday-scrapbook (5.5 s · tap · no hold: its tap IS begin())

   Ground: data-ground="pink" (the pink watercolour gingham), painted full-bleed
   by .special-delivery-ground. Its gingham tile is centred on the stage
   (background-size = two cells, background-position: center) so caution's
   identical gingham lines up across the cut.

   States are tokens in data-special-delivery-state on the container (not
   classes), set by js/special-delivery.js:
     armed   the first frame: the badge wipes in on (re)display, the tag is
             taped on, next >> waits
     tapped  the payoff (the tap, perf clock): next >> presses and fades, the
             tag flutters off, the tape tail peels and curls (0.2-0.9 s), the
             lid lifts a crack (0.5-1.4 s), a heart peeks out and tucks back
             (0.55-1.35 s)
     rattle  cue 1.4 s: three +-1.5 deg twitches (2.3 s)
     swell   cue 3.7 s: the rattle grows (+-3 deg), the badge inflates 1 -> 1.06
     out     cue 5.2 s: the badge fades out (0.3 s, silk)
   Only transform and opacity animate after the load wipe.

   Layout: phone portrait first (badge min(72vw, 46svh) centred at 44svh, the
   tag under its lower right, next >> 12svh up from the bottom); landscape
   (min-aspect-ratio 4/3) is the reference's composition (badge 44vh centred,
   tag overlapping its lower right, next >> under it). The top ~56 px is left
   to the bridge's progress tape and mute pill.
   ═══════════════════════════════════════════ */

.special-delivery-container {
    /* Geometry (phone portrait first) */
    --special-delivery-b: min(72vw, 46vh);
    --special-delivery-cy: 44vh;
    --special-delivery-next-bottom: 12vh;
    --special-delivery-tag-top: calc(var(--special-delivery-cy) + var(--special-delivery-b) * 0.41);
    --special-delivery-tag-right: calc(50% - var(--special-delivery-b) * 0.54);
    --special-delivery-tag-w: min(84vw, 22rem);

    /* The badge's own inks (concept.md Art inventory), as rgba tints */
    --special-delivery-parcel: rgba(246, 198, 207, 1);
    --special-delivery-parcel-line: rgba(236, 154, 171, 1);
    --special-delivery-letter-top: rgba(232, 154, 171, 1);
    --special-delivery-letter-bottom: rgba(244, 188, 201, 1);
    --special-delivery-field: rgba(251, 246, 241, 1);

    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
    font-family: var(--font-body);
    color: var(--text-primary);
    -webkit-user-select: none;
    user-select: none;
}

@supports (height: 1svh) {
    .special-delivery-container {
        --special-delivery-b: min(72vw, 46svh);
        --special-delivery-cy: 44svh;
        --special-delivery-next-bottom: 12svh;
    }
}

/* ───── The ground: pink watercolour gingham, full-bleed ─────
   Over-sized by 12% each side and set back (translateZ -120px), so neither a
   camera push nor the depth ever shows an edge. The watercolour mottle is a
   feTurbulence tile rasterised once and multiplied over the bands. */
.special-delivery-ground {
    position: absolute;
    inset: -12%;
    /* the shorthand: the token ends in its base colour, which only `background` accepts */
    background:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='640' height='640'%3E%3Cfilter id='w' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.006' numOctaves='3' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.86 0 0 0 0 0.42 0 0 0 0 0.55 0 0 0 1.25 -0.5'/%3E%3C/filter%3E%3Crect width='640' height='640' filter='url(%23w)'/%3E%3C/svg%3E"),
        var(--ground-gingham-pink);
    background-size:
        640px 640px,
        calc(var(--gingham-cell) * 2) calc(var(--gingham-cell) * 2),
        calc(var(--gingham-cell) * 2) calc(var(--gingham-cell) * 2);
    background-position: center;
    background-repeat: repeat;
    background-blend-mode: multiply, normal, normal;
    transform: translateZ(-120px);
    pointer-events: none;
}

/* ───── The parcel: the badge and its tag, on a near plane ───── */
.special-delivery-parcel {
    position: absolute;
    inset: 0;
    transform: translateZ(40px);
    pointer-events: none;
}

.special-delivery-badge {
    position: absolute;
    left: calc(50% - var(--special-delivery-b) / 2);
    top: calc(var(--special-delivery-cy) - var(--special-delivery-b) / 2);
    width: var(--special-delivery-b);
    height: var(--special-delivery-b);
    /* the reference's left-to-right wipe, on load and on every re-display (restart) */
    animation: special-delivery-wipe var(--dur-wipe) var(--ease-expo-out) backwards;
}

.special-delivery-exit,
.special-delivery-inflate,
.special-delivery-rattle {
    width: 100%;
    height: 100%;
}

.special-delivery-exit {
    transition: opacity 300ms var(--ease-silk);
}

.special-delivery-inflate {
    transition: transform 1500ms var(--ease-expo-out);
}

.special-delivery-rattle {
    border-radius: 50%;
    box-shadow: var(--sticker-shadow);
    transform-origin: 50% 56%;
    will-change: transform;
}

.special-delivery-art {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

/* ───── The badge artwork (inline SVG, styled by class) ───── */
.special-delivery-disc { fill: var(--sticker-border); }

.special-delivery-ring {
    fill: var(--special-delivery-field);
    stroke: var(--text-primary);
    stroke-width: 9;
}

/* Pink letters with a dark ink outline, as the reference: the stroke is painted
   under the fill (paint-order: stroke), so half of it shows outside each glyph.
   4.6 viewBox units = a visible 2.3-unit outline, about 1.5-2 px at the badge's
   rendered size (259-338 px across), scaling with it. Ink on the cream field is
   the edge that reads (>= 3:1 as large text); the pink is the fill inside it. */
.special-delivery-lettering {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 43px;
    stroke: var(--text-primary);
    stroke-width: 4.6;
    stroke-linejoin: round;
    paint-order: stroke;
}

.special-delivery-lettering-top { fill: var(--special-delivery-letter-top); }

.special-delivery-lettering-bottom { fill: var(--special-delivery-letter-bottom); }

.special-delivery-flower { fill: var(--text-primary); }
.special-delivery-flower-eye { fill: var(--special-delivery-field); }

.special-delivery-outline,
.special-delivery-outline-thin {
    stroke: var(--text-primary);
    stroke-linejoin: round;
    stroke-linecap: round;
}
.special-delivery-outline { stroke-width: 3; }
.special-delivery-outline-thin { stroke-width: 2; }

.special-delivery-face { fill: var(--special-delivery-parcel); }
.special-delivery-face-left { fill: url(#special-delivery-hatch); }
.special-delivery-hatch-ground { fill: var(--special-delivery-parcel); }
.special-delivery-hatch-line { fill: var(--special-delivery-parcel-line); }
.special-delivery-label { fill: var(--sticker-border); }
.special-delivery-mark,
.special-delivery-tape,
.special-delivery-inside { fill: var(--text-primary); }

.special-delivery-heart-body {
    fill: var(--sticker-pink-light);
    stroke: var(--text-primary);
    stroke-width: 2.5;
    stroke-linejoin: round;
}
.special-delivery-heart-glint { fill: var(--spark); }

.special-delivery-heart {
    transform-box: fill-box;
    transform-origin: 50% 100%;
}

.special-delivery-lid {
    transform-box: view-box;
    transform-origin: 120px 154px;   /* the box's left corner: the lid lifts at the front */
}

.special-delivery-tail {
    transform-box: view-box;
    transform-origin: 160px 177px;   /* where the tape crosses the lid's front-left edge */
}

/* The pre-drawn curled tail: only the reduced-motion cross-fade shows it. */
.special-delivery-tail-curled { opacity: 0; }

/* ───── The name tag: "for {toName}", taped to the badge's lower right ───── */
.special-delivery-tagbox {
    position: absolute;
    top: var(--special-delivery-tag-top);
    right: max(4vw, var(--special-delivery-tag-right));
    width: var(--special-delivery-tag-w);
    display: flex;
    justify-content: flex-end;
    pointer-events: none;
}

.special-delivery-tag {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    max-width: 100%;
    margin: 0;
    padding: 0.7rem 1.05rem 0.6rem 1.75rem;
    box-sizing: border-box;
    background: var(--sticker-border);
    color: var(--ink);
    border-radius: 0.45rem 0.75rem 0.75rem 0.45rem;
    box-shadow: var(--sticker-shadow);
    transform: rotate(-4deg);
    transform-origin: 60% 0;
    animation: special-delivery-tag-on 350ms var(--ease-expo-out) 300ms backwards;
}

/* the punched hole */
.special-delivery-tag::before {
    content: '';
    position: absolute;
    left: 0.6rem;
    top: 50%;
    width: 0.5rem;
    height: 0.5rem;
    margin-top: -0.25rem;
    border-radius: 50%;
    background: var(--bg-elevated);
    box-shadow: inset 0 1px 2px rgba(70, 6, 24, 0.35);
}

/* the washi strip across its top */
.special-delivery-tag::after {
    content: '';
    position: absolute;
    top: -0.6rem;
    left: 34%;
    width: 3.6rem;
    height: 1.15rem;
    background: var(--washi);
    opacity: 0.88;
    border-left: 1px dashed var(--washi-edge);
    border-right: 1px dashed var(--washi-edge);
    transform: rotate(5deg);
    clip-path: polygon(0 8%, 6% 0, 12% 10%, 18% 0, 82% 0, 88% 10%, 94% 0, 100% 8%, 100% 92%, 94% 100%, 88% 90%, 82% 100%, 18% 100%, 12% 90%, 6% 100%, 0 92%);
}

.special-delivery-tag-for {
    flex: none;
    font-weight: 400;
    font-size: 1.05rem;
    line-height: 1;
    letter-spacing: var(--body-tracking);
    color: var(--ink-soft);
}

/* font-size / letter-spacing are fitted by window.setTagName (1.8rem -> 1.1rem floor) */
.special-delivery-tag-name {
    display: block;
    min-width: 0;
    font-weight: 700;
    font-size: 1.8rem;
    line-height: 1.04;
    letter-spacing: 0.02em;
    white-space: nowrap;
    color: var(--ink);
    text-align: left;
}

.special-delivery-tag-line { display: block; }

/* ───── next >>: the one control (its tap is begin()) ───── */
.special-delivery-next {
    position: absolute;
    left: 0;
    right: 0;
    bottom: var(--special-delivery-next-bottom);
    width: max-content;
    min-width: 7.5rem;
    min-height: 48px;
    margin: 0 auto;
    padding: 0.35rem 1.1rem;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--btn-ink);
    font-family: var(--font-body);
    font-weight: 700;
    font-size: 1.35rem;
    line-height: 1;
    letter-spacing: var(--label-tracking);
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transform: translateZ(60px);
}

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

.special-delivery-next:disabled { cursor: default; }

/* ═══════════ The payoff and the cues ═══════════ */

/* tapped (the tap itself, perf clock) */
.special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-next {
    pointer-events: none;
    animation: special-delivery-press 360ms var(--ease-snap) forwards;
}

.special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-tag {
    animation: special-delivery-tag-off 500ms var(--ease-expo-out) forwards;
}

.special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-tail {
    animation: special-delivery-tail-peel 700ms var(--ease-expo-out) 200ms both;
}

.special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-lid {
    animation: special-delivery-lid-lift 900ms var(--ease-breath) 500ms both;
}

.special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-heart {
    animation: special-delivery-peek 800ms var(--ease-expo-out) 550ms both;
}

/* rattle (cue 1.4 s): three twitches, 1.4-3.7 s */
.special-delivery-container[data-special-delivery-state~="rattle"] .special-delivery-rattle {
    animation: special-delivery-twitch 767ms var(--ease-breath) 3;
}

/* swell (cue 3.7 s): the rattle grows and the badge inflates, 3.7-5.2 s */
.special-delivery-container[data-special-delivery-state~="swell"] .special-delivery-rattle {
    animation: special-delivery-shudder 375ms var(--ease-breath) infinite;
}

.special-delivery-container[data-special-delivery-state~="swell"] .special-delivery-inflate {
    transform: scale(1.06);
}

/* out (cue 5.2 s): the badge fades over the same gingham */
.special-delivery-container[data-special-delivery-state~="out"] .special-delivery-exit {
    opacity: 0;
}

/* ═══════════ Landscape / desktop: the reference's composition ═══════════ */
@media (min-aspect-ratio: 4/3) {
    .special-delivery-container {
        --special-delivery-b: 44vh;
        --special-delivery-cy: 53vh;
        --special-delivery-tag-top: calc(var(--special-delivery-cy) + var(--special-delivery-b) * 0.24);
        --special-delivery-tag-right: calc(50% - var(--special-delivery-b) * 0.7);
        --special-delivery-tag-w: min(46vw, 26rem);
    }

    .special-delivery-next {
        bottom: auto;
        top: calc(var(--special-delivery-cy) + var(--special-delivery-b) / 2 + 3vh);
    }
}

@supports (height: 1svh) {
    @media (min-aspect-ratio: 4/3) {
        .special-delivery-container {
            --special-delivery-b: 44svh;
            --special-delivery-cy: 53svh;
        }

        .special-delivery-next {
            top: calc(var(--special-delivery-cy) + var(--special-delivery-b) / 2 + 3svh);
        }
    }
}

/* ═══════════ Reduced motion: every beat still plays, calmly ═══════════
   The badge and tag fade instead of wiping and fluttering; the tape peel and
   the lid are cross-fades (the curled tail fades in, the heart fades in and
   out at its peek); no rattle and no inflate; the exit fade is unchanged. */
@media (prefers-reduced-motion: reduce) {
    .special-delivery-badge {
        animation: special-delivery-fade-in var(--dur-wipe) var(--ease-silk) backwards;
    }

    .special-delivery-tag {
        animation: special-delivery-fade-in 350ms var(--ease-silk) 300ms backwards;
    }

    .special-delivery-heart {
        opacity: 0;
        transform: translateY(-46px);
    }

    .special-delivery-inflate { transition: none; }

    .special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-next {
        animation: special-delivery-fade-out 300ms var(--ease-silk) forwards;
    }

    .special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-tag {
        animation: special-delivery-fade-out 400ms var(--ease-silk) forwards;
    }

    .special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-tail {
        animation: special-delivery-fade-out 500ms var(--ease-silk) 200ms both;
    }

    .special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-tail-curled {
        animation: special-delivery-fade-in 500ms var(--ease-silk) 200ms both;
    }

    .special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-lid {
        animation: none;
    }

    .special-delivery-container[data-special-delivery-state~="tapped"] .special-delivery-heart {
        animation: special-delivery-blink 1000ms var(--ease-silk) 400ms both;
    }

    .special-delivery-container[data-special-delivery-state~="rattle"] .special-delivery-rattle,
    .special-delivery-container[data-special-delivery-state~="swell"] .special-delivery-rattle {
        animation: none;
    }

    .special-delivery-container[data-special-delivery-state~="swell"] .special-delivery-inflate {
        transform: none;
    }
}

/* ═══════════ Keyframes (prefixed: one namespace across the template) ═══════════ */
@keyframes special-delivery-wipe {
    from { clip-path: inset(-12% 112% -12% -12%); }
    to { clip-path: inset(-12% -12% -12% -12%); }
}

@keyframes special-delivery-tag-on {
    from { opacity: 0; transform: translateY(-10px) rotate(2deg) scale(1.08); }
    to { opacity: 1; transform: rotate(-4deg); }
}

@keyframes special-delivery-tag-off {
    0% { opacity: 1; transform: rotate(-4deg); }
    22% { opacity: 1; transform: translate(4px, -14px) rotate(4deg); }
    100% { opacity: 0; transform: translate(46px, -170px) rotate(26deg); }
}

@keyframes special-delivery-press {
    0% { opacity: 1; transform: translateZ(60px) scale(1); }
    22% { opacity: 1; transform: translateZ(60px) scale(0.92); }
    45% { opacity: 1; transform: translateZ(60px) scale(1); }
    100% { opacity: 0; transform: translateZ(60px) translateY(6px); }
}

@keyframes special-delivery-tail-peel {
    0% { transform: none; }
    65% { transform: rotate(-7deg) scaleY(-0.62); }
    100% { transform: rotate(-4deg) scaleY(-0.5); }
}

@keyframes special-delivery-lid-lift {
    0% { transform: none; }
    22% { transform: translateY(-8px) rotate(-2.5deg); }
    50% { transform: translateY(-6px) rotate(-1.5deg); }
    78% { transform: translateY(-8px) rotate(-2.5deg); }
    100% { transform: none; }
}

@keyframes special-delivery-peek {
    0% { transform: translateY(0); }
    32% { transform: translateY(-48px) rotate(-6deg); }
    52% { transform: translateY(-44px) rotate(6deg); }
    70% { transform: translateY(-47px) rotate(-3deg); }
    100% { transform: translateY(0); }
}

@keyframes special-delivery-twitch {
    0% { transform: rotate(0deg); }
    10% { transform: rotate(-1.5deg); }
    20% { transform: rotate(1.5deg); }
    30% { transform: rotate(-1deg); }
    40% { transform: rotate(0.6deg); }
    50%, 100% { transform: rotate(0deg); }
}

@keyframes special-delivery-shudder {
    0% { transform: rotate(0deg) translateX(0); }
    25% { transform: rotate(-3deg) translateX(-2px); }
    50% { transform: rotate(0.5deg) translateX(0); }
    75% { transform: rotate(3deg) translateX(2px); }
    100% { transform: rotate(0deg) translateX(0); }
}

@keyframes special-delivery-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

@keyframes special-delivery-fade-out {
    from { opacity: 1; }
    to { opacity: 0; }
}

@keyframes special-delivery-blink {
    0% { opacity: 0; }
    30%, 70% { opacity: 1; }
    100% { opacity: 0; }
}
