/* ═══════════════════════════════════════════
   now-streaming — the shell (build contract §7.2)

   The stage (a cinema screen at night), its three set-piece canvases, the
   camera world that holds the projector dust and every beat's <section>,
   the mute control, and the few rules the film spine (js/app.js) relies
   on. Beats style only their own prefixed classes; .screen, the stage and
   the canvases belong here.

   Stacking inside #stage (all position: absolute over one box):
     0  .aurora-bg        the two edge glows, outside the camera world
     0  #fx-back          the ambient bokeh (film.ambient; never on in this film)
     1  #world            the camera world: two planes of dust, then every beat
     2  #fx-light         lightDissolve, nameAssemble, the credits' afterglow
     3  the hit flash     (.reveel-flash::after), from --flash-x/-y
     4  #fx-burst         goldBurst, brightest of all
     6  #end-credits-again  hoisted after #world by end-credits' boot
     8  #stage-mute

   No filter: blur, no backdrop-filter, no mix-blend-mode (concept.md): every
   soft edge is a gradient feather, so the film plays on a budget phone.
   #screen-premiere carries its own camera counter-transform (premiere.css);
   nothing here puts a transform on a section.
   ═══════════════════════════════════════════ */

html,
body {
    height: 100%;
    margin: 0;
}

body {
    background: var(--void);
    color: var(--text-primary);
    font-family: var(--font-body);
    overflow: hidden;
    overscroll-behavior: none;
    -webkit-tap-highlight-color: transparent;
    -webkit-font-smoothing: antialiased;
}

button {
    font: inherit;
}

/* ───── The stage: ReveelStage's camera box, one phone screen tall ─────
   The ground is the screen's lit pool on blue-black (--screen-bg). `overflow:
   clip`, not hidden: a hidden box is still a scroll container, and a
   scrollIntoView (the episode list scrolls its open row into view) could
   scroll it and move the whole film. */
#stage {
    width: 100%;
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    overflow: clip;
    background: var(--screen-bg);
    background-color: var(--void);
    touch-action: manipulation;
    user-select: none;
    -webkit-user-select: none;
}

/* The primitive's hit flash, its timing untouched: over the world and the
   light canvas, under the burst so its sparks read brightest. It blooms from
   --flash-x/-y (the stage centre unless a beat sets them), which is where
   both of this film's hits are: the monogram and the renewal card. */
.reveel-stage.reveel-flash::after {
    z-index: 3;
    background: radial-gradient(circle at var(--flash-x, 50%) var(--flash-y, 50%),
        var(--flash-core) 0%, var(--flash-mid) 40%, transparent 75%);
}

/* ───── The aurora: the screen's two edge glows, recoloured ─────
   aurora.css hard-codes a purple haze, a pink glow and a navy haze, each a
   120 px blur; all three are replaced (concept.md): a wine-violet haze on the
   right edge (blob-1), an amber glow low on the left (blob-2), a far, faint
   blush (blob-3). The blur is dropped: each gradient already feathers to
   transparent, which is the soft edge. About 0.22 at its peak (the tokens'
   own alpha times the blobs' 0.4). Outside the camera world, so no camera
   move drags the light with it. */
.reveel-stage > .aurora-bg {
    position: absolute;
    inset: 0;
    z-index: 0;
}
.reveel-stage > .aurora-bg .aurora-blob {
    filter: none;
    opacity: 0.4;
}
.reveel-stage > .aurora-bg .aurora-blob-1 {
    width: 110vw;
    height: 110vw;
    max-width: 900px;
    max-height: 900px;
    top: 4%;
    left: auto;
    right: calc(min(55vw, 450px) * -1);
    background: radial-gradient(circle,
        var(--edge-wine) 0%,
        rgba(74, 25, 66, 0.18) 42%,
        transparent 70%);
}
.reveel-stage > .aurora-bg .aurora-blob-2 {
    width: 100vw;
    height: 100vw;
    max-width: 820px;
    max-height: 820px;
    top: auto;
    bottom: calc(min(42vw, 340px) * -1);
    right: auto;
    left: calc(min(48vw, 390px) * -1);
    background: radial-gradient(circle,
        var(--edge-amber) 0%,
        rgba(196, 138, 96, 0.08) 44%,
        transparent 70%);
}
.reveel-stage > .aurora-bg .aurora-blob-3 {
    width: 80vw;
    height: 80vw;
    max-width: 680px;
    max-height: 680px;
    top: 30%;
    background: radial-gradient(circle,
        var(--edge-rose) 0%,
        rgba(212, 160, 160, 0.04) 50%,
        transparent 70%);
}

