/* ═══════════════════════════════════════════
   now-playing — beat 5 of now-streaming (the montage)

   A full-bleed picture in two slots (one showing, one parked), a dim layer,
   a letterbox, the entrance title card, the per-moment slate, two subtitle
   cards, the progress hairline and the exit's "Next up" card. Every state
   is a class toggled by a cue in js/now-playing.js; nothing here loops.

   Container states (on #now-playing-container):
     now-playing-is-live      the beat has been entered
     now-playing-lb-on        the letterbox has slid in
     now-playing-tc-dim       the photo dims under the title card
     now-playing-tc-slate-on  "S{S} · E1"
     now-playing-tc-title-on  the show's title
     now-playing-tc-out       the title card fades
     now-playing-is-cut       the first cut has landed (the dim lifts over 0.3 s,
                              the subtitle band comes up)
     now-playing-fallback     a photo failed: the previous one stays, dimmed
     now-playing-exit         the last 10 s: the frame dims 40%
     now-playing-nextup-on    "Next up" and its line filling
     now-playing-frozen       the line is complete, the picture is still
   ═══════════════════════════════════════════ */

.now-playing-container {
    position: absolute;
    inset: 0;
    overflow: hidden;
    background: var(--void);
    color: var(--text-primary);
    font-family: var(--font-body);
    pointer-events: none;            /* nothing on this beat is a control */
    user-select: none;
    -webkit-user-select: none;
}

/* Entry states are applied instantly (prepare), never animated in. */
.now-playing-instant,
.now-playing-instant *,
.now-playing-instant *::before,
.now-playing-instant *::after {
    transition: none !important;
    animation: none !important;
}

/* ─────────── The picture ─────────── */

.now-playing-frame {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: var(--void);
}

/* A hard cut: the slot swap has no transition. */
.now-playing-slot {
    position: absolute;
    inset: 0;
    z-index: 1;
    opacity: 0;
    overflow: hidden;
    transition: none;
}
.now-playing-slot.now-playing-slot-on {
    z-index: 2;
    opacity: 1;
}

/* The ghost plate: the same photo, cover-scaled and darkened with a flat
   --plate-dim layer (no filter, no blur, no second decode). Only shown when
   the photo cannot fill the frame. */
.now-playing-plate,
.now-playing-plate-dim {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: none;
}
.now-playing-plate {
    object-fit: cover;
    object-position: 50% 50%;
}
.now-playing-plate-dim {
    background: var(--plate-dim);
}
.now-playing-slot[data-fit="contain"] .now-playing-plate,
.now-playing-slot[data-fit="contain"] .now-playing-plate-dim {
    display: block;
}

/* The photo. Cover by default, with a 14% upper-third bias (50% 36%) so a
   face keeps its chin; a landscape, a square or a panorama sits at its own
   width, centred, over the plate. */
.now-playing-photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 36%;
    transform-origin: 50% 36%;
    transform: translate3d(0, 0, 0) scale(1);
}
.now-playing-slot[data-fit="contain"] .now-playing-photo {
    object-fit: contain;
    object-position: 50% 50%;
    transform-origin: 50% 50%;
}

/* Dwell classes: each scene's length, set on the showing slot at its cut. */
.now-playing-dwell-8  { --now-playing-dwell: 5.333s; }
.now-playing-dwell-10 { --now-playing-dwell: 6.667s; }
.now-playing-dwell-11 { --now-playing-dwell: 7.333s; }
.now-playing-dwell-12 { --now-playing-dwell: 8s; }

/* Four pan variants by index: scale 1.0 to 1.08 over the dwell, with a drift
   of at most 3% (the drift starts from centre, so the zoom always covers the
   edge it moves toward). A near-frame-shaped photo (9:16) drifts least. */
.now-playing-pan-0 { --now-playing-dx: -3%;   --now-playing-dy: -1.5%; }
.now-playing-pan-1 { --now-playing-dx: 3%;    --now-playing-dy: 1.5%; }
.now-playing-pan-2 { --now-playing-dx: 2.5%;  --now-playing-dy: -2%; }
.now-playing-pan-3 { --now-playing-dx: -2.5%; --now-playing-dy: 1.2%; }
.now-playing-slot { --now-playing-k: 1; }
.now-playing-slot[data-pan="weak"] { --now-playing-k: 0.35; }

/* Moment 1 under the title card (0-5.67 s): already drifting, gently. The
   first cut swaps this for the pan class, which restarts the pan from 0. */
