/* ZS R3 LIVING-PLATE STAGE (r3-stage.css): the Mythos-style stage engine, ZS's own code. Spec + contract: evidence/r3/final6/ENG/STAGE_ENGINE.md. Behaviour: r3-stage.js.
   WHAT IT IS (David, round 3, template 55 "Mythos00"): a pinned, LIVING plate (film, or a still with code-made ambient motion) stays while the TEXT LAYER swaps on top of it in a timed sequence;
   the copy lives in a mapped SAFE ZONE of the shot (left in landscape, top in portrait) behind a LOCAL dim (a gradient laid over the plate, never a hidden picture); the last state of a scene
   is the subject alone on a clean plate. Timings are Grigoletto's own (TIMING stream, MYTHOS_TIMING_SPEC.md): text pops 0.5 s EASE_OUT on a 0.075 s word step with groups at 0.2 / 0.4 / 0.6 s,
   plate moves 1.25 / 2.084 s "settle", hand-overs 1 s / 2 s expo in-out (G-06 zoom-out-to-card).
   CONTENTS  0 tokens  1 STATIC composition (default: reduced motion, no JS, phones without the engine)  2 LIVE pin (.is-live)  3 plates, media, poses, hand-over  4 safe zones, local dim  5 states + text cascade
             6 aperture opener  7 ambient (flicker, caustics, canvas, push-in)  8 index + meta (caption, pause control)  9 FREE scenes (no pin)  10 hero ambient (candle flames)  11 reduced motion
   Markup (full contract in STAGE_ENGINE.md):
     <div class="r3s" data-r3s [data-r3s-open=".6"]>  .r3s__pin > .r3s__world[data-world=a|b] > .r3s__plate (> .r3s__media (img + video) .r3s__ambient .r3s__dim .r3s__shade .r3s__meta)
                                                         + .r3s__states (> .r3s__state[data-len][data-pose=text|clean|zoom][data-idx]) ; .r3s__idx (ticks) ; .r3s__open (aperture headline)
   Only compositor-friendly properties animate (opacity, transform, translate, scale, clip-path on the aperture, background layers moved by transform). No layout property is animated. */

/* ================================ 0. TOKENS ================================ */
:root {
  --r3s-floor: #0C0C0F; --r3s-gold: #DCBC7E; --r3s-ink: #F3F0EA; --r3s-ink2: #D9D3C8;
  --r3s-vh: 100vh; --r3s-u: max(1vh, 5px);   /* runway unit = 1 % of max(window height, 500 px): a short landscape phone still gets a scroll length a thumb can step through (TIMING spec C2) */
  --r3s-edge: max(var(--gutter, 24px), calc((100vw - var(--wrap, 1320px)) / 2));   /* the left edge of the wrap: copy and the header logo share it */
  --r3s-nav: var(--nav-h, 68px);
  /* TIMING (MYTHOS_TIMING_SPEC.md D / tokens.json) */
  --tm-ease-quick: cubic-bezier(0, 0, .58, 1);
  --tm-ease-settle: cubic-bezier(.304, .714, 0, 1);
  --tm-ease-handover: cubic-bezier(1, 0, 0, 1);
  --tm-d-micro: .2s; --tm-d-quick: .3s; --tm-d-text: .5s;
  --tm-d-calm-short: .625s; --tm-d-calm: 1.25s;
  --tm-d-sig: 2.084s; --tm-d-sig-finale: 3.683s;
  --tm-d-hand: 1s; --tm-d-hand-long: 2s;
  --tm-step-word: .075s; --tm-group-a: .2s; --tm-group-b: .4s; --tm-group-c: .6s;
}
@supports (height: 1svh) { :root { --r3s-vh: 100svh; --r3s-u: max(1svh, 5px); } }
@supports (transition-timing-function: linear(0, 1)) {
  :root { --tm-ease-settle: linear(0, 0.0015 0.5%, 0.0058 1%, 0.0216 2%, 0.0451 3%, 0.0747 4%, 0.1086 5%, 0.1458 6%, 0.2255 8%, 0.3076 10%, 0.3879 12%, 0.4638 14%, 0.5665 17%, 0.6542 20%, 0.7272 23%, 0.8038 27%, 0.8606 31%, 0.9104 36%, 0.9481 42%, 0.9731 49%, 0.9876 57%, 0.9949 66%, 0.9982 76%, 0.9995 87%, 1); }
}

/* ================================ 1. STATIC COMPOSITION (the default) ================================ */
/* No pin. Each world is a block: its plate (a photograph band), then its copy as a ledger. The page holds up as a screenshot with every effect off (reduced motion, no JS). */
.r3s { position: relative; isolation: isolate; background: var(--r3s-floor); color: var(--r3s-ink); color-scheme: dark;
  --ink: #F3F0EA; --ink-2: #CFCAC1; --ink-3: #A7A298; --gold: #DCBC7E; --line: rgba(243, 240, 234, .18); --line-2: rgba(243, 240, 234, .09); --accent: #A48FFF; --bg: var(--r3s-floor); }
.r3s__pin { position: relative; }
.r3s__world { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); }
.r3s__plate { position: relative; overflow: hidden; background: var(--r3s-floor); aspect-ratio: 4 / 5; max-height: 76vh; max-height: 76svh; width: 100%; }
/* the band melts into the floor above and below (tone rule: no photographic edge). ENG2 (CRIT-MOTION caption contrast): the mask sits on the PICTURE and the ambient layers, not on the plate, so the caption pill
   and the pause control on the plate stay fully opaque (they measured 3.5:1 where the plate mask faded them) */
