/* ═══════════════════════════════════════════
   name-in-lights — the wow beat
   The name gathers out of the ember's burst (ReveelHero.nameAssemble on the
   light canvas), stands in its halo, then rises to the zenith as the film's
   masthead of light while the starfield ignites in three depth layers.

   Two pieces outlive this beat and are moved out of the section at boot:
     .name-in-lights-masthead -> #stage (screen space, over the world, under
                                 the light canvas): the name, fitted once.
     .name-in-lights-hint     -> #stage (screen space): the control layer, so
                                 "Tap to look back" never moves once shown
                                 (the badge guard lifts only over stationary
                                 controls; the world rides every camera move).
     .name-in-lights-sky      -> #world (camera space, three depth planes):
                                 the starfield, so every later camera move
                                 has parallax.
   Their pose in later beats is keyed off which beat is active (:has), so a
   goto() finds them where the natural flow would have left them.

   Persistent states are data-* attributes (set by the JS) and the decorative
   reveals are Web Animations started from cues: the badge guard re-measures
   (a forced layout) on every class/style mutation and every transition or
   CSS animation event, so this beat keeps those to the one control. The
   rules here are the resting states those animations start from.
   ═══════════════════════════════════════════ */

/* ───── The beat's own layer (inside the section, in the world) ───── */
.name-in-lights-container {
    position: absolute;
    inset: 0;
    pointer-events: none;
    --name-in-lights-block-h: 7rem;           /* the fitted name's height, set by JS */
}

/* The conic spotlight from above: fades up with the name, falls away as it rises. */
.name-in-lights-spot {
    position: absolute;
    inset: -12% -10% 0;
    background:
        conic-gradient(from 180deg at 50% -6%,
            transparent 161deg,
            rgba(196, 138, 96, 0.06) 170deg,
            rgba(242, 196, 160, 0.14) 180deg,
            rgba(196, 138, 96, 0.06) 190deg,
            transparent 199deg);
    opacity: 0;
}

/* ───── The masthead: the name, in screen space ───── */
.name-in-lights-masthead {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 1;                                /* over the world, under the light canvas */
    pointer-events: none;
    opacity: 0;
    transform: none;
    transform-origin: 50% 40%;                 /* the name's centre: every pose scales about it */
    transition: opacity 0.9s var(--ease-silk), transform 4.6s var(--ease-stage);

    /* Poses, in the masthead's own % (it is the stage's size, so % is stage-relative). */
    --name-in-lights-zenith: translate3d(0, -28%, 0) scale(0.42);   /* centre at 12% */
    --name-in-lights-upper: translate3d(0, -20%, 0) scale(0.56);    /* cap-toss: centre at 20% */
    --name-in-lights-settle: translate3d(0, -15%, 0) scale(0.64);   /* finale: centre at 25% */
    --name-in-lights-halo-w: 22rem;
    --name-in-lights-halo-h: 22rem;
}
/* Live from the beat's entrance (its bloom and halo show before the name):
   at once, so no transitionend wakes the badge guard. */
.name-in-lights-masthead[data-name-in-lights-live],
.name-in-lights-masthead[data-name-in-lights-lit] {
    opacity: 1;
    transition: opacity 0s, transform 4.6s var(--ease-stage);
}
.name-in-lights-masthead[data-name-in-lights-risen] { transform: var(--name-in-lights-zenith); }

/* 80% tall, content centred: the name's centre sits at 40% of the stage. No
   transform on the way to the lines, so film.box() reads their true box. */
