/* ==========================================================================
   Intro — a fixed stage that owns the whole viewport. The page does not
   scroll while it runs; a scroll gesture, click, tap or key advances to the
   next clip instead.

   Only shown when the inline head script has flagged JS support, so a visitor
   without JavaScript goes straight to the content and is never stuck behind a
   stage that can't advance.
   ========================================================================== */

.intro {
    display: none;
}

.js .intro {
    /* Single source for the stage footprint: the caption plates anchor to it so
       they hug the artwork instead of drifting off to the viewport edges. */
    --stage-size: min(86vw, 68svh, 620px);
    --stage-gap: clamp(var(--space-4), 3vw, var(--space-7));

    position: fixed;
    inset: 0;
    z-index: 100;
    display: grid;
    place-items: center;
    background: var(--paper);
    transition: opacity var(--duration-slow) var(--ease-out);
}

.js .intro[hidden] {
    display: none;
}

.js .intro.is-done {
    opacity: 0;
    pointer-events: none;
}

/* ---------- stage ---------- */

.intro__stage {
    position: relative;
    z-index: 2;
    width: var(--stage-size);
    aspect-ratio: 1 / 1;
}

/* Clips are stacked in playback order, so the incoming one always paints over
   the outgoing one. Consecutive clips share an identical boundary frame, which
   is what makes the swap invisible.

   The brightness filter lifts each clip's near-white backdrop to pure white so
   it merges into the page and the video's rectangle disappears completely. It
   costs nothing at runtime — the compositor applies it on the GPU. */
.intro__clip {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0;
    visibility: hidden;
    filter: brightness(var(--intro-white-point));
}

.intro__clip.is-visible {
    opacity: 1;
    visibility: visible;
}

/* ---------- captions ----------
   Plates that slide out from behind the stage once a clip settles on its last
   frame. They sit below the stage in the stacking order, so the clip's own
   opaque white backdrop hides them until they clear its edge — that is what
   makes them read as emerging from under the artwork.

   On desktop they accumulate: each new pair joins the ones already up, and the
   earlier plates slide to new heights and angles to make room, so the stage
   fills out as the sequence goes on. Narrow screens have no room for a stack,
   so there only the current pair is shown, above and below the artwork. */

.intro__captions {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
}

.intro__caption {
    --angle: 0deg;
    --y: 0px;
    --from: 0px;
    --delay: 0ms;

    position: absolute;
    top: 50%;
    width: clamp(15rem, 24vw, 21rem);
    margin: 0;
    padding: clamp(var(--space-4), 1.6vw, var(--space-6));
    border: 1px solid rgb(4 4 7 / 0.05);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    /* Deliberately short-reach. The plates sit below the stage in the stacking
       order, so any shadow that spills as far as the clip gets cut off by its
       opaque white — which draws the video's rectangle back onto the page. */
    box-shadow:
        0 1px 0 rgb(255 255 255 / 0.9) inset,
        0 10px 22px -14px rgb(4 4 7 / 0.3),
        0 2px 6px -3px rgb(4 4 7 / 0.12);
    font-size: clamp(0.95rem, 0.86rem + 0.45vw, 1.15rem);
    font-weight: var(--weight-medium);
    line-height: var(--leading-snug);
    letter-spacing: -0.01em;
    text-align: left;
    text-wrap: balance;
    color: var(--color-text);
    opacity: 0;
    transform: translate(var(--from), calc(-50% + var(--y))) rotate(0deg) scale(0.94);
    transition:
        opacity var(--duration-base) var(--ease-out),
        transform var(--duration-slow) var(--ease-out);
    transition-delay: var(--delay);
}

/* Later plates land a beat after the ones already up have shifted aside. */
.intro__caption[data-caption="2"] { --delay: 90ms; }
.intro__caption[data-caption="3"] { --delay: 180ms; }
.intro__caption--right { --delay: 70ms; }
.intro__caption--right[data-caption="2"] { --delay: 160ms; }
.intro__caption--right[data-caption="3"] { --delay: 250ms; }

/* A short pink kicker rule above the text. Reads the same whichever side the
   plate is on, unlike an edge bar, which left one flank looking unfinished. */
.intro__caption::before {
    content: "";
    display: block;
    width: 2.25rem;
    height: 3px;
    margin-bottom: var(--space-3);
    border-radius: var(--radius-pill);
    background: linear-gradient(90deg, var(--brand-500), var(--brand-300));
}

/* ---- wide: a column of plates either side of the stage, accumulating ---- */

