/* ═══════════════════════════════════════════
   end-credits — End Credits (beat 7 of 7, the finale; watched)
   The roll (six fixed-height slots, one layer, a constant-speed linear
   translate), the renewal card that bursts into gold on the hit, the three
   lines beneath it, and "Watch again". Every play state is a class on
   .end-credits-container set by a cue in js/end-credits.js; the hoisted
   "Watch again" layer carries its own.
   No filter: blur, no backdrop-filter, no mix-blend-mode.
   ═══════════════════════════════════════════ */

.end-credits-container {
    --end-credits-u: 3.1rem;            /* one second of roll: every slot is (its seconds) x this tall */
    --end-credits-roll-s: 16s;          /* shots.md: a fixed 16 s, whatever the content */
    position: absolute;
    inset: 0;
    overflow: visible;
    color: var(--text-primary);
    font-family: var(--font-body);
    pointer-events: none;
}

.end-credits-container.end-credits-no-places {
    --end-credits-roll-s: 12.8s;        /* slot 4 (3.2 s) drops out with no places */
}

.end-credits-container p {
    margin: 0;
}

/* Entry states are applied instantly (prepare), never animated in. */
.end-credits-instant,
.end-credits-instant * {
    transition: none !important;
}

/* ─────────── The dark: ground, beam, the warm point, the motes ───────────
   Oversized so the camera's push (z 70) and back-off (z -60) never show its edge. */
.end-credits-ground {
    position: absolute;
    inset: -16%;
    background:
        radial-gradient(70% 52% at 50% 46%, rgba(16, 24, 48, 0.55) 0%, rgba(12, 18, 34, 0.32) 42%, rgba(5, 5, 17, 0) 100%),
        var(--void);
    z-index: 0;
}

.end-credits-beam {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 78%;
    background: linear-gradient(180deg, var(--beam) 0%, rgba(242, 196, 160, 0.035) 55%, rgba(242, 196, 160, 0) 100%);
    clip-path: polygon(45% 0, 55% 0, 78% 100%, 22% 100%);
    opacity: 0;
    transition: opacity 1.4s var(--ease-silk);
}

.end-credits-point,
.end-credits-afterglow {
    position: absolute;
    left: 50%;
    top: calc(50% - 7vh);               /* the card's centre: .end-credits-renewal lifts it by 7vh */
    border-radius: 50%;
    pointer-events: none;
}

.end-credits-point {
    width: 132px;
    height: 132px;
    margin: -66px 0 0 -66px;
    background: radial-gradient(closest-side, var(--light-core) 0%, rgba(242, 196, 160, 0.55) 9%, var(--accent-warm-glow-soft) 38%, rgba(232, 168, 124, 0) 100%);
    opacity: 0;
    transition: opacity 1.2s var(--ease-silk);
}

.end-credits-afterglow {
    width: 150vmin;
    height: 150vmin;
    margin: -75vmin 0 0 -75vmin;
    background: radial-gradient(closest-side, var(--halo) 0%, var(--bloom) 34%, var(--halo-far) 62%, rgba(232, 168, 124, 0) 100%);
    opacity: 0;
    transition: opacity 2.4s var(--ease-silk);
}

.end-credits-motes {
    position: absolute;
    inset: 0;
}

.end-credits-motes i {
    position: absolute;
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: var(--spark);
    box-shadow: 0 0 6px rgba(242, 196, 160, 0.55);
    opacity: 0;
    transition: opacity 1.6s var(--ease-silk);
}