.r3s__plate > .r3s__media, .r3s__plate > .r3s__ambient { -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 24%, #000 76%, transparent 100%); mask-image: linear-gradient(180deg, transparent 0, #000 24%, #000 76%, transparent 100%); }
@media (min-width: 700px) { .r3s__plate { aspect-ratio: 16 / 9; max-height: none; } }
@media (min-width: 1024px) { .r3s__plate { aspect-ratio: 21 / 9; } }
@media (max-height: 520px) and (orientation: landscape) { .r3s__plate { aspect-ratio: 16 / 9; max-height: none; } }
.r3s__media { position: absolute; inset: 0; margin: 0; }
.r3s__media picture { display: block; width: 100%; height: 100%; }
.r3s__media img, .r3s__media video { display: block; width: 100%; height: 100%; object-fit: cover; object-position: var(--fx, 50%) var(--fy, 50%); }
.r3s__media video { position: absolute; inset: 0; opacity: 0; transition: opacity .9s var(--tm-ease-settle); }
.r3s__media video.is-playing { opacity: 1; }
.r3s__ambient, .r3s__dim, .r3s__shade, .r3s__ring, .r3s__idx, .r3s__cv { display: none; }
.r3s__meta { position: absolute; z-index: 6; right: var(--gutter, 16px); bottom: calc(var(--r3-fade, 96px) * .5); display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; max-width: calc(100% - 2 * var(--gutter, 16px)); }
.r3s__meta > * { pointer-events: auto; }
.r3s__meta [data-r3-film-toggle] { display: none; }
.r3s__open { position: absolute; z-index: 5; margin: 0; left: var(--gutter, 16px); right: var(--gutter, 16px); font: 600 clamp(3rem, 1.2rem + 6.6vw, 7.5rem)/.92 var(--r3-f-serif, "Cormorant Garamond", serif); letter-spacing: -.02em; font-variant-numeric: lining-nums; color: var(--r3s-ink); text-wrap: balance; max-width: 11em; }
.r3s__open span + span { color: var(--r3s-gold); }
.r3s__world[data-world="a"] { grid-template-areas: "plate" "states"; }
.r3s__world[data-world="a"] > .r3s__plate { grid-area: plate; }
.r3s__world[data-world="a"] > .r3s__open { grid-area: plate; align-self: end; position: relative; left: auto; right: auto; margin: 0 var(--gutter, 16px) clamp(28px, 6vw, 84px); z-index: 5; }
.r3s__world[data-world="a"] > .r3s__plate::after { content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none; background: linear-gradient(0deg, rgba(12, 12, 15, .92) 0, rgba(12, 12, 15, .78) 28%, rgba(12, 12, 15, .4) 50%, rgba(12, 12, 15, .1) 72%, rgba(12, 12, 15, 0) 88%); }
.r3s__states { display: contents; }
.r3s__in, .r3s__state { min-width: 0; }
.r3s__state--clean, .r3s__state--zoom { display: none; }
.r3s__state { opacity: 1; }
.r3s__list { list-style: none; margin: 0; padding: 0; }
.r3s__state > * { opacity: 1; transform: none; }
.r3s__t { margin: 0; }
.r3s__d { margin: 0; }
.r3s__n { margin: 0; }
.r3s__acc { margin: 0; }
.r3s__acc img { display: block; }

/* ================================ 2. LIVE PIN (.is-live is set by r3-stage.js while motion is allowed) ================================ */
.r3s.is-live { height: calc(var(--r3s-vh) + var(--r3s-run, 400) * var(--r3s-u)); }
.r3s.is-live .r3s__pin { position: sticky; top: 0; height: var(--r3s-vh); overflow: hidden; background: var(--r3s-floor); }
.r3s.is-live .r3s__world { position: absolute; inset: 0; display: block; }
.r3s.is-live .r3s__states { display: block; position: absolute; inset: 0; pointer-events: none; z-index: 8; }
.r3s.is-live .r3s__idx { display: flex; }
.r3s.is-live .r3s__ambient, .r3s.is-live .r3s__dim, .r3s.is-live .r3s__shade { display: block; }
.r3s.is-live .r3s__cv { display: block; }
.r3s.is-live .r3s__meta [data-r3-film-toggle] { display: inline-flex; align-items: center; justify-content: center; gap: .35em; }   /* ENG2: the label sat on the top border of the pill (anonymous flex item, align-items: normal) */
.r3s.is-live .r3s__meta [data-r3-film-toggle][hidden] { display: none; }

/* ================================ 3. PLATES, MEDIA, POSES, HAND-OVER ================================ */
.r3s.is-live .r3s__plate { position: absolute; inset: 0; z-index: 1; aspect-ratio: auto; max-height: none; will-change: transform;
  translate: 0 0; scale: 1; border-radius: 0; transform-origin: 50% 50%; }
.r3s.is-live .r3s__plate > .r3s__media, .r3s.is-live .r3s__plate > .r3s__ambient { -webkit-mask-image: none; mask-image: none; }
.r3s.is-live .r3s__world[data-world="a"] > .r3s__plate::after { display: none; }
.r3s.is-live .r3s__media { z-index: 1; will-change: transform; transform: translate3d(var(--mx, 0%), var(--my, 0%), 0) scale(var(--ms, 1)); transform-origin: 50% 50%;
  transition: transform var(--tm-d-sig) var(--tm-ease-settle); }
/* POSES (T-class, real time, the recorded 2.084 s "settle"): text = the plate makes room for the copy (shifts away from the safe zone), clean = the subject alone, centred */
@media (orientation: landscape) {
  .r3s[data-pose="text"] .r3s__world.is-active .r3s__media { --mx: var(--r3s-mx, 9%); --ms: 1.015; }
}
@media (orientation: portrait) {
  /* portrait: the plate makes room at the TOP (the safe zone): it slides down (--r3s-my) and/or settles to a smaller picture anchored at the foot (--r3s-ms < 1, --r3s-oy 100%: the source is never enlarged) */
  .r3s[data-pose="text"] .r3s__world.is-active .r3s__media { --my: var(--r3s-my, 15%); --ms: var(--r3s-ms, 1.015); transform-origin: 50% var(--r3s-oy, 50%); }
  .r3s__media img, .r3s__media video { object-position: var(--fxp, var(--fx, 50%)) var(--fyp, var(--fy, 50%)); }
  /* a plate that settles to a smaller picture (--r3s-ms < 1) needs a media box wider than the stage, or its sides would show as hard edges */
  .r3s.is-live .r3s__world[data-world="b"] .r3s__media { left: -32%; right: -32%; -webkit-mask-image: linear-gradient(180deg, transparent 0, rgba(0, 0, 0, .55) 9%, #000 20%); mask-image: linear-gradient(180deg, transparent 0, rgba(0, 0, 0, .55) 9%, #000 20%); }   /* the picture melts into the floor at its top (tone rule: no photographic edge) */
}
.r3s[data-pose="clean"] .r3s__world.is-active .r3s__media { --ms: 1.04; transition-duration: var(--tm-d-sig-finale); }   /* the finale: the one creeping move, 3.683 s (Mythos00's spring) */
.r3s[data-pose="zoom"] .r3s__world.is-active .r3s__media { --ms: 1.1; }
/* HAND-OVER (G-06 zoom-out-to-card, T-class: scale 1 s, glide 2 s, expo in-out, Paradise 12 x 1 s / 5 x 2 s). Roles are set by the engine: .is-full = the plate that fills the frame, .is-parked = the other */
.r3s { --r3s-ho-zoom: calc(.9s * var(--hk, 1)); --r3s-ho-glide: calc(1.5s * var(--hk, 1)); --r3s-ho-lag: calc(.45s * var(--hk, 1)); --r3s-ho-grow: calc(1.3s * var(--hk, 1)); }   /* Paradise's 1 s / 2 s scaled to 2.2 s in all (STAGE_ENGINE.md); ENG2: --hk = 1 calm, .85 / .7 while the visitor scrolls fast, set by the engine at the commit that changes the world; the next state's copy waits for the hand-over (time latch) */
.r3s.is-live .r3s__world.is-parked > .r3s__plate { translate: var(--park, 112%) 0; scale: .62; border-radius: 30px;
  transition: scale var(--r3s-ho-zoom) var(--tm-ease-handover) 0s, translate var(--r3s-ho-glide) var(--tm-ease-handover) var(--r3s-ho-lag), border-radius var(--r3s-ho-zoom) var(--tm-ease-handover) 0s; }
.r3s.is-live .r3s__world[data-world="a"].is-parked > .r3s__plate { --park: -112%; }
.r3s.is-live .r3s__world.is-full > .r3s__plate { translate: 0 0; scale: 1; border-radius: 0;
  transition: translate var(--r3s-ho-glide) var(--tm-ease-handover) var(--r3s-ho-lag), scale var(--r3s-ho-zoom) var(--tm-ease-handover) var(--r3s-ho-grow), border-radius var(--r3s-ho-zoom) var(--tm-ease-handover) var(--r3s-ho-grow); }
.r3s.is-live .r3s__world.is-parked { pointer-events: none; }
/* the zoom-out to the examples (last state of the scene): the plate becomes a card on the floor and scrolls away with the pin */
.r3s.is-live[data-pose="zoom"] .r3s__world.is-full > .r3s__plate { scale: .64; border-radius: 30px; box-shadow: 0 50px 120px -40px rgba(0, 0, 0, .9), 0 0 140px -30px rgba(var(--r3s-glow, 132, 81, 105), .38);
  transition: scale var(--tm-d-hand) var(--tm-ease-handover) 0s, border-radius var(--tm-d-hand) var(--tm-ease-handover) 0s, box-shadow var(--tm-d-hand) var(--tm-ease-handover) 0s; }
/* the first paint of the pin: no transition until the engine has placed the worlds (is-set) */
.r3s.is-live:not(.is-set) .r3s__plate, .r3s.is-live:not(.is-set) .r3s__media, .r3s.is-live:not(.is-set) .r3s__shade { transition: none !important; }
.r3s.is-live:not(.is-set) .r3s__world[data-fit~="air"] .r3s__media picture, .r3s.is-live:not(.is-set) .r3s__world[data-fit~="air"] .r3s__media video { transition: none !important; }   /* v1.2: the framed pictures too */

/* ================================ 4. SAFE ZONES + LOCAL DIM ================================ */
/* The copy lives in the plate's safe zone: LEFT in landscape, TOP in portrait. The plate is not hidden: a gradient in the page's own black (the floor of the grade) lies over the zone, so the type
   keeps AA and the subject stays visible next to it. In the clean pose the shade is gone and the subject is alone. */
.r3s__shade { position: absolute; inset: 0; z-index: 3; pointer-events: none; opacity: 0; transition: opacity var(--tm-d-calm) var(--tm-ease-settle);
  background: linear-gradient(90deg, rgba(12, 12, 15, .97) 0, rgba(12, 12, 15, .95) 22%, rgba(12, 12, 15, .82) 34%, rgba(12, 12, 15, .5) 47%, rgba(12, 12, 15, .18) 60%, rgba(12, 12, 15, .04) 70%, rgba(12, 12, 15, 0) 78%); }
@media (orientation: portrait) {
  .r3s__shade { background: linear-gradient(180deg, rgba(12, 12, 15, .97) 0, rgba(12, 12, 15, .95) 24%, rgba(12, 12, 15, .82) 36%, rgba(12, 12, 15, .5) 47%, rgba(12, 12, 15, .18) 56%, rgba(12, 12, 15, .04) 63%, rgba(12, 12, 15, 0) 70%); }
}
.r3s[data-pose="text"] .r3s__world.is-active .r3s__shade { opacity: 1; }
.r3s__dim { position: absolute; inset: 0; z-index: 2; pointer-events: none; background: radial-gradient(120% 110% at 55% 50%, rgba(12, 12, 15, 0) 52%, rgba(12, 12, 15, .5) 100%); }   /* the vignette of the grade, always on */

/* ================================ 5. STATES + TEXT CASCADE ================================ */
.r3s.is-live .r3s__state { position: absolute; left: var(--r3s-edge); width: min(40vw, 620px); top: 50%; margin: 0; padding: 0; transform: translate3d(0, -50%, 0); pointer-events: none; opacity: 1; visibility: visible; }
.r3s.is-live .r3s__list { display: block; }
.r3s.is-live .r3s__list > .r3s__state { position: absolute; }
.r3s.is-live .r3s__state--clean, .r3s.is-live .r3s__state--zoom { display: block; width: 0; height: 0; overflow: hidden; }
@media (orientation: portrait) {
  .r3s.is-live .r3s__state { left: var(--gutter, 16px); right: var(--gutter, 16px); width: auto; top: calc(var(--r3s-nav) + 22px); transform: none; }
}
@media (max-height: 520px) and (orientation: landscape) { .r3s.is-live .r3s__state { width: min(46vw, 460px); } }
/* OTHER SAFE ZONES (data-zone on a .r3s__world; the default is left in landscape, top in portrait). The shade mirrors with a flip, the plate makes room on the opposite side.
     right   landscape: copy at the right edge, shade and plate shift mirrored         bottom  copy in the lower band (both orientations), shade from the foot
     center  landscape + portrait: a centred statement, a soft radial dim behind it, the plate does not shift                                                                                 */
@media (orientation: landscape) {
  .r3s__world[data-zone="right"] .r3s__shade { transform: scaleX(-1); }
  .r3s.is-live .r3s__world[data-zone="right"] .r3s__state { left: auto; right: var(--r3s-edge); }
  .r3s[data-pose="text"] .r3s__world[data-zone="right"].is-active .r3s__media { --mx: calc(var(--r3s-mx, 9%) * -1); }
}
.r3s__world[data-zone="bottom"] .r3s__shade { background: linear-gradient(180deg, rgba(12, 12, 15, .97) 0, rgba(12, 12, 15, .95) 24%, rgba(12, 12, 15, .82) 36%, rgba(12, 12, 15, .5) 47%, rgba(12, 12, 15, .18) 56%, rgba(12, 12, 15, .04) 63%, rgba(12, 12, 15, 0) 70%); transform: scaleY(-1); }
.r3s.is-live .r3s__world[data-zone="bottom"] .r3s__state { top: auto; bottom: calc(var(--r3s-bottom, 56px) + env(safe-area-inset-bottom, 0px)); transform: none; width: min(64vw, 820px); }
.r3s[data-pose="text"] .r3s__world[data-zone="bottom"].is-active .r3s__media { --mx: 0%; --my: calc(var(--r3s-mb, 12%) * -1); }
@media (orientation: portrait) {
  .r3s.is-live .r3s__world[data-zone="bottom"] .r3s__state { left: var(--gutter, 16px); right: var(--gutter, 16px); width: auto; bottom: calc(var(--r3s-bottom, 56px) + 76px); }
  .r3s[data-pose="text"] .r3s__world[data-zone="bottom"].is-active .r3s__media { --r3s-oy: 50%; }
}
.r3s__world[data-zone="center"] .r3s__shade { background: radial-gradient(62% 56% at 50% 50%, rgba(12, 12, 15, .86), rgba(12, 12, 15, .55) 52%, rgba(12, 12, 15, 0) 82%); }
.r3s.is-live .r3s__world[data-zone="center"] .r3s__state { left: 50%; right: auto; width: min(70vw, 860px); transform: translate3d(-50%, -50%, 0); text-align: center; top: 50%; }
.r3s[data-pose="text"] .r3s__world[data-zone="center"].is-active .r3s__media { --mx: 0%; --my: 0%; }
/* the cascade: every direct piece of a state is an item; it is hidden until its state is on. Exit is quick and undelayed; entry follows the Mythos00 chain (group a .2 s, b .4 s, c .6 s, word step .075 s) */
/* ENG2 (critic fix): --ck is the cascade factor the engine sets on the state that comes on (1 = the calm Grigoletto cascade, .72 / .5 = compact, while the visitor scrolls fast), --st-delay a wait for a plate in
   transit. EXIT = the whole state fades in .25 s, undelayed; the words stay in their masks (no glyph slivers, no flicker of half-risen words) and reset after the fade. ENTRY = the calm chain below. */
.r3s.is-live .r3s__state { --ck: 1; }
.r3s.is-live .r3s__state > * { opacity: 0; transform: translate3d(0, 12px, 0); transition: opacity .25s var(--tm-ease-quick) 0s, transform .25s var(--tm-ease-quick) 0s; }
.r3s.is-live .r3s__state .r3s-w { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: .16em; margin-bottom: -.16em; }
.r3s.is-live .r3s__state .r3s-w > span { display: inline-block; transform: translate3d(0, 115%, 0); transition: transform 0s linear .3s; }
.r3s.is-live .r3s__state > .r3s__t { transform: none; }                  /* the title is made of masked words: the wrapper only fades, each word rises */
.r3s.is-live .r3s__state.is-on > * { opacity: 1; transform: none; transition: opacity calc(var(--tm-d-text) * var(--ck, 1)) var(--tm-ease-quick) calc(var(--st-delay, 0s) + var(--tm-group-a) * var(--ck, 1)), transform calc(var(--tm-d-text) * var(--ck, 1)) var(--tm-ease-quick) calc(var(--st-delay, 0s) + var(--tm-group-a) * var(--ck, 1)); }
.r3s.is-live .r3s__state.is-on > [data-g="b"] { transition-delay: calc(var(--st-delay, 0s) + var(--tm-group-b) * var(--ck, 1)); }
.r3s.is-live .r3s__state.is-on > [data-g="c"] { transition-delay: calc(var(--st-delay, 0s) + var(--tm-group-c) * var(--ck, 1)); }
.r3s.is-live .r3s__state.is-on > .r3s__t { transition: none; }           /* the wrapper shows at once; its words are still below their masks until their own delay */
.r3s.is-live .r3s__state.is-on .r3s-w > span { transform: none; transition: transform calc(var(--tm-d-text) * var(--ck, 1)) var(--tm-ease-quick) calc(var(--st-delay, 0s) + (var(--tm-group-a) + var(--i, 0) * var(--tm-step-word)) * var(--ck, 1)); }
.r3s.is-live .r3s__state.is-on { pointer-events: auto; }
/* items that the engine has not split (no JS word split yet) still show */
.r3s.is-live .r3s__state > .r3s__t:not([data-r3s-done]) { opacity: 0; }
.r3s.is-live .r3s__state.is-on > .r3s__t:not([data-r3s-done]) { opacity: 1; transition: opacity calc(var(--tm-d-text) * var(--ck, 1)) var(--tm-ease-quick) calc(var(--st-delay, 0s) + var(--tm-group-a) * var(--ck, 1)); }

/* ================================ 6. APERTURE OPENER (G-03, W-05, template 53; scrubbed by the engine: --e = eased 0..1 over the opening) ================================ */
.r3s.is-live[data-r3s-open] .r3s__world[data-world="a"] > .r3s__plate { clip-path: circle(calc(var(--r3s-r0, 17vmin) + var(--e, 1) * 118vmax) at 50% 50%); }
.r3s.is-live[data-r3s-open].is-opened .r3s__world[data-world="a"] > .r3s__plate { clip-path: none; }
.r3s.is-live[data-r3s-open] .r3s__world[data-world="a"] .r3s__media { transform: translate3d(var(--mx, 0%), calc(var(--my, 0%) + (1 - var(--e, 1)) * var(--r3s-oy0, -8%)), 0) scale(calc(var(--ms, 1) * (1 + (1 - var(--e, 1)) * .18))); transition-property: none; }
.r3s.is-live[data-r3s-open].is-opened .r3s__world[data-world="a"] .r3s__media { transition-property: transform; }   /* once the window is open the poses glide again (the opening itself is scrubbed, no transition) */
.r3s.is-live .r3s__ring { position: absolute; z-index: 2; left: 50%; top: 50%; width: calc(var(--r3s-r0, 17vmin) * 2); height: calc(var(--r3s-r0, 17vmin) * 2); margin: calc(var(--r3s-r0, 17vmin) * -1) 0 0 calc(var(--r3s-r0, 17vmin) * -1);
  border-radius: 50%; pointer-events: none; display: block; box-shadow: 0 0 0 1px rgba(220, 188, 126, .6), 0 0 80px 8px rgba(220, 188, 126, .12); opacity: calc(1 - var(--e, 1) * 3); }
.r3s.is-live[data-r3s-open] { --r3s-r0: clamp(96px, 17vmin, 260px); }
@media (orientation: portrait) { .r3s.is-live[data-r3s-open] { --r3s-r0: clamp(92px, 25vmin, 210px); --r3s-oy0: -30%; } }   /* the flames of the portrait clip sit low in the frame: the window starts on them */
.r3s.is-live .r3s__open { position: absolute; z-index: 7; inset: 0; margin: 0; max-width: none; pointer-events: none; align-self: auto; grid-area: auto; font-size: clamp(2.6rem, 1rem + 6.4vw, 8rem); opacity: calc(1.6 - var(--e, 1) * 5); }
/* ENG2 (CRIT-TECH: the headline was 1:1 over bright flame while it faded): every word carries its own dark halo, a real element (not a text-shadow) that travels with it, so the type keeps AA on the film
   behind it; it fades with the word. The window itself starts dimmer and warmer (CRIT-MOTION: the portrait orb was a blown-out white disc) and rises to full brightness as it opens. */
.r3s.is-live .r3s__open span::before { content: ""; position: absolute; z-index: -1; inset: -.45em -1.4em; pointer-events: none; background: radial-gradient(closest-side, rgba(12, 12, 15, .86) 0, rgba(12, 12, 15, .84) 64%, rgba(12, 12, 15, 0) 100%); }
.r3s.is-live[data-r3s-open] .r3s__world[data-world="a"] > .r3s__plate::before { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; background: radial-gradient(closest-side at 50% 50%, rgba(40, 14, 2, .5), rgba(40, 14, 2, .34)); opacity: calc(1 - var(--e, 1) * 1.8); }
.r3s.is-live .r3s__open span { position: absolute; top: 50%; white-space: nowrap; line-height: .9; }
.r3s.is-live .r3s__open span:first-child { right: calc(50% + var(--r3s-r0, 17vmin) + 1.2rem); transform: translate(calc(var(--e, 1) * -34vw), -50%); }
.r3s.is-live .r3s__open span + span { left: calc(50% + var(--r3s-r0, 17vmin) + 1.2rem); transform: translate(calc(var(--e, 1) * 34vw), -50%); }
@media (orientation: portrait) {
  .r3s.is-live .r3s__open { font-size: clamp(2.8rem, 1.2rem + 9vw, 5rem); }
  .r3s.is-live .r3s__open span { left: 0; right: 0; text-align: center; }
  .r3s.is-live .r3s__open span::before { inset: -.4em 6%; }
  .r3s.is-live .r3s__open span:first-child { right: 0; top: calc(50% - var(--r3s-r0, 25vmin) - 1.1rem); transform: translate(0, calc(-100% + var(--e, 1) * -34svh)); }
  .r3s.is-live .r3s__open span + span { left: 0; top: calc(50% + var(--r3s-r0, 25vmin) + 1.1rem); transform: translate(0, calc(var(--e, 1) * 34svh)); }
}
.r3s.is-live[data-r3s-open] .r3s__world[data-world="a"] > .r3s__plate .r3s__meta { opacity: clamp(0, (var(--e, 1) - .5) * 12, 1); }
/* ENG2 (CRIT-TECH MAJOR, invisible focus target): the caption + pause control cannot be reached by keyboard while the window is still opening; a focused control is always drawn in full */
.r3s.is-live[data-r3s-open]:not(.is-ap-ready) .r3s__world[data-world="a"] > .r3s__plate .r3s__meta { visibility: hidden; }
.r3s.is-live .r3s__world .r3s__meta:focus-within { opacity: 1 !important; visibility: visible !important; transition: none !important; }
.r3s.is-live:not([data-r3s-open]) .r3s__open, .r3s.is-live:not([data-r3s-open]) .r3s__ring { display: none; }

/* ================================ 7. AMBIENT: code-made life (flicker, caustics, canvas particles, push-in) ================================ */
.r3s__ambient { position: absolute; inset: 0; z-index: 2; pointer-events: none; overflow: hidden; }
.r3s__cv { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/* flame world, until/while the film runs: a warm light that breathes in the bottom of the frame (two incommensurate cycles, opacity only) */
.r3s__flick { position: absolute; inset: auto -10% -6% -10%; height: 62%; background: radial-gradient(52% 70% at 50% 100%, rgba(255, 150, 60, .34), rgba(255, 120, 40, .12) 48%, rgba(255, 110, 30, 0) 76%); mix-blend-mode: screen; opacity: .8;
  animation: r3s-flick 2.9s steps(1, end) infinite, r3s-breathe 6.3s ease-in-out infinite alternate; }
.r3s__flick::after { content: ""; position: absolute; inset: 24% 18% 0 30%; background: radial-gradient(48% 62% at 50% 100%, rgba(255, 196, 120, .3), rgba(255, 170, 90, 0) 70%); animation: r3s-flick2 3.7s steps(1, end) infinite; }
.r3s__media.has-film ~ .r3s__ambient .r3s__flick, .r3s__plate.has-film .r3s__flick { opacity: .38; }
@keyframes r3s-flick { 0% { opacity: .86; } 9% { opacity: .66; } 17% { opacity: .92; } 26% { opacity: .72; } 38% { opacity: 1; } 47% { opacity: .78; } 59% { opacity: .9; } 71% { opacity: .64; } 83% { opacity: .96; } 100% { opacity: .82; } }
@keyframes r3s-flick2 { 0% { opacity: 1; } 14% { opacity: .55; } 31% { opacity: .9; } 44% { opacity: .5; } 62% { opacity: 1; } 78% { opacity: .62; } 100% { opacity: .95; } }
@keyframes r3s-breathe { from { transform: translate3d(0, 2%, 0) scale(.97, .94); } to { transform: translate3d(0, 0, 0) scale(1.03, 1.05); } }
/* water world: two drifting caustic layers (the texture is generated by code, assets/zs/img/r3-stage-caustic-512.webp; translate only, one tile per loop = seamless) */
.r3s__cw { position: absolute; inset: 0; overflow: hidden; -webkit-mask-image: linear-gradient(0deg, #000 0, #000 22%, rgba(0, 0, 0, .35) 46%, transparent 64%); mask-image: linear-gradient(0deg, #000 0, #000 22%, rgba(0, 0, 0, .35) 46%, transparent 64%); }   /* light on the water surface below the face, never over the skin */
.r3s__caus { position: absolute; left: calc(var(--tile, 820px) * -1); top: calc(var(--tile, 820px) * -1); right: 0; bottom: 0; background: url(/assets/zs/img/r3-stage-caustic-512.webp) 0 0 / var(--tile, 820px) var(--tile, 820px) repeat; opacity: .065; will-change: transform; animation: r3s-caus-a 70s linear infinite; mix-blend-mode: screen; }
.r3s__caus--b { --tile: 560px; opacity: .045; animation-name: r3s-caus-b; animation-duration: 50s; }
@keyframes r3s-caus-a { to { transform: translate3d(var(--tile, 820px), calc(var(--tile, 820px) * .5), 0); } }
@keyframes r3s-caus-b { to { transform: translate3d(calc(var(--tile, 560px) * -1), calc(var(--tile, 560px) * .75), 0); } from { transform: translate3d(0, 0, 0); } }
.r3s__glow { position: absolute; inset: 0; background: radial-gradient(46% 52% at 62% 46%, rgba(255, 190, 160, .16), rgba(255, 170, 140, 0) 70%); mix-blend-mode: screen; animation: r3s-glow 9s ease-in-out infinite alternate; }
@keyframes r3s-glow { from { opacity: .55; transform: scale(.96); } to { opacity: 1; transform: scale(1.06); } }
/* ENG2 (CRIT-MOTION: the water world was almost a still, motion energy 1.3-2.9): a broad band of warm light travels across the water and the skin like sun through a moving surface (opacity + translate only, 13 s, no blend mode) */
.r3s__sweep { position: absolute; inset: -10% -45%; background: linear-gradient(102deg, rgba(255, 190, 140, 0) 36%, rgba(255, 190, 140, .09) 45%, rgba(255, 214, 176, .2) 50%, rgba(255, 190, 140, .09) 55%, rgba(255, 190, 140, 0) 64%); animation: r3s-sweep 13s ease-in-out infinite; will-change: transform, opacity; }
@keyframes r3s-sweep { 0% { transform: translate3d(-30%, 0, 0); opacity: 0; } 22% { opacity: 1; } 78% { opacity: 1; } 100% { transform: translate3d(30%, 0, 0); opacity: 0; } }
/* a still plate breathes: slow push-in on the poster itself (G-33), compositor only; the film plays over it and needs none */
.r3s__media > picture > img { transform-origin: 50% 55%; animation: r3s-push 30s ease-in-out infinite alternate; will-change: transform; }
.r3s__media.has-film > picture > img { animation: none; }
@keyframes r3s-push { from { transform: scale(1); } to { transform: scale(1.055); } }
/* the engine pauses everything that is off screen: .is-paused on the scene stops the CSS loops too */
.r3s.is-paused .r3s__flick, .r3s.is-paused .r3s__flick::after, .r3s.is-paused .r3s__caus, .r3s.is-paused .r3s__glow, .r3s.is-paused .r3s__sweep, .r3s.is-paused .r3s__media > picture > img { animation-play-state: paused; }

/* ================================ 8. INDEX TICKS + META (caption, pause control) ================================ */
.r3s__idx { position: absolute; z-index: 9; right: max(var(--gutter, 16px), calc((100vw - var(--wrap, 1320px)) / 2 - 8px)); top: 50%; transform: translateY(-50%); flex-direction: column; gap: 14px; align-items: flex-end; pointer-events: none; opacity: 0; transition: opacity var(--tm-d-calm) var(--tm-ease-settle); }
.r3s__idx i { display: block; width: 16px; height: 2px; border-radius: 1px; background: rgba(243, 240, 234, .32); transition: width var(--tm-d-quick) var(--tm-ease-quick), background-color var(--tm-d-quick) var(--tm-ease-quick); }
.r3s__idx i.is-on { width: 34px; background: var(--r3s-gold); }
.r3s__idx i.is-past { background: rgba(220, 188, 126, .55); }
.r3s.is-idx .r3s__idx { opacity: 1; }
@media (orientation: portrait) {
  .r3s__idx { top: auto; bottom: calc(18px + 72px); right: auto; left: var(--gutter, 16px); transform: none; flex-direction: row; align-items: center; gap: 9px; }
  .r3s__idx i { height: 3px; width: 12px; }
  .r3s__idx i.is-on { width: 26px; }
}
@media (max-height: 520px) and (orientation: landscape) { .r3s__idx { gap: 9px; } }
.r3s.is-live .r3s__meta { left: auto; right: var(--gutter, 16px); bottom: calc(18px + env(safe-area-inset-bottom, 0px)); z-index: 9; }
@media (orientation: portrait) { .r3s.is-live .r3s__meta { left: var(--gutter, 16px); right: var(--gutter, 16px); justify-content: flex-start; bottom: calc(18px + 76px); } }   /* above the phone dock */
.r3s.is-live .r3s__world:not(.is-active) .r3s__meta { opacity: 0; visibility: hidden; transition: opacity .3s, visibility 0s .3s; }
.r3s.is-live .r3s__world.is-active .r3s__meta { opacity: 1; visibility: visible; transition: opacity .6s var(--tm-ease-settle) .5s, visibility 0s; }
.r3s .r3p-credit { display: inline-flex; align-items: center; max-width: 100%; margin: 0; padding: 8px 14px; border-radius: 999px; background: #0C0C0F; border: 1px solid rgba(243, 240, 234, .16); color: var(--r3s-ink); font: 500 .8125rem/1.3 var(--r3-f-text, Inter, sans-serif); }
.r3s .r3p-film__btn { position: relative; min-height: 44px; min-width: 44px; padding: 0 16px; border-radius: 999px; background: #0C0C0F; border: 1px solid rgba(243, 240, 234, .3); color: var(--r3s-ink); font: 600 .8125rem/1 var(--r3-f-text, Inter, sans-serif); cursor: pointer; }
.r3s .r3p-film__btn:hover { border-color: rgba(243, 240, 234, .6); }
.r3s .r3p-film__btn:focus-visible { outline: 2px solid var(--r3s-gold); outline-offset: 3px; }
.r3s .r3p-film__btn[hidden] { display: none; }

/* ================================ 9. FREE SCENES (no pin: a living plate in the page flow; the cascade starts when the scene is in view) ================================ */
.r3s--free { overflow-x: clip; }
.r3s--free .r3s__plate { position: relative; }
html.lib-on .r3s--free .r3s__state > * { opacity: 0; transform: translate3d(0, 20px, 0); transition: opacity var(--tm-d-text) var(--tm-ease-quick) 0s, transform var(--tm-d-text) var(--tm-ease-quick) 0s; }
html.lib-on .r3s--free.is-on .r3s__state > * { opacity: 1; transform: none; transition-delay: var(--d, .2s); }
html.lib-on .r3s--free .r3s__plate { opacity: 0; transform: scale(1.04); transition: opacity var(--tm-d-calm) var(--tm-ease-settle), transform var(--tm-d-sig) var(--tm-ease-settle); }
html.lib-on .r3s--free.is-on .r3s__plate { opacity: 1; transform: none; }
html.lib-on .r3s--free:not(.is-armed) .r3s__state > *, html.lib-on .r3s--free:not(.is-armed) .r3s__plate { opacity: 1; transform: none; transition: none; }   /* until the engine is ready everything shows (no flash of nothing) */
/* ENG2 (CRIT-TECH MAJOR, invisible focused control): a keyboard visitor who tabs into the scene before its cascade has played gets everything at once, never a focused control at opacity 0 */
html.lib-on .r3s--free:focus-within .r3s__state > *, html.lib-on .r3s--free:focus-within .r3s__plate { opacity: 1; transform: none; transition: none; }

/* ================================ 10. HERO AMBIENT (the candle table lives: candle flames, a light pool, dust; push-in) ================================ */
.r3s-push { position: relative; transform-origin: 50% 76%; }
.r3p-hero__plate picture { display: block; width: 100%; height: 100%; }
.r3s-push > picture { display: block; }
html:not(.no-motion) .r3s-push { animation: r3s-hero-push 34s ease-in-out infinite alternate; will-change: transform; }
@keyframes r3s-hero-push { from { transform: scale(1); } to { transform: scale(1.05); } }
.r3s-flame, .r3s-pool { position: absolute; left: 0; top: 0; pointer-events: none; display: none; }
html:not(.no-motion) .r3s-flame, html:not(.no-motion) .r3s-pool { display: block; }
.r3s-flame { width: calc(var(--fs, 16px)); height: calc(var(--fs, 16px) * 2.9); margin: calc(var(--fs, 16px) * -2.6) 0 0 calc(var(--fs, 16px) * -.5); transform-origin: 50% 100%; opacity: 0; transition: opacity .6s ease; }
.r3s-flame.is-set { opacity: 1; }
.r3s-flame i { position: absolute; inset: 0; border-radius: 52% 52% 48% 48% / 74% 74% 26% 26%; background: radial-gradient(50% 60% at 50% 74%, #FFF3D0 0, #FFD488 34%, #FF9A3C 66%, rgba(255, 110, 20, 0) 100%); filter: blur(.5px); animation: r3s-fl-a 1.9s ease-in-out infinite alternate, r3s-fl-b 2.7s steps(1, end) infinite; transform-origin: 50% 100%; }
.r3s-flame::before { content: ""; position: absolute; left: 50%; top: 46%; width: calc(var(--fs, 16px) * 7); height: calc(var(--fs, 16px) * 7); margin: calc(var(--fs, 16px) * -3.5) 0 0 calc(var(--fs, 16px) * -3.5); border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 168, 80, .34), rgba(255, 140, 50, .12) 52%, rgba(255, 120, 30, 0) 100%); mix-blend-mode: screen; animation: r3s-halo 2.3s ease-in-out infinite alternate, r3s-fl-b 3.3s steps(1, end) infinite; }
.r3s-flame--b i { animation-duration: 2.3s, 3.1s; animation-delay: -.8s, -1.2s; }
.r3s-flame--b::before { animation-duration: 2.8s, 3.9s; animation-delay: -1.1s, -.4s; }
@keyframes r3s-fl-a { from { transform: scale(.94, .9) skewX(-3deg); } to { transform: scale(1.06, 1.12) skewX(3deg); } }
@keyframes r3s-fl-b { 0% { opacity: .92; } 18% { opacity: .78; } 33% { opacity: 1; } 52% { opacity: .84; } 71% { opacity: .96; } 86% { opacity: .74; } 100% { opacity: .9; } }
@keyframes r3s-halo { from { transform: scale(.9); } to { transform: scale(1.12); } }
.r3s-pool { width: calc(var(--ps, 300px)); height: calc(var(--ps, 300px) * .46); margin: calc(var(--ps, 300px) * -.23) 0 0 calc(var(--ps, 300px) * -.5); background: radial-gradient(closest-side, rgba(255, 150, 70, .3), rgba(255, 130, 50, .1) 56%, rgba(255, 120, 40, 0) 100%); mix-blend-mode: screen; opacity: 0; transition: opacity .8s ease; animation: r3s-pool 5.3s ease-in-out infinite alternate; }
.r3s-pool.is-set { opacity: 1; }
.r3s-pool--w { width: calc(var(--ps, 300px) * 2.1); height: calc(var(--ps, 300px) * .95); margin: calc(var(--ps, 300px) * -.475) 0 0 calc(var(--ps, 300px) * -1.05); background: radial-gradient(closest-side, rgba(255, 140, 64, .17), rgba(255, 130, 50, .06) 58%, rgba(255, 120, 40, 0) 100%); animation-duration: 7.3s; animation-direction: alternate-reverse; }   /* the candles' light spills into the black on the left: the fold is not empty and the headline's own black stays black (below y 40 %) */
@keyframes r3s-pool { from { transform: scale(.94); filter: brightness(.86); } to { transform: scale(1.06); filter: brightness(1.08); } }
.r3p-hero__plate .r3s__cv { z-index: 2; }

/* ================================ 11. REDUCED MOTION / NO JS: nothing here moves ================================ */
html.no-motion .r3s *, html.no-motion .r3s *::before, html.no-motion .r3s *::after, html.no-motion .r3s-push, html.no-motion .r3s-flame, html.no-motion .r3s-pool { animation: none !important; }
html.no-motion .r3s-flame, html.no-motion .r3s-pool, html.no-motion .r3s__cv, html.no-motion .r3s__ambient, html.no-motion .r3s__ring, html.no-motion .r3s__idx { display: none !important; }
html.no-motion .r3s__media video { display: none; }
html.no-motion .r3s--free .r3s__plate, html.no-motion .r3s--free .r3s__state > * { opacity: 1 !important; transform: none !important; transition: none !important; }
html:not(.js) .r3s__media video, html:not(.js) .r3s__cv { display: none; }

/* ---- off screen: the hero host pauses its CSS loops too (the canvas stops by itself, see r3-stage.js) ---- */
.r3p-hero__plate.is-paused .r3s-push, .r3p-hero__plate.is-paused .r3s-flame i, .r3p-hero__plate.is-paused .r3s-flame::before, .r3p-hero__plate.is-paused .r3s-pool { animation-play-state: paused; }

/* ================================ 12. AIR FIT (engine v1.2, ENG3, round 3c): a window that is not the picture's shape gives the picture its own frame ================================ */
/* WHY (David, recording m390_s450: "the fire video is too zoomed in while you scroll"): the portrait clip is 3:4 (720 x 960) and the pinned stage of a phone is 9:19.5 (390 x 844). object-fit: cover
   scales the clip to the stage HEIGHT (844 px) and throws away 38 % of its width: the pan became a flat cream slab, the flames were cropped into a blur, and the aperture (x 1.18) and the poses
   (x 1.015 / 1.04 / 1.1) zoomed it further (1.9x the clip's own frame in the opening window). The same happened to the 16:9 lite clip on a 4:3 tablet (1.42x, both sides of the pan cut off).
   WHAT (opt-in, additive: nothing changes without the attribute): data-fit="air" on a .r3s__world. In a window that is much narrower than the picture's own aspect (portrait and narrower than 5:8,
   i.e. every phone; landscape and narrower than 3:2, i.e. a 4:3 tablet) the world's picture (poster and film are the SAME box, so the film lands exactly on its poster) is laid out in its OWN frame:
   the full window width, its own aspect, standing on the foot of the stage (--r3s-air-b lifts it); its top melts into the floor (--r3s-air-f) and its foot a little (--r3s-air-fb), so there is no
   photographic edge, not even while the aperture or a pose moves it; the copy lives on the floor above it. The pose transforms (shift, push-in, zoom) pivot on the picture's foot (the base of the fire
   stays planted, the picture only breathes upward) and the text pose needs no shift (--r3s-air-my / --r3s-air-mx, default 0). The aperture opener keeps its mechanics; --r3s-oy0 on the world places
   the opening window. In the clean beat the picture glides up on the 3.683 s creep until it is centred between header and dock (the subject alone); as the CARD of the hand-over (parked plate, final zoom pose) it loses its melted
   edges and gets rounded corners on the same expo in-out curve (registered properties --r3s-fe / --r3s-fbe), so the G-06 card stays a clean rounded card. Every other window (desktop, landscape phones, portrait tablets: aspect close to
   the picture's) keeps the cover fit it always had, so nothing changes there (A/B pixel test, evidence/r3/final10/ENG3: 13 states at 5 profiles dark and 3 light, largest difference 1 of 255).
     parameters on the world (all optional)  --r3s-ar  portrait picture aspect (3 / 4)   --r3s-arl  landscape picture aspect (16 / 9)   --r3s-air-b  lift from the foot (0px)
                                              --r3s-air-f  melt length of the top (30 %)   --r3s-air-fb  melt length of the foot (7 %)   --r3s-oy0  aperture start offset (-30 % portrait, -8 % landscape)
                                              --r3s-air-cy  glide of the picture in the clean beat (default: centred between the header and the dock)   --r3s-arh / --r3s-arlh  picture height per width (1.3333 / .5625), only for the centring maths
   A scene that uses it must not set a fixed --r3s-my / --r3s-mx for this world on the media itself (on the world is fine: the air rule overrides it). Contract: NICHE_GUIDE.md.
   v1.3 (ENG3F, round 3c fix pass): (1) data-fit="air all" = the same frame in EVERY portrait window (second block at the end of this section); data-fit="air" alone is unchanged. (2) the melted top of the frame is an eased
   7-stop gradient (a short 3-stop ramp showed a photographic edge on a small frame, because the poster and the film are two masked layers that add up). (3) a world with data-fit may use a different picture per
   orientation: the portrait <source> and data-r3-film-portrait name the picture of a portrait window, --r3s-ar is ITS aspect (the Max page: a 3:2 window onto the flame, not the 3:4 crop). */
@media (orientation: portrait) { .r3s__world[data-fit~="air"] { --r3s-air-ar: var(--r3s-ar, 3 / 4); --r3s-air-ph: min(calc(100vw * var(--r3s-arh, 1.3333)), var(--r3s-vh)); --r3s-air-dock: 64px; } }
@media (orientation: landscape) { .r3s__world[data-fit~="air"] { --r3s-air-ar: var(--r3s-arl, 16 / 9); --r3s-air-ph: min(calc(100vw * var(--r3s-arlh, .5625)), var(--r3s-vh)); --r3s-air-dock: 0px; } }
@property --r3s-fe { syntax: '<percentage>'; inherits: false; initial-value: 30%; }   /* effective melt of the top / the foot: registered so that the card of the hand-over can take them to 0 on the zoom-out curve */
@property --r3s-fbe { syntax: '<percentage>'; inherits: false; initial-value: 7%; }
@media (orientation: portrait) and (max-aspect-ratio: 5/8), (orientation: landscape) and (max-aspect-ratio: 3/2) {
  .r3s.is-live .r3s__world[data-fit~="air"] .r3s__media picture,
  .r3s.is-live .r3s__world[data-fit~="air"] .r3s__media video {
    --r3s-fe: var(--r3s-air-f, 30%); --r3s-fbe: var(--r3s-air-fb, 7%);
    position: absolute; inset: auto 0 var(--r3s-air-b, 0px) 0; width: 100%; height: auto; aspect-ratio: var(--r3s-air-ar, 3 / 4); max-height: 100%; overflow: hidden; border-radius: 0;
    -webkit-mask-image: linear-gradient(180deg, transparent 0, rgba(0, 0, 0, .03) calc(var(--r3s-fe) * .18), rgba(0, 0, 0, .12) calc(var(--r3s-fe) * .36), rgba(0, 0, 0, .3) calc(var(--r3s-fe) * .54), rgba(0, 0, 0, .58) calc(var(--r3s-fe) * .74), rgba(0, 0, 0, .86) calc(var(--r3s-fe) * .9), #000 var(--r3s-fe), #000 calc(100% - var(--r3s-fbe)), transparent 100%);
    mask-image: linear-gradient(180deg, transparent 0, rgba(0, 0, 0, .03) calc(var(--r3s-fe) * .18), rgba(0, 0, 0, .12) calc(var(--r3s-fe) * .36), rgba(0, 0, 0, .3) calc(var(--r3s-fe) * .54), rgba(0, 0, 0, .58) calc(var(--r3s-fe) * .74), rgba(0, 0, 0, .86) calc(var(--r3s-fe) * .9), #000 var(--r3s-fe), #000 calc(100% - var(--r3s-fbe)), transparent 100%);
    transition: --r3s-fe var(--tm-d-hand) var(--tm-ease-handover), --r3s-fbe var(--tm-d-hand) var(--tm-ease-handover), border-radius var(--tm-d-hand) var(--tm-ease-handover); }
  .r3s.is-live .r3s__world[data-fit~="air"] .r3s__media video { transition: opacity .9s var(--tm-ease-settle), --r3s-fe var(--tm-d-hand) var(--tm-ease-handover), --r3s-fbe var(--tm-d-hand) var(--tm-ease-handover), border-radius var(--tm-d-hand) var(--tm-ease-handover); }   /* the film keeps its fade-in over the poster */
  .r3s.is-live .r3s__world[data-fit~="air"] .r3s__media { transform-origin: 50% calc(100% - var(--r3s-air-b, 0px)); --r3s-my: var(--r3s-air-my, 0%); --r3s-mx: var(--r3s-air-mx, 0%); }   /* the picture already stands below / apart from the copy: the text pose needs no shift */
  /* the beat without copy ("the subject alone", the finale of the world): the picture glides up on the 3.683 s creeping move until it is centred between the header and the dock (--r3s-air-cy overrides) */
  .r3s[data-pose="clean"] .r3s__world[data-fit~="air"].is-active .r3s__media { --my: var(--r3s-air-cy, min(0px, calc((var(--r3s-nav) + (var(--r3s-vh) - var(--r3s-nav) - var(--r3s-air-dock, 0px)) / 2) - (var(--r3s-vh) - var(--r3s-air-b, 0px) - var(--r3s-air-ph) / 2)))); }
  /* the CARD of the hand-over (G-06: the plate is parked as a rounded card; the final zoom pose): a framed picture has no melted edges there, it is a clean rounded card, on the same expo in-out curve as the zoom-out */
  .r3s.is-live .r3s__world[data-fit~="air"].is-parked .r3s__media picture, .r3s.is-live .r3s__world[data-fit~="air"].is-parked .r3s__media video,
  .r3s.is-live[data-pose="zoom"] .r3s__world[data-fit~="air"].is-full .r3s__media picture, .r3s.is-live[data-pose="zoom"] .r3s__world[data-fit~="air"].is-full .r3s__media video { --r3s-fe: 0%; --r3s-fbe: 0%; border-radius: 30px; }
}

/* ENG3F (round 3c fix pass, v1.3): data-fit="air all" = the same framing in EVERY portrait window, not only in those narrower than 5:8. Use it when the portrait window shows a picture that is NOT 3:4
   (the Max page world A shows a 3:2 window onto the flame in a portrait window: at 768x1024, exactly 3:4, the cover fit would zoom it again, 1.6x). Everything of the block above applies unchanged
   (the same parameters); the two blocks overlap only at exactly 5:8, with identical rules. A world with plain data-fit="air" behaves exactly as in v1.2 (A/B proven in ENG3). */
@media (orientation: portrait) and (min-aspect-ratio: 5/8) {
  .r3s.is-live .r3s__world[data-fit~="all"] .r3s__media picture,
  .r3s.is-live .r3s__world[data-fit~="all"] .r3s__media video {
    --r3s-fe: var(--r3s-air-f, 30%); --r3s-fbe: var(--r3s-air-fb, 7%);
    position: absolute; inset: auto 0 var(--r3s-air-b, 0px) 0; width: 100%; height: auto; aspect-ratio: var(--r3s-air-ar, 3 / 4); max-height: 100%; overflow: hidden; border-radius: 0;
    -webkit-mask-image: linear-gradient(180deg, transparent 0, rgba(0, 0, 0, .03) calc(var(--r3s-fe) * .18), rgba(0, 0, 0, .12) calc(var(--r3s-fe) * .36), rgba(0, 0, 0, .3) calc(var(--r3s-fe) * .54), rgba(0, 0, 0, .58) calc(var(--r3s-fe) * .74), rgba(0, 0, 0, .86) calc(var(--r3s-fe) * .9), #000 var(--r3s-fe), #000 calc(100% - var(--r3s-fbe)), transparent 100%);
    mask-image: linear-gradient(180deg, transparent 0, rgba(0, 0, 0, .03) calc(var(--r3s-fe) * .18), rgba(0, 0, 0, .12) calc(var(--r3s-fe) * .36), rgba(0, 0, 0, .3) calc(var(--r3s-fe) * .54), rgba(0, 0, 0, .58) calc(var(--r3s-fe) * .74), rgba(0, 0, 0, .86) calc(var(--r3s-fe) * .9), #000 var(--r3s-fe), #000 calc(100% - var(--r3s-fbe)), transparent 100%);
    transition: --r3s-fe var(--tm-d-hand) var(--tm-ease-handover), --r3s-fbe var(--tm-d-hand) var(--tm-ease-handover), border-radius var(--tm-d-hand) var(--tm-ease-handover); }
  .r3s.is-live .r3s__world[data-fit~="all"] .r3s__media video { transition: opacity .9s var(--tm-ease-settle), --r3s-fe var(--tm-d-hand) var(--tm-ease-handover), --r3s-fbe var(--tm-d-hand) var(--tm-ease-handover), border-radius var(--tm-d-hand) var(--tm-ease-handover); }   /* the film keeps its fade-in over the poster */
  .r3s.is-live .r3s__world[data-fit~="all"] .r3s__media { transform-origin: 50% calc(100% - var(--r3s-air-b, 0px)); --r3s-my: var(--r3s-air-my, 0%); --r3s-mx: var(--r3s-air-mx, 0%); }   /* the picture already stands below / apart from the copy: the text pose needs no shift */
  /* the beat without copy ("the subject alone", the finale of the world): the picture glides up on the 3.683 s creeping move until it is centred between the header and the dock (--r3s-air-cy overrides) */
  .r3s[data-pose="clean"] .r3s__world[data-fit~="all"].is-active .r3s__media { --my: var(--r3s-air-cy, min(0px, calc((var(--r3s-nav) + (var(--r3s-vh) - var(--r3s-nav) - var(--r3s-air-dock, 0px)) / 2) - (var(--r3s-vh) - var(--r3s-air-b, 0px) - var(--r3s-air-ph) / 2)))); }
  /* the CARD of the hand-over (G-06: the plate is parked as a rounded card; the final zoom pose): a framed picture has no melted edges there, it is a clean rounded card, on the same expo in-out curve as the zoom-out */
  .r3s.is-live .r3s__world[data-fit~="all"].is-parked .r3s__media picture, .r3s.is-live .r3s__world[data-fit~="all"].is-parked .r3s__media video,
  .r3s.is-live[data-pose="zoom"] .r3s__world[data-fit~="all"].is-full .r3s__media picture, .r3s.is-live[data-pose="zoom"] .r3s__world[data-fit~="all"].is-full .r3s__media video { --r3s-fe: 0%; --r3s-fbe: 0%; border-radius: 30px; }
}

/* b6 fix54b scene headline, enlarged text */
.r3s:not(.is-live) .r3s__open { font-size: min(clamp(3rem, 1.2rem + 6.6vw, 7.5rem), clamp(48px, 19.2px + 6.6vw, 120px)); }