@media (min-width: 62rem) {
    /* The stage gives up some size so the plates have real room beside it
       rather than crowding the artwork. */
    .js .intro {
        --stage-size: min(42vw, 62svh, 520px);
    }

    .intro__caption--left {
        right: calc(50% + var(--stage-size) / 2 + var(--stage-gap));
        --from: 4rem;
    }

    .intro__caption--right {
        left: calc(50% + var(--stage-size) / 2 + var(--stage-gap));
        --from: -4rem;
    }

    .intro__captions[data-step="1"] .intro__caption[data-caption="1"],
    .intro__captions[data-step="2"] .intro__caption[data-caption="1"],
    .intro__captions[data-step="2"] .intro__caption[data-caption="2"],
    .intro__captions[data-step="3"] .intro__caption[data-caption="1"],
    .intro__captions[data-step="3"] .intro__caption[data-caption="2"],
    .intro__captions[data-step="3"] .intro__caption[data-caption="3"] {
        opacity: 1;
        transform: translate(0, calc(-50% + var(--y))) rotate(var(--angle)) scale(1);
    }

    /* One plate: centred on the stage. */
    .intro__captions[data-step="1"] .intro__caption--left[data-caption="1"] { --y: -1rem; --angle: -6deg; }
    .intro__captions[data-step="1"] .intro__caption--right[data-caption="1"] { --y: 1.5rem; --angle: 5deg; }

    /* Two plates: the first slides up, the newcomer takes the lower slot. */
    .intro__captions[data-step="2"] .intro__caption--left[data-caption="1"] { --y: -6rem; --angle: -5deg; }
    .intro__captions[data-step="2"] .intro__caption--left[data-caption="2"] { --y: 4.5rem; --angle: 4deg; }
    .intro__captions[data-step="2"] .intro__caption--right[data-caption="1"] { --y: -5rem; --angle: 6deg; }
    .intro__captions[data-step="2"] .intro__caption--right[data-caption="2"] { --y: 5.5rem; --angle: -5deg; }

    /* Three plates: the stack spreads out around the stage. */
    .intro__captions[data-step="3"] .intro__caption--left[data-caption="1"] { --y: -11rem; --angle: -6deg; }
    .intro__captions[data-step="3"] .intro__caption--left[data-caption="2"] { --y: -0.5rem; --angle: 3deg; }
    .intro__captions[data-step="3"] .intro__caption--left[data-caption="3"] { --y: 10rem; --angle: -4deg; }
    .intro__captions[data-step="3"] .intro__caption--right[data-caption="1"] { --y: -10.5rem; --angle: 5deg; }
    .intro__captions[data-step="3"] .intro__caption--right[data-caption="2"] { --y: 0.5rem; --angle: -4deg; }
    .intro__captions[data-step="3"] .intro__caption--right[data-caption="3"] { --y: 11rem; --angle: 6deg; }
}

/* ---- narrow: no room for a stack, so only the current pair, above and
        below the artwork ---- */

@media (max-width: 61.99rem) {
    /* A smaller stage buys the room the plates need above and below it. Pinning
       them to the viewport edges instead let them ride onto the clip on short
       screens, and a plate's shadow landing on the clip is exactly what makes
       the video's rectangle visible again. */
    .js .intro {
        --stage-size: min(78vw, 42svh, 620px);
        --stage-gap: clamp(var(--space-4), 4vh, var(--space-6));
    }

    /* Above the stage here, unlike the wide layout: the plates approach the clip
       closely enough that a stray overlap is possible, and a plate covering a
       sliver of artwork reads far better than a shadow cut off mid-page. */
    .intro__captions {
        z-index: 3;
    }

    .intro__caption,
    .intro__caption--left,
    .intro__caption--right {
        top: auto;
        bottom: auto;
        left: 50%;
        right: auto;
        width: min(76vw, 20rem);
        --from: 0px;
    }

    .intro__caption--left {
        bottom: calc(50% + var(--stage-size) / 2 + var(--stage-gap));
        transform: translate(-50%, -2rem) rotate(0deg) scale(0.94);
    }

    .intro__caption--right {
        top: calc(50% + var(--stage-size) / 2 + var(--stage-gap));
        transform: translate(-50%, 2rem) rotate(0deg) scale(0.94);
    }

    .intro__captions[data-step="1"] .intro__caption[data-caption="1"],
    .intro__captions[data-step="2"] .intro__caption[data-caption="2"],
    .intro__captions[data-step="3"] .intro__caption[data-caption="3"] {
        opacity: 1;
        transform: translate(-50%, 0) rotate(var(--angle)) scale(1);
    }

    .intro__captions[data-step="1"] .intro__caption--left { --angle: -3deg; }
    .intro__captions[data-step="1"] .intro__caption--right { --angle: 2.5deg; }
    .intro__captions[data-step="2"] .intro__caption--left { --angle: 2.5deg; }
    .intro__captions[data-step="2"] .intro__caption--right { --angle: -3deg; }
    .intro__captions[data-step="3"] .intro__caption--left { --angle: -2deg; }
    .intro__captions[data-step="3"] .intro__caption--right { --angle: 3deg; }
}