.end-credits-motes i:nth-child(1)  { left: 38%; top: 30%; animation-delay: -1s;  animation-duration: 11s; }
.end-credits-motes i:nth-child(2)  { left: 47%; top: 22%; animation-delay: -4s;  animation-duration: 13s; width: 2px; height: 2px; }
.end-credits-motes i:nth-child(3)  { left: 56%; top: 35%; animation-delay: -7s;  animation-duration: 10s; }
.end-credits-motes i:nth-child(4)  { left: 43%; top: 46%; animation-delay: -2s;  animation-duration: 14s; width: 2px; height: 2px; }
.end-credits-motes i:nth-child(5)  { left: 61%; top: 51%; animation-delay: -9s;  animation-duration: 12s; }
.end-credits-motes i:nth-child(6)  { left: 34%; top: 58%; animation-delay: -5s;  animation-duration: 15s; width: 2px; height: 2px; }
.end-credits-motes i:nth-child(7)  { left: 52%; top: 63%; animation-delay: -3s;  animation-duration: 11s; }
.end-credits-motes i:nth-child(8)  { left: 66%; top: 27%; animation-delay: -8s;  animation-duration: 16s; width: 2px; height: 2px; }
.end-credits-motes i:nth-child(9)  { left: 29%; top: 40%; animation-delay: -6s;  animation-duration: 12s; width: 2px; height: 2px; }
.end-credits-motes i:nth-child(10) { left: 58%; top: 71%; animation-delay: -10s; animation-duration: 14s; width: 2px; height: 2px; }
.end-credits-motes i:nth-child(11) { left: 49%; top: 38%; animation-delay: -11s; animation-duration: 13s; }
.end-credits-motes i:nth-child(12) { left: 40%; top: 68%; animation-delay: -12s; animation-duration: 15s; width: 2px; height: 2px; }

/* In: the beam, the point and the motes are up from the beat's entry. */
.end-credits-is-in .end-credits-beam { opacity: 1; }
.end-credits-is-in .end-credits-point {
    opacity: 1;
    animation: end-credits-glimmer 3.2s var(--ease-breath) infinite alternate;
}
.end-credits-is-in .end-credits-motes i {
    opacity: 0.7;
    animation-name: end-credits-mote;
    animation-timing-function: var(--ease-drift);
    animation-iteration-count: infinite;
    animation-direction: alternate;
}
/* The point gives way to the card's glow as "Renewed" builds. */
.end-credits-is-in.end-credits-is-rise .end-credits-point {
    opacity: 0;
    animation: none;
    transition: opacity 1.8s var(--ease-silk);
}

@keyframes end-credits-glimmer {
    from { transform: scale(0.94); }
    to { transform: scale(1.06); }
}

@keyframes end-credits-mote {
    from { transform: translate3d(0, 0, 0); }
    to { transform: translate3d(12px, -34px, 0); }
}

/* ─────────── The roll ───────────
   The frame stops above the badge band (72 px + the safe area), so no credit
   ever passes through it; its two feathers fade the roll in and out of the dark. */
.end-credits-frame {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: calc(72px + env(safe-area-inset-bottom, 0px));
    overflow: hidden;
    z-index: 1;
}

.end-credits-frame::before,
.end-credits-frame::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    z-index: 2;
    pointer-events: none;
}

.end-credits-frame::before {
    top: 0;
    height: 12%;
    background: linear-gradient(180deg, var(--void) 0%, rgba(5, 5, 17, 0) 100%);
}

.end-credits-frame::after {
    bottom: 0;
    height: 14%;
    background: linear-gradient(0deg, var(--void) 0%, rgba(5, 5, 17, 0) 100%);
}

.end-credits-roll {
    position: absolute;
    top: 100%;                          /* parked just below the frame until 1.5 s */
    left: 0;
    right: 0;
    width: min(88%, 26rem);
    margin: 0 auto;
    z-index: 1;
}

/* One layer, one constant speed: a credits roll that eases reads as a stall.
   It travels the frame's height plus its own, so the last slot has left by
   the end. --end-credits-frame-h is the frame's height, read at entry. */
.end-credits-is-rolling .end-credits-roll {
    will-change: transform;
    animation: end-credits-roll var(--end-credits-roll-s) linear forwards;
}

.end-credits-is-rolled .end-credits-frame {
    visibility: hidden;
}