.name-in-lights-frame {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 80%;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The bloom: warm light growing from the ember point while the particles
   scatter and regroup (0.3-3.9 s), so the frame always has a centre; it
   settles to a low glow under the name. Drawn by a Web Animation. */
.name-in-lights-bloom {
    position: absolute;
    left: 50%;
    top: 50%;
    width: calc(var(--name-in-lights-halo-w) * 0.62);
    height: calc(var(--name-in-lights-halo-h) * 0.62);
    transform: translate(-50%, -50%) scale(0.12);
    border-radius: 50%;
    background: radial-gradient(closest-side,
        rgba(242, 196, 160, 0.5) 0%,
        rgba(232, 168, 124, 0.32) 24%,
        rgba(232, 168, 124, 0.16) 52%,
        transparent 100%);
    opacity: 0;
}

/* The halo: a wide, soft glow with a faint ring of light inside it -- no hard
   edge, so it never reads as a badge. Round for a short name; an ellipse
   that follows the line for a long one. Draws in from 1.2 s. */
.name-in-lights-halo {
    position: absolute;
    left: 50%;
    top: 50%;
    width: var(--name-in-lights-halo-w);
    height: var(--name-in-lights-halo-h);
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background:
        radial-gradient(closest-side,
            transparent 44%,
            rgba(242, 196, 160, 0.075) 54%,
            transparent 66%),
        radial-gradient(closest-side,
            var(--halo) 0%,
            var(--halo-far) 46%,
            transparent 100%);
    opacity: 0;
}
.name-in-lights-masthead[data-name-in-lights-lit] .name-in-lights-halo { opacity: 1; }

.name-in-lights-name {
    position: relative;
    margin: 0;
    text-align: center;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--text-primary);
    text-shadow: var(--name-shadow);
    opacity: 0;                                /* revealed at 3.1 s by a Web Animation */
    transition: text-shadow 1.6s var(--ease-silk);
}
/* The settled glow, for the finale's payoff: toggle .name-in-lights-settled
   on #name-in-lights-name (it eases in; a flare over it returns to it). */
.name-in-lights-name.name-in-lights-settled { text-shadow: var(--name-shadow-settled); }
.name-in-lights-masthead[data-name-in-lights-lit] .name-in-lights-name { opacity: 1; }

.name-in-lights-line {
    display: block;
    white-space: nowrap;
    line-height: 1.04;
    font-size: clamp(2rem, 19vw, 7.5rem);      /* before the fit lands */
}
.name-in-lights-line-rest {
    position: relative;
    margin-top: 0.08em;
    line-height: 1.1;
    font-size: clamp(1.3rem, 10vw, 4.2rem);
}
.name-in-lights-line-rest[hidden] { display: none; }

/* Line 2's light sweep: a glint clipped to the glyphs (a box sweep would read
   as a bar across bare text on the night sky). A copy of the text laid over
   it; a Web Animation moves its gradient at 3.1 s. */
/* Its text is generated (attr), so the copy never joins the name's textContent. */
.name-in-lights-sheen::before { content: attr(data-text); }
.name-in-lights-sheen {
    position: absolute;
    inset: 0;
    color: transparent;
    text-shadow: none;
    background: linear-gradient(100deg,
        transparent 38%,
        rgba(250, 240, 230, 0.95) 50%,
        transparent 62%);
    background-size: 280% 100%;
    background-position: 140% 0;
    -webkit-background-clip: text;
    background-clip: text;
    opacity: 0;
    pointer-events: none;
}

/* The flare, for other beats (the tap's own flare is a Web Animation):
   re-flare by removing and re-adding .name-in-lights-flare. */
.name-in-lights-name.name-in-lights-flare {
    animation: name-in-lights-flare 1.6s var(--ease-silk);
}

/* ───── The masthead in the beats that follow ─────
   the-years, years-in-order: risen at the zenith (already there on the
   natural flow, so the move is instant; it only shows on a goto).
   the-letter: out of the way of the letter, the film's quiet centre.
   cap-toss: descends to the upper third. finale: glides a little lower. */