.now-playing-slot.now-playing-slot-on.now-playing-drifting .now-playing-photo {
    will-change: transform;
    animation: now-playing-drift 5.667s var(--ease-drift) both;
}
.now-playing-slot.now-playing-slot-on.now-playing-panning .now-playing-photo {
    will-change: transform;
    animation: now-playing-pan var(--now-playing-dwell, 6.667s) var(--ease-drift) both;
}
.now-playing-frozen .now-playing-photo {
    animation-play-state: paused;
}

@keyframes now-playing-drift {
    from { transform: translate3d(0, 0, 0) scale(1); }
    to { transform: translate3d(-0.6%, -0.4%, 0) scale(1.025); }
}

@keyframes now-playing-pan {
    from { transform: translate3d(0, 0, 0) scale(1); }
    to {
        transform: translate3d(calc(var(--now-playing-dx, 0%) * var(--now-playing-k, 1)),
                               calc(var(--now-playing-dy, 0%) * var(--now-playing-k, 1)), 0) scale(1.08);
    }
}

/* ─────────── The dim layer (flat void, never a filter) ─────────── */

.now-playing-dim {
    position: absolute;
    inset: 0;
    z-index: 2;
    background: var(--void);
    opacity: 0.6;                     /* moment 1, dimmed 60% under the title card */
    transition: opacity 1.2s var(--ease-silk);
}
.now-playing-container.now-playing-tc-dim .now-playing-dim {
    opacity: 0.6;
}
.now-playing-container.now-playing-is-cut .now-playing-dim {
    opacity: 0;
    transition: opacity 0.3s var(--ease-silk);   /* the first cut: moment 1 brightens to full */
}
.now-playing-container.now-playing-fallback .now-playing-dim {
    opacity: 0.5;
    transition: none;
}
.now-playing-container.now-playing-exit .now-playing-dim {
    opacity: 0.4;
    transition: opacity 1s var(--ease-silk);
}
.now-playing-container.now-playing-fallback.now-playing-exit .now-playing-dim {
    opacity: 0.55;
}

/* ─────────── The subtitle band ───────────
   --sub-band is void at 0.82, solid from the bottom edge to 236 px up and
   feathered out by 276 px (subtitles sit at 96-220 px): text-primary on it
   is 11.27:1 over a pure-white photo. The band is lifted by the safe-area
   inset, with a solid strip under it, so the stops stay measured from the
   subtitles' own baseline. A gradient, never a box. */
.now-playing-subband {
    position: absolute;
    left: 0;
    right: 0;
    bottom: env(safe-area-inset-bottom, 0px);
    z-index: 2;
    height: 276px;
    background: var(--sub-band);
    opacity: 0;
    transition: opacity 0.3s var(--ease-silk);
}
.now-playing-subband::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    height: env(safe-area-inset-bottom, 0px);
    background: rgba(5, 5, 17, 0.82);  /* void, the band's solid stop */
}
.now-playing-container.now-playing-is-cut .now-playing-subband {
    opacity: 1;
}

/* ─────────── The letterbox: the lights going down ─────────── */

.now-playing-letterbox {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 3;
    height: 6vh;
    background: var(--void);
    transition: transform 1.2s var(--ease-stage);
}
.now-playing-letterbox-top {
    top: 0;
    transform: translate3d(0, -101%, 0);
}
.now-playing-letterbox-bottom {
    bottom: 0;
    transform: translate3d(0, 101%, 0);
}
.now-playing-container.now-playing-lb-on .now-playing-letterbox {
    transform: translate3d(0, 0, 0);
}

/* ─────────── Entrance title card ─────────── */

.now-playing-titlecard {
    position: absolute;
    left: 8%;
    right: 8%;
    top: 50%;
    z-index: 4;
    transform: translate3d(0, -50%, 0);
    text-align: center;
}
/* The card's backing: --block-backing (void 0.82, feathered over 40 px), the
   card's height plus 40 px each way, across the frame (clipped by the
   container), so it is a band, not a box. It fades in with "S{S} · E1"
   (1.4 s) and out with the card (4.6 s). */