/* A credit line is drawn only inside the window. Clipping alone is not enough:
   below the window a line's box still sits in the badge band (parked before
   1.5 s, and on its way up). So every line holds at opacity 0 until its bottom
   edge has crossed the window's bottom edge, then fades in under the bottom
   feather. --end-credits-in (per line, seconds after the roll starts) is
   computed at entry from the roll's constant speed (js › measureReveal). */
.end-credits-roll p {
    opacity: 0;
}

.end-credits-is-rolling .end-credits-roll p {
    animation: end-credits-reveal 0.5s var(--ease-silk) var(--end-credits-in, 0s) forwards;
}

@keyframes end-credits-reveal {
    from { opacity: 0; }
    to { opacity: 1; }
}

.end-credits-is-rolled .end-credits-roll {
    will-change: auto;
}

@keyframes end-credits-roll {
    from { transform: translate3d(0, 0, 0); }
    to { transform: translate3d(0, calc(-100% - var(--end-credits-frame-h, 100vh)), 0); }
}

/* Six slots, each (its seconds) x --end-credits-u tall: 2.0 / 3.0 / 2.8 / 3.2 / 2.5 / 2.5. */
.end-credits-slot {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    text-align: center;
    overflow: visible;
}

.end-credits-slot-1 { height: calc(var(--end-credits-u) * 2.0); }
.end-credits-slot-2 { height: calc(var(--end-credits-u) * 3.0); }
.end-credits-slot-3 { height: calc(var(--end-credits-u) * 2.8); }
.end-credits-slot-4 { height: calc(var(--end-credits-u) * 3.2); }
.end-credits-slot-5 { height: calc(var(--end-credits-u) * 2.5); }
.end-credits-slot-6 { height: calc(var(--end-credits-u) * 2.5); }

.end-credits-no-places .end-credits-slot-4 {
    display: none;
}

.end-credits-role {
    font: 500 0.74rem/1.4 var(--font-body);
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--credit-role);
}

.end-credits-name {
    width: 100%;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: clamp(1.65rem, 7.2vw, 1.95rem);
    line-height: 1.15;
    color: var(--credit-name);
    text-wrap: balance;
    overflow-wrap: break-word;
}

/* A fitted name: one line first, smaller to a 1.6rem floor, then two lines (JS). */
.end-credits-fit {
    white-space: nowrap;
}

.end-credits-fit.end-credits-fit-wrap {
    white-space: normal;
    text-wrap: balance;
    overflow-wrap: anywhere;
}

.end-credits-star {
    font-weight: 700;
    font-size: var(--end-credits-fit-size, clamp(2.1rem, 9.6vw, 2.6rem));
    background: var(--credit-star);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
}

.end-credits-director {
    font-size: var(--end-credits-fit-size, clamp(1.75rem, 7.6vw, 2.05rem));
}

.end-credits-tag {
    max-width: 22rem;
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: 0.95rem;
    line-height: 1.35;
    color: var(--text-secondary);
    text-wrap: balance;
}

.end-credits-places {
    width: 100%;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: clamp(0.95rem, 4.95vw, 1.12rem);   /* 1.12rem from 362 px; a touch smaller on a 320 px phone, so six places of 16 still sit two to a line */
    line-height: 1.4;
    color: var(--credit-name);
    text-wrap: balance;
}

/* A place is never cut mid-word: each one is a single unbreakable unit. */
.end-credits-place {
    white-space: nowrap;
}

.end-credits-line {
    max-width: 22rem;
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: 1.12rem;
    line-height: 1.45;
    color: var(--text-primary);
    text-wrap: balance;
}

/* ─────────── The renewal ───────────
   The card is laid out in flow (no transform centring), so film.box reads
   its true centre; .end-credits-after hangs beneath it, outside its box. */
.end-credits-renewal {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-bottom: 14vh;               /* lifts the card's centre 7vh above the stage's */
    z-index: 2;
}

.end-credits-card {
    position: relative;
    z-index: 0;
    text-align: center;
    padding: 0.6rem 1.2rem;
}