/* ───── The set-piece canvases: inert, covering the stage ───── */
.fx {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}
.fx-back { z-index: 0; }
.fx-light { z-index: 2; }
.fx-burst { z-index: 4; }

/* ───── The world the camera moves ───── */
.reveel-stage-world {
    z-index: 1;
}

/* ───── Projector dust (sparkles.css) ─────
   About 18 motes over two depth planes, behind every beat: 11 far and
   pin-small, 7 mid. Each plane is pushed back and scaled up by
   (900 + depth) / 900, so at rest it lies at its layout size and a camera
   move gives it parallax. --spark on the dark ground: motes of light, not
   stars, so they twinkle slowly and never brightly. */
.stage-dust {
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.stage-dust--far { transform: translateZ(-600px) scale(1.667); }
.stage-dust--mid { transform: translateZ(-260px) scale(1.289); }

.stage-dust--far .sparkle {
    width: 2px;
    height: 2px;
    box-shadow: 0 0 4px 1px var(--accent-warm-glow-soft);
    animation-duration: 4.2s;
}
.stage-dust--mid .sparkle {
    box-shadow: 0 0 6px 1px var(--accent-warm-glow-soft);
    animation-duration: 5.4s;
}

/* The edge glows and the dust show only where a beat's ground lets them
   through: the picker. premiere, still-watching and end-credits paint their
   own opaque ground (with their own motes and beam), and the browse page,
   the guide and the playback are full-bleed photographs. Everywhere else
   they are taken out of the page, so their looping animations cost no
   style work behind a beat that hides them (demo 365-372). */
.reveel-stage > .aurora-bg,
.stage-dust {
    display: none;
}
.reveel-stage[data-beat="whos-watching"] > .aurora-bg,
.reveel-stage[data-beat="whos-watching"] .stage-dust {
    display: block;
}

/* ───── Beats are screens ─────
   Every beat is a full-bleed layer of the world, the stage's size. Only the
   director changes which one is active, and it is a hard cut on the beat
   boundary: each beat's exit composes the frame for the next and its
   entrance cue reveals it, so there is no fade and no entrance stagger. */
.screen {
    position: absolute;
    inset: 0;
    display: none;
    opacity: 0;
}
.screen.active {
    display: flex;
    opacity: 1;
}

/* Entry states are applied instantly (the spine's prepare on goto), never
   animated in. */
.instant,
.instant *,
.instant *::before,
.instant *::after {
    transition: none !important;
}

/* ───── Mute ─────
   Top right, which every beat leaves free for it (now-showing's top bar
   reserves 100 px). At most 84 px wide. A flat translucent fill: no
   backdrop-filter. */
.stage-mute {
    position: absolute;
    z-index: 8;
    top: calc(12px + env(safe-area-inset-top, 0px));
    right: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    box-sizing: border-box;
    max-width: 84px;
    min-height: 34px;
    padding: 0.45rem 0.7rem;
    font: 500 0.74rem/1 var(--font-body);
    letter-spacing: 0.06em;
    color: var(--text-primary);
    background: var(--glass);
    border: 1px solid var(--glass-border);
    border-radius: 999px;
    cursor: pointer;
    white-space: nowrap;
}
.stage-mute-icon {
    flex: none;
    width: 15px;
    height: 15px;
}
.stage-mute .stage-mute-x { display: none; }
.stage-mute[aria-pressed="true"] .stage-mute-x { display: inline; }
.stage-mute[aria-pressed="true"] .stage-mute-waves { display: none; }
.stage-mute[aria-pressed="true"] {
    color: var(--accent-warm-bright);
    border-color: var(--glass-border-hover);
}
.stage-mute:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 3px;
}

/* ───── Reduced motion: the film still plays in full, calmly ─────
   The camera and shake no-op inside ReveelStage; here the room holds
   still: no edge-glow drift, and the dust stops and rests at half its
   light. */
@media (prefers-reduced-motion: reduce) {
    .reveel-stage > .aurora-bg .aurora-blob {
        animation: none;
    }
    .stage-dust .sparkle {
        animation: none;
        opacity: 0.5;
        transform: none;
    }
}