.reveel-stage:has(#screen-the-years.active) > .name-in-lights-masthead,
.reveel-stage:has(#screen-years-in-order.active) > .name-in-lights-masthead {
    opacity: 1;
    transform: var(--name-in-lights-zenith);
    transition: opacity 0.9s var(--ease-silk), transform 0s;
}
.reveel-stage:has(#screen-the-letter.active) > .name-in-lights-masthead {
    opacity: 0;
    transform: var(--name-in-lights-zenith);
    transition: opacity 1.4s var(--ease-silk), transform 0s;
}
.reveel-stage:has(#screen-cap-toss.active) > .name-in-lights-masthead {
    opacity: 1;
    transform: var(--name-in-lights-upper);
    transition: opacity 1.2s var(--ease-silk), transform 2.4s var(--ease-stage);
}
.reveel-stage:has(#screen-finale.active) > .name-in-lights-masthead {
    opacity: 1;
    transform: var(--name-in-lights-settle);
    transition: opacity 1.2s var(--ease-silk), transform 2.4s var(--ease-stage);
}
.reveel-stage:has(#screen-the-years.active) > .name-in-lights-masthead .name-in-lights-name,
.reveel-stage:has(#screen-years-in-order.active) > .name-in-lights-masthead .name-in-lights-name,
.reveel-stage:has(#screen-the-letter.active) > .name-in-lights-masthead .name-in-lights-name,
.reveel-stage:has(#screen-cap-toss.active) > .name-in-lights-masthead .name-in-lights-name,
.reveel-stage:has(#screen-finale.active) > .name-in-lights-masthead .name-in-lights-name,
.reveel-stage:has(#screen-the-years.active) > .name-in-lights-masthead .name-in-lights-halo,
.reveel-stage:has(#screen-years-in-order.active) > .name-in-lights-masthead .name-in-lights-halo,
.reveel-stage:has(#screen-the-letter.active) > .name-in-lights-masthead .name-in-lights-halo,
.reveel-stage:has(#screen-cap-toss.active) > .name-in-lights-masthead .name-in-lights-halo,
.reveel-stage:has(#screen-finale.active) > .name-in-lights-masthead .name-in-lights-halo {
    opacity: 1;
}

/* ───── Titles around the name (world, mid plane) ─────
   Anchored to the same 40% centre as the masthead, clear of the fitted name. */
.name-in-lights-titles {
    position: absolute;
    inset: 0;
    opacity: 1;
}

.name-in-lights-eyebrow {
    position: absolute;
    left: 16px;
    right: 16px;
    bottom: calc(60% + var(--name-in-lights-block-h) / 2 + 1rem);
    margin: 0;
    padding-left: 0.34em;                      /* balances the trailing tracking */
    text-align: center;
    font: 500 0.74rem/1.6 var(--font-body);
    letter-spacing: 0.34em;
    text-transform: uppercase;
    text-wrap: balance;
    color: var(--accent-warm);
    opacity: 0;
}

.name-in-lights-below {
    position: absolute;
    left: 16px;
    right: 16px;
    top: calc(40% + var(--name-in-lights-block-h) / 2 + 1.25rem);
    display: grid;
    justify-items: center;
    gap: 1.15rem;
    text-align: center;
}

/* A gilt plate: what ReveelStage.lightSweep glints across. */
.name-in-lights-plaque {
    margin: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    max-width: 100%;
    padding: 0.64rem 1.3rem;
    border: 1px solid var(--gilt-line);
    border-radius: 999px;
    background: var(--plaque-fill);
    box-shadow: var(--plaque-inset);
    font: 500 0.76rem/1.3 var(--font-body);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-primary);
    position: relative;
    opacity: 0;
}
/* The plaque's glint: a narrow band of light, moved across by transform,
   clipped by its own wrapper (never by the plaque, so its text never clips). */
.name-in-lights-glint-clip {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    overflow: hidden;
    pointer-events: none;
}
.name-in-lights-glint {
    position: absolute;
    top: -20%;
    bottom: -20%;
    left: 0;
    width: 34%;
    background: linear-gradient(90deg, transparent, rgba(250, 240, 230, 0.5), transparent);
    transform: translateX(-160%) skewX(-18deg);
    pointer-events: none;
}
.name-in-lights-plaque::before {
    content: '';
    flex: none;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--accent-warm-bright);
    box-shadow: 0 0 10px 2px var(--accent-warm-glow);
}

.name-in-lights-from {
    margin: 0;
    max-width: 26rem;
    font: 400 0.98rem/1.45 var(--font-body);
    letter-spacing: 0.02em;
    text-wrap: balance;
    color: var(--text-secondary);
    opacity: 0;
}
.name-in-lights-from > span {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 1.08em;
    color: var(--accent-warm-bright);
}

/* ───── The hold: tap to look back ─────
   Screen space (#stage) after boot, centred, at a fixed bottom offset: it
   only ever fades, never travels. */
.name-in-lights-hint {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(9% + env(safe-area-inset-bottom, 0px));
    z-index: 5;
    display: grid;
    justify-items: center;
    gap: 0.7rem;
    padding-inline: 16px;
    opacity: 0;
    visibility: hidden;
    pointer-events: auto;
    transition: opacity 0.5s var(--ease-silk), visibility 0s linear 0.5s;
}
.name-in-lights-hint.name-in-lights-on {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.8s var(--ease-silk);
}
/* Never showing outside this beat (a goto away mid-hold leaves no stray button). */
.reveel-stage:has(#screen-name-in-lights:not(.active)) > .name-in-lights-hint {
    opacity: 0;
    visibility: hidden;
}
.name-in-lights-chevs {
    display: grid;
    justify-items: center;
    height: 22px;
}
.name-in-lights-chev {
    width: 12px;
    height: 12px;
    margin-top: -5px;
    border-left: 1.5px solid var(--accent-warm);
    border-top: 1.5px solid var(--accent-warm);
    transform: rotate(45deg);
}
.name-in-lights-hint.name-in-lights-on .name-in-lights-chev {
    animation: name-in-lights-nudge 1.8s var(--ease-breath) infinite;
}
.name-in-lights-chev + .name-in-lights-chev { opacity: 0.45; animation-delay: 0.15s; }

.name-in-lights-look {
    -webkit-appearance: none;
    appearance: none;
    min-height: 44px;
    padding: 0.95rem 1.7rem;
    border: 1px solid var(--glass-border-hover);
    border-radius: 999px;
    background: var(--glass);
    box-shadow: 0 0 26px var(--accent-warm-glow-soft), inset 0 1px 0 rgba(242, 196, 160, 0.14);
    font: 500 0.78rem/1 var(--font-body);
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--text-primary);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.name-in-lights-look:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 3px;
}

/* ───── The sky: stars on three depth planes, plus the near-plane motes ─────
   Lives in #world after boot. Extends well above the stage so a crane up
   finds stars; each plane is scaled back to rest at its layout size. */
.name-in-lights-sky {
    position: absolute;
    left: -20%;
    right: -20%;
    top: -60%;
    bottom: 10%;
    transform-style: preserve-3d;
    pointer-events: none;
    opacity: 1;
    transition: opacity 1.6s var(--ease-silk);
}
.name-in-lights-stars,
.name-in-lights-motes {
    position: absolute;
    inset: 0;
    transform-origin: 50% 73.3%;               /* the stage's centre: the perspective origin */
    opacity: 0;
}
.name-in-lights-stars-far { transform: translateZ(-600px) scale(1.667); }
.name-in-lights-stars-mid { transform: none; }
.name-in-lights-stars-near,
.name-in-lights-motes { transform: translateZ(220px) scale(0.756); }

.name-in-lights-star {
    position: absolute;
    width: 2px;
    height: 2px;
    margin: -1px 0 0 -1px;
    border-radius: 50%;
    background: var(--spark);
    box-shadow: 0 0 4px 1px rgba(242, 196, 160, 0.55);
}
.name-in-lights-stars-mid .name-in-lights-star {
    width: 3px;
    height: 3px;
    margin: -1.5px 0 0 -1.5px;
    box-shadow: 0 0 7px 2px rgba(242, 196, 160, 0.5);
}
.name-in-lights-stars-near .name-in-lights-star {
    width: 5px;
    height: 5px;
    margin: -2.5px 0 0 -2.5px;
    background: var(--text-primary);
    box-shadow: 0 0 10px 3px rgba(242, 196, 160, 0.55), 0 0 26px 6px rgba(232, 168, 124, 0.18);
}
/* The near stars carry a four-point glint. */
.name-in-lights-stars-near .name-in-lights-star::before,
.name-in-lights-stars-near .name-in-lights-star::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 26px;
    height: 1px;
    margin: -0.5px 0 0 -13px;
    background: linear-gradient(90deg, transparent, rgba(250, 240, 230, 0.75), transparent);
}
.name-in-lights-stars-near .name-in-lights-star::after { transform: rotate(90deg); }

.name-in-lights-mote {
    position: absolute;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(242, 196, 160, 0.7), rgba(232, 168, 124, 0) 70%);
    opacity: 0.5;
}

/* Twinkle: this beat starts it as Web Animations when each layer ignites
   (and marks the sky twinkling). A film entered past this beat (goto) gets
   the CSS twinkle instead. */
.reveel-stage:has(#screen-the-years.active, #screen-years-in-order.active, #screen-the-letter.active, #screen-cap-toss.active, #screen-finale.active) .name-in-lights-sky:not([data-name-in-lights-twinkling]) .name-in-lights-star {
    animation: name-in-lights-twinkle var(--name-in-lights-tw, 4s) var(--ease-breath) var(--name-in-lights-delay, 0s) infinite;
}

/* The stars stay lit for the rest of the film; the letter dims its sky. */
.reveel-stage:has(#screen-the-years.active, #screen-years-in-order.active, #screen-the-letter.active, #screen-cap-toss.active, #screen-finale.active) .name-in-lights-stars {
    opacity: 1;
}
.reveel-stage:has(#screen-the-letter.active) .name-in-lights-sky { opacity: 0.35; }

/* Entry states land instantly (prepare / goto), never animated in. */
.name-in-lights-instant,
.name-in-lights-instant * {
    transition: none !important;
}

/* ───── Keyframes ───── */
/* Both ends are the name's own glow (plain or settled), so a flare returns to whichever it has. */
@keyframes name-in-lights-flare {
    14% { text-shadow: var(--name-shadow-flare); }
}
@keyframes name-in-lights-nudge {
    0%, 100% { transform: translateY(0) rotate(45deg); }
    50% { transform: translateY(-6px) rotate(45deg); }
}
@keyframes name-in-lights-twinkle {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}
@keyframes name-in-lights-crossfade {
    0% { opacity: 1; transform: none; }
    42% { opacity: 0; transform: none; }
    58% { opacity: 0; transform: var(--name-in-lights-zenith); }
    100% { opacity: 1; transform: var(--name-in-lights-zenith); }
}

/* ───── Reduced motion: the beat plays in full, calmly ─────
   The camera no-ops by itself and nameAssemble takes its calm variant. Here
   the name cross-fades from centre to masthead instead of travelling and the
   ornaments stop looping; the JS (film.reduced()) drops the reveals' rises,
   the sweeps, the flare, the breathing and the twinkle. */
@media (prefers-reduced-motion: reduce) {
    .name-in-lights-masthead { transition: opacity 0.9s var(--ease-silk); }
    .name-in-lights-masthead[data-name-in-lights-risen] {
        animation: name-in-lights-crossfade 2.4s var(--ease-silk);
    }
    .reveel-stage:has(#screen-cap-toss.active) > .name-in-lights-masthead,
    .reveel-stage:has(#screen-finale.active) > .name-in-lights-masthead {
        transition: opacity 1.2s var(--ease-silk), transform 1.6s var(--ease-silk);
    }
    .name-in-lights-name { transition-property: text-shadow; }
    .name-in-lights-name.name-in-lights-flare { animation: none; }
    .name-in-lights-hint.name-in-lights-on .name-in-lights-chev,
    .reveel-stage:has(#screen-the-years.active, #screen-years-in-order.active, #screen-the-letter.active, #screen-cap-toss.active, #screen-finale.active) .name-in-lights-sky:not([data-name-in-lights-twinkling]) .name-in-lights-star { animation: none; }
}