.end-credits-card-glow {
    position: absolute;
    left: -45%;
    right: -45%;
    top: -80%;
    bottom: -80%;
    z-index: 0;
    background: radial-gradient(closest-side, var(--halo) 0%, var(--accent-warm-glow-soft) 46%, var(--halo-far) 70%, rgba(232, 168, 124, 0) 100%);
    opacity: 0;
    transition: opacity 2.3s cubic-bezier(0.4, 0, 1, 1);
}

.end-credits-renewed {
    position: relative;
    z-index: 1;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(2.9rem, 14vw, 4rem);
    line-height: 1.05;
    letter-spacing: 0.02em;
    opacity: 0;
    transform: scale(1.08);
    transition: opacity 1.4s var(--ease-silk), transform 1.8s var(--ease-expo-out);
}

.end-credits-renewed-glow,
.end-credits-renewed-flare,
.end-credits-renewed-word {
    display: block;
    position: relative;
}

.end-credits-renewed-glow,
.end-credits-renewed-flare {
    position: absolute;
    inset: 0;
    color: transparent;
    -webkit-text-fill-color: transparent;
    pointer-events: none;
}

.end-credits-renewed-glow {
    text-shadow: var(--title-shadow-settled);
    opacity: 0;
    transition: opacity 1.6s var(--ease-silk);
}

.end-credits-renewed-flare {
    text-shadow: var(--title-shadow-flare);
    opacity: 0;
}

.end-credits-renewed-word {
    background: var(--gilt-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
}

.end-credits-another {
    position: relative;
    z-index: 1;
    margin-top: 0.1rem;
    font-family: var(--font-script);
    font-size: clamp(1.9rem, 8.6vw, 2.5rem);
    line-height: 1.2;
    color: var(--accent-warm-bright);
    text-shadow: 0 0 18px var(--accent-warm-glow);
    opacity: 0;
    transform: translate3d(0, 8px, 0);
    transition: opacity 1.2s var(--ease-silk), transform 1.4s var(--ease-expo-out);
}

/* The rise (18.7 s): the card's glow builds on the swell. */
.end-credits-is-rise .end-credits-card-glow { opacity: 0.55; }

/* 19.2 s: "Renewed" lights in; 20.2 s: "for another season". */
.end-credits-is-renewed .end-credits-renewed { opacity: 1; transform: none; }
.end-credits-is-renewed .end-credits-renewed-glow { opacity: 0.45; }
.end-credits-is-season .end-credits-another { opacity: 1; transform: none; }

/* The hit (21.03 s): the card flares, then settles into its glow and breathes. */
.end-credits-is-hit .end-credits-renewed-flare {
    animation: end-credits-flare 1.9s ease-out both;
}
.end-credits-is-hit .end-credits-renewed-glow { opacity: 1; }
.end-credits-is-hit .end-credits-renewed-word {
    animation: end-credits-pop 1.4s var(--ease-expo-out) both;
}
.end-credits-is-hit .end-credits-card-glow {
    opacity: 1;
    animation: end-credits-breathe 6.4s var(--ease-breath) 1.2s infinite alternate;
}

@keyframes end-credits-flare {
    0% { opacity: 0; }
    6% { opacity: 1; }
    100% { opacity: 0; }
}

@keyframes end-credits-pop {
    from { transform: scale(1.05); }
    to { transform: scale(1); }
}

@keyframes end-credits-breathe {
    from { opacity: 1; }
    to { opacity: 0.72; }
}

/* The afterglow under reduced motion: the card's static glow fades up instead of the bokeh. */
.end-credits-is-afterglow .end-credits-afterglow { opacity: 1; }

/* ─────────── After the burst: Season {S + 1}, the quiet line, the count ─────────── */
.end-credits-after {
    position: absolute;
    top: 100%;
    left: 50%;
    width: min(88vw, 24rem);
    transform: translateX(-50%);
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    padding-top: 1.5rem;
    text-align: center;
}

.end-credits-next,
.end-credits-daily,
.end-credits-count {
    opacity: 0;
    transform: translate3d(0, 10px, 0);
    transition: opacity 1.1s var(--ease-silk), transform 1.3s var(--ease-expo-out);
}

.end-credits-next {
    font: 600 0.86rem/1.3 var(--font-body);
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--accent-warm-bright);
}