/* ---------- progress ----------
   Segments lying back in perspective, each one a groove carved into the page
   with a lit pink fill riding inside it. The fill tracks the clip's own
   playback, so the bar doubles as the player scrubber; the segment in play
   widens and breathes so the stage never looks frozen while it waits. */

.intro__progress {
    position: absolute;
    z-index: 3;
    bottom: clamp(var(--space-5), 5vh, var(--space-7));
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: clamp(var(--space-2), 1vw, var(--space-3));
    perspective: 520px;
    pointer-events: none;
}

.intro__bar {
    --fill: 0%;

    position: relative;
    width: clamp(1.9rem, 4vw, 2.5rem);
    height: 0.6rem;
    border-radius: var(--radius-pill);
    background: linear-gradient(180deg, var(--ink-200), var(--ink-100));
    box-shadow:
        0 2px 3px rgb(4 4 7 / 0.16) inset,
        0 -1px 0 rgb(255 255 255 / 0.9) inset,
        0 5px 12px -6px rgb(4 4 7 / 0.4);
    transform: rotateX(48deg);
    overflow: hidden;
    transition:
        width var(--duration-base) var(--ease-out),
        box-shadow var(--duration-base) var(--ease-out);
}

.intro__bar::after {
    content: "";
    position: absolute;
    inset: 0;
    width: var(--fill);
    border-radius: inherit;
    background: linear-gradient(180deg, var(--brand-300), var(--brand-500) 55%, var(--brand-700));
    box-shadow:
        0 1px 0 rgb(255 255 255 / 0.55) inset,
        0 -1px 2px rgb(4 4 7 / 0.25) inset;
}

/* The segment in play is longer and sits proud of the others. */
.intro__bar.is-current {
    width: clamp(3.25rem, 7vw, 4.5rem);
    box-shadow:
        0 2px 3px rgb(4 4 7 / 0.16) inset,
        0 -1px 0 rgb(255 255 255 / 0.9) inset,
        0 8px 18px -7px rgb(252 58 114 / 0.55);
}

.intro__bar.is-current::after {
    animation: fill-breath 2.6s var(--ease-out) infinite;
}

@keyframes fill-breath {
    0%, 100% {
        filter: brightness(1) saturate(1);
    }
    50% {
        filter: brightness(1.12) saturate(1.15);
    }
}

/* ---------- skip ---------- */

.intro__skip {
    position: absolute;
    z-index: 3;
    top: clamp(var(--space-4), 3vh, var(--space-5));
    right: clamp(var(--space-4), 3vw, var(--space-6));
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: 50%;
    background: var(--color-surface);
    color: var(--ink-400);
    cursor: pointer;
    box-shadow:
        0 1px 0 rgb(255 255 255 / 0.9) inset,
        0 8px 18px -10px rgb(4 4 7 / 0.35);
    transition:
        color var(--duration-fast) var(--ease-out),
        border-color var(--duration-fast) var(--ease-out),
        transform var(--duration-fast) var(--ease-out);
}

.intro__skip svg {
    width: 1.05rem;
    height: 1.05rem;
}

.intro__skip:hover,
.intro__skip:focus-visible {
    color: var(--color-accent);
    border-color: var(--color-accent);
    transform: translateX(2px);
}

.intro__skip:active {
    transform: translateX(3px);
}

/* ---------- page reveal ---------- */

/* Held back only while the stage is up, so the content is in the DOM and
   visible to crawlers from the first byte. */
.js .page {
    opacity: 0;
}

.js .page.is-revealed {
    opacity: 1;
    transition: opacity var(--duration-slow) var(--ease-out);
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
    .js .intro {
        display: none;
    }

    .js .page,
    .js .page.is-revealed {
        opacity: 1;
        transition: none;
    }

    .intro__bar.is-current::after {
        animation: none;
    }
}