.now-playing-titlecard::before {
    content: '';
    position: absolute;
    z-index: -1;
    top: -40px;
    bottom: -40px;
    left: 50%;
    width: 200vw;
    transform: translateX(-50%);
    background: var(--block-backing);
    opacity: 0;
    transition: opacity 0.7s var(--ease-silk);
    pointer-events: none;
}
.now-playing-container.now-playing-tc-slate-on .now-playing-titlecard::before {
    opacity: 1;
}
.now-playing-container.now-playing-tc-out .now-playing-titlecard::before {
    opacity: 0;
    transition: opacity 0.8s var(--ease-silk);
}
.now-playing-tc-slate,
.now-playing-tc-title {
    margin: 0;
    opacity: 0;
    transform: translate3d(0, 6px, 0);
    transition: opacity 0.7s var(--ease-silk), transform 0.9s var(--ease-expo-out);
}
.now-playing-tc-slate {
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 0.78rem;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--tag-ink);
    text-shadow: var(--sub-outline);
}
.now-playing-tc-title {
    margin-top: 0.7rem;
    font-family: var(--font-display);
    font-weight: 600;
    font-variant-caps: all-small-caps;
    font-size: clamp(1.4rem, 6.4vw, 1.9rem);
    line-height: 1.2;
    letter-spacing: 0.06em;
    color: var(--text-primary);
    text-shadow: var(--title-shadow);
    overflow-wrap: anywhere;
    text-wrap: balance;
    /* small, two lines at most */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    max-height: 3em;
    overflow: hidden;
    padding: 0 0.2em;
}
.now-playing-container.now-playing-tc-slate-on .now-playing-tc-slate,
.now-playing-container.now-playing-tc-title-on .now-playing-tc-title {
    opacity: 1;
    transform: translate3d(0, 0, 0);
}
.now-playing-container.now-playing-tc-out .now-playing-tc-slate,
.now-playing-container.now-playing-tc-out .now-playing-tc-title {
    opacity: 0;
    transform: translate3d(0, -4px, 0);
    transition: opacity 0.8s var(--ease-silk), transform 0.8s var(--ease-silk);
}

/* ─────────── Per-moment slate: "E{k} · {title}" ─────────── */

.now-playing-slate {
    position: absolute;
    z-index: 4;
    top: calc(6vh + 16px + env(safe-area-inset-top, 0px));
    left: 6%;
    max-width: 68%;                   /* the Mute pill owns the top right */
    margin: 0;
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 0.74rem;
    line-height: 1.5;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--tag-ink);
    text-shadow: var(--sub-outline);
    overflow-wrap: anywhere;
    opacity: 0;
    transform: translate3d(0, -6px, 0);
    transition: opacity 0.4s var(--ease-silk), transform 0.4s var(--ease-silk);
}
/* The letterbox's dark carried down under the slate as a short band (void
   0.82 from the letterbox's edge to 40 px below the slate's text, then
   feathered over 40 px; full frame width, clipped by the container). It
   fades with the slate. tag-ink on it: 8.23:1 over a pure-white photo. */
.now-playing-slate::before {
    content: '';
    position: absolute;
    z-index: -1;
    top: calc(-16px - env(safe-area-inset-top, 0px));
    bottom: -40px;
    left: -100vw;
    right: -100vw;
    background: linear-gradient(180deg, rgba(5, 5, 17, 0.82) 0, rgba(5, 5, 17, 0.82) calc(100% - 40px), rgba(5, 5, 17, 0) 100%);
    pointer-events: none;
}
.now-playing-slate.now-playing-slate-on {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    transition: opacity 0.5s var(--ease-silk), transform 0.6s var(--ease-expo-out);
}

/* ─────────── Subtitles: 96-220 px above the bottom edge ─────────── */

.now-playing-subs {
    position: absolute;
    z-index: 4;
    left: 6%;
    right: 6%;
    bottom: calc(100px + env(safe-area-inset-bottom, 0px));
    height: 116px;                    /* the block's top stays under 220 px */
}
.now-playing-sub {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    margin: 0;
    text-align: center;
    font-family: var(--font-body);
    font-weight: 500;
    font-size: clamp(1.05rem, 4.6vw, 1.25rem);
    line-height: 1.35;
    color: var(--sub-ink);
    text-shadow: var(--sub-outline);  /* a void outline, never a box */
    overflow-wrap: break-word;
    text-wrap: balance;
    opacity: 0;
    transform: translate3d(0, 4px, 0);
    transition: opacity 0.4s var(--ease-silk), transform 0.4s var(--ease-silk);
}
.now-playing-sub.now-playing-sub-on {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    transition: opacity 0.3s var(--ease-silk), transform 0.4s var(--ease-expo-out);
}
/* The second card of a split line arrives as the first leaves. */
.now-playing-sub.now-playing-sub-second.now-playing-sub-on {
    transition-delay: 0.2s;
}

/* ─────────── Progress hairline (decoration: no thumb, not interactive) ─────────── */

.now-playing-progress {
    position: absolute;
    z-index: 4;
    left: 10%;
    right: 10%;
    bottom: calc(76px + env(safe-area-inset-bottom, 0px));
    height: 2px;
    display: flex;
    gap: 3px;
    opacity: 0;
    transition: opacity 0.8s var(--ease-silk);
}
.now-playing-container.now-playing-lb-on .now-playing-progress {
    opacity: 0.85;
}
.now-playing-notch {
    position: relative;
    flex: 1 1 0;
    height: 100%;
    overflow: hidden;
    background: var(--progress-track);
}
.now-playing-notch::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--progress-fill);
    transform: scaleX(0);
    transform-origin: 0 50%;
    transition: transform 0.45s var(--ease-expo-out);
}
.now-playing-notch.now-playing-notch-on::after {
    transform: scaleX(1);
}