.end-credits-daily {
    font-family: var(--font-display);
    font-style: italic;
    font-size: 1.15rem;
    line-height: 1.35;
    color: var(--text-primary);
}

.end-credits-count {
    font: 400 0.82rem/1.45 var(--font-body);
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    text-wrap: balance;
}

/* "{together}" is optional: its separators belong to it and vanish with it. */
.end-credits-together:empty { display: none; }
.end-credits-together::before { content: ' '; }
.end-credits-together::after { content: '.'; }

.end-credits-is-next .end-credits-next,
.end-credits-is-daily .end-credits-daily,
.end-credits-is-count .end-credits-count {
    opacity: 1;
    transform: none;
}

/* ─────────── Watch again ───────────
   Hoisted into #stage at boot (screen space: the camera never carries it),
   above the badge band. Hidden, and so unfocusable, until 28 s. */
.end-credits-again {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(96px + env(safe-area-inset-bottom, 0px));
    z-index: 6;
    display: flex;
    justify-content: center;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.6s var(--ease-silk), visibility 0s linear 0.6s;
}

.end-credits-again.end-credits-again-on {
    opacity: 1;
    visibility: visible;
    transition: opacity 1.4s var(--ease-silk), visibility 0s;
}

/* The hit box is the button's full rectangle (no radius, so its corners are
   not tap holes that fall through to the section beneath); the pill is
   painted by ::before inside it. */
.end-credits-again-btn {
    position: relative;
    isolation: isolate;
    min-height: 48px;
    padding: 0 1.7rem;
    border: 0;
    border-radius: 0;
    background: transparent;
    outline: none;
    color: var(--text-primary);
    font: 500 0.84rem/1 var(--font-body);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    cursor: pointer;
    pointer-events: none;
    -webkit-tap-highlight-color: transparent;
    transition: transform 0.18s var(--ease-snap);
}

.end-credits-again-btn::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border: 1px solid var(--btn-ghost-border);
    border-radius: 999px;
    background: var(--btn-ghost-fill);
    transition: border-color 0.3s var(--ease-silk);
}

.end-credits-again-on .end-credits-again-btn {
    pointer-events: auto;
}

.end-credits-again-btn:hover::before {
    border-color: var(--accent-warm-bright);
}

.end-credits-again-btn:active {
    transform: scale(0.97);
}

.end-credits-again-btn:focus-visible::before {
    box-shadow: 0 0 0 3px var(--void), 0 0 0 5px var(--focus-ring);
}

/* ─────────── Reduced motion: plays in full, calmer ───────────
   The roll keeps its speed; the camera and shake no-op in ReveelStage; the
   card fades in whole, flares as a plain fade, and does not breathe; the
   motes rest at half opacity; the afterglow is the static glow above. */
@media (prefers-reduced-motion: reduce) {
    .end-credits-is-in .end-credits-motes i { animation: none; opacity: 0.5; }
    .end-credits-is-in .end-credits-point { animation: none; }
    .end-credits-renewed,
    .end-credits-another,
    .end-credits-next,
    .end-credits-daily,
    .end-credits-count {
        transform: none;
        transition: opacity 1.2s var(--ease-silk);
    }
    .end-credits-card-glow { transition: opacity 1.6s var(--ease-silk); }
    .end-credits-is-hit .end-credits-renewed-flare { animation: none; }
    .end-credits-is-hit .end-credits-renewed-word { animation: none; }
    .end-credits-is-hit .end-credits-card-glow { animation: none; opacity: 0.9; }
    .end-credits-again-btn,
    .end-credits-again-btn:active { transform: none; }
}