/* ─────────── Exit: "Next up" ─────────── */

.now-playing-nextup {
    position: absolute;
    z-index: 5;
    left: 50%;
    top: 52%;
    width: max-content;
    min-width: 12rem;
    max-width: 86%;
    text-align: center;
    opacity: 0;
    transform: translate3d(-50%, 8px, 0);
    transition: opacity 0.8s var(--ease-silk), transform 0.9s var(--ease-expo-out);
}
.now-playing-container.now-playing-nextup-on .now-playing-nextup {
    opacity: 1;
    transform: translate3d(-50%, 0, 0);
}
/* The card's backing: --block-backing (void 0.82, feathered over 40 px) as a
   band the card's height plus 40 px each way, across the frame (clipped by
   the container), so it is not a box. It fades in with the card. Over a
   pure-white photo under the 0.4 exit dim: "Next up" (tag-ink) 10.47:1,
   "The rest of your life." (text-primary) 14.34:1, the line's fill 4.89:1. */
.now-playing-nextup::before {
    content: '';
    position: absolute;
    z-index: -1;
    top: -40px;
    bottom: -40px;
    left: 50%;
    width: 200vw;
    transform: translateX(-50%);
    background: var(--block-backing);
    pointer-events: none;
}
/* A thin line under the text, filling left to right over 6 s: decoration
   (no thumb, no glyph, no ring), in --decor-ink on a --progress-track. */
.now-playing-nextup-bar {
    position: relative;
    display: block;
    height: 2px;
    margin-top: 0.85rem;
    overflow: hidden;
    background: var(--progress-track);
}
.now-playing-nextup-bar::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--decor-ink);
    transform: scaleX(0);
    transform-origin: 0 50%;
    transition: transform 6s linear;
}
.now-playing-container.now-playing-nextup-on .now-playing-nextup-bar::after {
    transform: scaleX(1);
}
.now-playing-nextup-kicker {
    margin: 0;
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 0.74rem;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--tag-ink);
    text-shadow: var(--sub-outline);
}
.now-playing-nextup-line {
    margin: 0.3rem 0 0;
    font-family: var(--font-display);
    font-style: italic;
    font-weight: 400;
    font-size: clamp(1.25rem, 5.4vw, 1.6rem);
    line-height: 1.25;
    color: var(--text-primary);
    text-shadow: var(--sub-outline);
}

/* ─────────── Reduced motion: plays in full, calmer ───────────
   No pan or zoom, no letterbox slide (it fades), each cut is a 0.25 s
   cross-fade on the same beats (the outgoing slot stays opaque under the
   incoming one until the fade ends), subtitles fade without moving, the
   hairline steps without easing, and the "Next up" line is a plain fill. */
@media (prefers-reduced-motion: reduce) {
    .now-playing-slot {
        transition: opacity 0s linear 0.25s;
    }
    .now-playing-slot.now-playing-slot-on {
        transition: opacity 0.25s var(--ease-silk);
    }
    .now-playing-slot.now-playing-slot-on.now-playing-drifting .now-playing-photo,
    .now-playing-slot.now-playing-slot-on.now-playing-panning .now-playing-photo {
        animation: none;
        will-change: auto;
    }
    .now-playing-container.now-playing-is-cut .now-playing-dim {
        transition: opacity 0.25s var(--ease-silk);
    }
    .now-playing-letterbox-top,
    .now-playing-letterbox-bottom {
        transform: none;
        opacity: 0;
        transition: opacity 0.8s var(--ease-silk);
    }
    .now-playing-container.now-playing-lb-on .now-playing-letterbox {
        transform: none;
        opacity: 1;
    }
    .now-playing-tc-slate,
    .now-playing-tc-title,
    .now-playing-slate,
    .now-playing-sub,
    .now-playing-container.now-playing-tc-out .now-playing-tc-slate,
    .now-playing-container.now-playing-tc-out .now-playing-tc-title,
    .now-playing-slate.now-playing-slate-on,
    .now-playing-sub.now-playing-sub-on {
        transform: none;
    }
    .now-playing-nextup,
    .now-playing-container.now-playing-nextup-on .now-playing-nextup {
        transform: translate3d(-50%, 0, 0);
    }
    .now-playing-notch::after {
        transition: none;
    }
}
