/* ============================================================
   RADHIMAA — SCENE 03 · THE LIGHT

   A scroll-controlled plate, pinned like Scene 02 and driven by the
   same transport (scrub.js). What is different is what the footage
   does: it opens in near-darkness and the room fills with morning
   light on its own.

   Measured off the shipped plate — mean luminance every 0.15s:

     T 0.00        L 73   the last of the whip-pan, dim
     T 0.15-0.30   L 18   the darkest point
     T 0.30-1.20   L 18 -> 56   the light arriving
     T 1.20-3.50   L 56 -> 60   the room established, near-static

   So the sunrise is in the footage. Everything below only leans on
   it: the grade never invents a light source, and the two warm
   glows sit exactly where the real windows are — lower-left, where
   the shaft falls on her, and upper-right, where the curtain burns
   out. No sun, no flare, no orange sheet over the picture.
   ============================================================ */

/* --mt, --mk, --mo are already registered by memory.css and are
   deliberately shared: they mean the same thing in every chapter. */
@property --senter { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --scool  { syntax: '<number>'; inherits: false; initial-value: 1; }
@property --swarm  { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --shaze  { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --sedge  { syntax: '<number>'; inherits: false; initial-value: 0; }

/* The light's own geometry, tracked rather than fixed.

   The camera pushes in for the whole plate, and the two things the
   grade is anchored to move with it: the curtain slides from 60% of
   frame width to 83%, and the pool it throws on the floor from 44%
   to 52%. Both are measured per frame as the brightest column of
   their band and driven from paint(), so every shaft, bloom and
   floor lift stays on the light that is actually in the picture
   instead of drifting off it. */
@property --sx     { syntax: '<number>'; inherits: false; initial-value: 60; }
@property --bx     { syntax: '<number>'; inherits: false; initial-value: 44; }
@property --sbeam  { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --sbloom { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --sfloor { syntax: '<number>'; inherits: false; initial-value: 0; }

:root {
  /* Sampled from Scene 03's own plate. The room is a cool blue with
     two warm windows in it; these are those two temperatures, not a
     palette chosen alongside them. */
  --sun-amber:  #f0b968;   /* the shaft on the floor */
  --sun-honey:  #ffd79a;
  --sun-cream:  #f6ead6;   /* the blown-out curtain, lifted to type */
  --sun-slate:  #2c3a4a;   /* the room's blue wall */
  --sun-deep:   #0d1420;

  --sun-run: 640svh;
}

/* ============================================================
   THE FRAME
   ============================================================ */

.sun {
  position: relative;
  height: var(--sun-run);
  background: #000;
}

.sun__frame {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  background: #000;
  isolation: isolate;
  z-index: 0;
}

.sun__plate {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: var(--senter);
  transform: translate3d(0, 0, 0) scale(calc(1.05 - var(--senter) * .05));
  filter: blur(calc((1 - var(--senter)) * 16px));
  will-change: opacity, transform, filter;
}

.sun--in .sun__plate  { will-change: opacity, transform; filter: none; }
.sun--out .sun__plate { will-change: auto; }

.sun__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* the room's ceiling is empty and its floor carries the lit rug —
     on a short window the floor is the half worth keeping */
  object-position: 50% 56%;
  display: block;
  background: #000;
}

/* nothing floats over the frame while it is on screen */
.sun-live .ui { visibility: hidden; }

/* ============================================================
   THE LIGHT
   Three layers, all of them anchored to light that is already in
   the picture. None of them is allowed to become the light itself.
   ============================================================ */

.sun__cool,
.sun__warm,
.sun__haze,
.sun__beam,
.sun__bloom,
.sun__floor,
.sun__vig,
.sun__grain,
.sun__edge,
.sun__pet,
.sun__air { position: absolute; inset: 0; pointer-events: none; }

/* The chapter opens out of Scene 02's darkness, so it opens cool and
   closed-down and lets the plate do the rest. */
.sun__cool {
  z-index: 1;
  opacity: var(--scool);
  background:
    linear-gradient(180deg, rgba(14, 22, 38, .52), rgba(10, 16, 30, .62)),
    radial-gradient(96% 78% at 46% 52%, rgba(44, 58, 74, .30), transparent 74%);
  mix-blend-mode: soft-light;
}

.sun__cool::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(112% 92% at 46% 54%,
    rgba(0, 0, 0, .16) 26%, rgba(0, 0, 0, .58) 100%);
}

/* The warmth. Two glows, both sitting on a real window: the shaft that
   falls across her at lower-left, and the curtain that burns out at
   upper-right (measured L 150 at cols 18-20, rows 11-39%). Soft-light
   at these alphas moves the plate a few percent — it is a temperature
   change, not a wash. */
.sun__warm {
  z-index: 2;
  opacity: var(--swarm);
  background:
    radial-gradient(52% 62% at 8% 64%, rgba(240, 185, 104, .30), transparent 70%),
    radial-gradient(44% 74% at 84% 26%, rgba(255, 215, 154, .26), transparent 72%),
    linear-gradient(178deg, rgba(255, 214, 150, .07), rgba(120, 74, 34, .10));
  mix-blend-mode: soft-light;
}

/* The haze the light hangs in. Screened, but barely — this is what
   makes the room feel like it has air in it rather than making it
   yellow. */
.sun__haze {
  z-index: 3;
  opacity: var(--shaze);
  background:
    radial-gradient(66% 58% at 12% 62%, rgba(255, 226, 176, .16), transparent 68%),
    radial-gradient(54% 66% at 86% 30%, rgba(255, 236, 200, .14), transparent 70%);
  mix-blend-mode: screen;
}

/* Where the light lands. The pool on the floor measures L 200 at its
   centre against L 55 for the room — it is already the brightest
   thing in the lower half, and it is the ground the petals are
   thrown from, so it gets a lift under them and nothing more. */
.sun__floor {
  z-index: 4;
  opacity: var(--sfloor);
  background: radial-gradient(30% 17% at calc(var(--bx) * 1%) 91%,
    rgba(255, 218, 158, .40), rgba(240, 185, 104, .14) 52%, transparent 80%);
  filter: blur(9px);
  mix-blend-mode: screen;
  will-change: opacity;
}

/* ---------- the shafts ----------

   A bundle rather than one ray: four shafts of different width and
   strength, parallel to each other because the sun is at infinity
   and its rays through a single window are. The bundle leans 32°
   off vertical, which is the angle between the curtain at the top of
   frame and the pool it throws on the floor — the room's own
   geometry, measured, rather than a diagonal picked by eye.

   Blurred well past being a shape and screened at single-digit
   alphas. What this adds is air with light in it; the moment it
   reads as four stripes it has failed. */
.sun__beam {
  z-index: 5;
  opacity: var(--sbeam);
  background: linear-gradient(122deg,
    transparent 26%,
    rgba(255, 234, 192, .100) 31%,
    transparent 35.5%,
    rgba(255, 240, 210, .190) 41%,
    rgba(255, 246, 226, .245) 45%,
    rgba(255, 240, 208, .155) 49%,
    transparent 54%,
    rgba(255, 232, 188, .090) 59%,
    transparent 64%,
    rgba(255, 238, 202, .138) 69%,
    transparent 75%);
  filter: blur(20px);
  mix-blend-mode: screen;
  transform: translate3d(calc((var(--sx) - 60) * 1%), 0, 0);
  will-change: opacity, transform;
}

/* The same bundle again, wider and fainter and a hair off the first
   angle — two depths of air rather than one sheet of it. */
.sun__beam::after {
  content: "";
  position: absolute;
  inset: -12%;
  background: linear-gradient(118deg,
    transparent 30%,
    rgba(255, 240, 206, .085) 44%,
    rgba(255, 246, 224, .115) 51%,
    transparent 63%);
  filter: blur(44px);
}

/* The curtain is the brightest thing in the frame — L 142 against a
   room at L 55 — so it is the one place a lens actually blooms. The
   wide, short second gradient is the horizontal bleed a bright edge
   leaves; one artifact, not a set of them. Both track the curtain,
   which slides right as the camera pushes in. */
.sun__bloom {
  z-index: 6;
  opacity: var(--sbloom);
  background:
    radial-gradient(19% 54% at calc(var(--sx) * 1%) 34%,
      rgba(255, 246, 226, .52), rgba(255, 226, 176, .20) 44%, transparent 72%),
    radial-gradient(46% 8% at calc(var(--sx) * 1%) 34%,
      rgba(255, 240, 210, .20), transparent 74%);
  filter: blur(12px);
  mix-blend-mode: screen;
  will-change: opacity;
}

/* ---------- the petals ----------
   One element and one 2D context for the whole field. It sits under
   the vignette on purpose: the frame's edge fall-off has to darken
   the petals too, or they float in front of the picture instead of
   being in the room with her. See petals.js. */
.sun__pet {
  z-index: 7;
  display: block;
  width: 100%;
  height: 100%;
}

.sun__vig {
  z-index: 9;
  background:
    radial-gradient(122% 94% at 50% 50%,
      rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, .20) 74%, rgba(0, 0, 0, .58) 100%),
    linear-gradient(to bottom,
      rgba(0, 0, 0, .30) 0%, rgba(0, 0, 0, 0) 22%,
      rgba(0, 0, 0, 0) 66%, rgba(6, 6, 8, .44) 100%);
}

/* ============================================================
   THE AIR — dust, and only dust
   Scene 04 gets the butterflies and the later chapters get the
   flowers. This chapter's whole vocabulary is light, so the only
   thing in the air is what light makes visible.
   ============================================================ */

.sun__air { z-index: 8; }

.sun-dust {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--w);
  height: var(--w);
  border-radius: 50%;
  background: radial-gradient(closest-side,
    rgba(255, 238, 206, .95), rgba(240, 185, 104, .30) 56%, transparent 100%);
  opacity: var(--op);
  filter: blur(var(--soft));
  will-change: transform, opacity;
  animation: sunDrift var(--dur) ease-in-out var(--delay) infinite alternate;
}

/* Motes rise and drift; real dust in a sunbeam never falls straight. */
@keyframes sunDrift {
  from { transform: translate3d(0, 0, 0) scale(.8);              opacity: .12; }
  to   { transform: translate3d(var(--dx), var(--dy), 0) scale(1.15); opacity: 1; }
}

.sun__air > .air { position: absolute; inset: 0; opacity: var(--mo); }

/* ============================================================
   TYPOGRAPHY

   Measured over the plate from T 1.16 to the end — the whole window
   in which anything is on screen. The band across the top of the
   wall, cols 4-17, reads L 10-46 at activity 0-8: the widest, darkest,
   stillest ground in the room, and it clears both their heads, which
   never rise above y 16%.

   The opening line does not live there. While the plate is still at
   L 18 there is no room to respect — only a small warm glow near the
   middle — so it sits low and centred, on black, and is gone before
   the light arrives. Two positions, each right for its own moment;
   they are never on screen together.
   ============================================================ */

.sun__type {
  position: absolute;
  inset: 0;
  z-index: 10;
  pointer-events: none;
}

/* ---------- the opening line, on the darkness ---------- */

.sun-open {
  position: absolute;
  left: 0;
  right: 0;
  top: 62%;
  margin: 0;
  text-align: center;
  font-size: clamp(9.5px, .8vw, 13px);
  letter-spacing: .38em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--sun-cream);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .8), 0 0 22px rgba(0, 0, 0, .6);
}

/* ---------- the line the light reveals ---------- */

.sun-main {
  position: absolute;
  left: 50%;
  top: 5.2vh;
  transform: translateX(-50%);
  width: min(48vw, 820px);
  text-align: center;
}

/* §10 asks for warm light behind the words rather than a scrim. It
   peaks while they are arriving and is nearly gone once they are
   sharp, so the light reads as what revealed them. */
.sun-main__glow {
  position: absolute;
  left: -22%;
  right: -22%;
  top: -120%;
  bottom: -130%;
  background: radial-gradient(50% 108% at 50% 50%,
    rgba(255, 226, 172, .26), rgba(240, 185, 104, .10) 46%, transparent 74%);
  filter: blur(30px);
  mix-blend-mode: screen;
  opacity: calc(.22 + var(--mt) * (1 - var(--mt)) * 2.6);
  pointer-events: none;
}

.sun-main__h {
  position: relative;
  margin: 0;
  font-family: var(--mem-serif);
  font-weight: 300;
  font-size: clamp(22px, 2.9vw, 50px);
  line-height: 1.18;
  letter-spacing: .006em;
  color: var(--sun-cream);
  text-shadow:
    0 1px 2px rgba(0, 0, 0, .5),
    0 2px 26px rgba(0, 0, 0, .5),
    0 0 80px rgba(0, 0, 0, .32);
}

.sun-main__sub {
  position: relative;
  margin: 1.9vh 0 0;
  font-size: clamp(9px, .74vw, 12px);
  letter-spacing: .34em;
  text-transform: uppercase;
  font-weight: 500;
  color: rgba(246, 234, 214, .84);
  text-shadow: 0 1px 2px rgba(0, 0, 0, .7), 0 0 16px rgba(0, 0, 0, .6);
}

/* ============================================================
   GRAIN + THE RELEASE
   ============================================================ */

/* the same plate treatment as the other chapters — keyframes `grain`
   live in hero.css */
.sun__grain {
  inset: -140px;
  z-index: 11;
  opacity: .045;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain 1.1s steps(5) infinite;
}

.sun__edge {
  z-index: 12;
  background: #000;
  opacity: calc(var(--sedge) * .97);
}

/* ============================================================
   PORTRAIT

   The plate is a different encode: the room as a full-width band
   inside its own blurred light, because a 9:16 crop of a room with
   one person at each side keeps neither of them. The band lands at
   26%-54% of the height, so the type goes below it — and the opening
   line, which used to sit at 62%, comes with it.
   ============================================================ */

@media (max-aspect-ratio: 1/1) {
  :root { --sun-run: 580svh; }

  .sun__video { object-position: 50% 50%; }

  .sun__vig {
    background:
      radial-gradient(120% 74% at 50% 42%,
        rgba(0, 0, 0, 0) 42%, rgba(0, 0, 0, .16) 76%, rgba(0, 0, 0, .44) 100%),
      linear-gradient(to bottom,
        rgba(6, 10, 18, .30) 0%, rgba(6, 10, 18, .06) 18%,
        rgba(6, 10, 18, 0) 28%, rgba(6, 10, 18, 0) 56%,
        rgba(8, 7, 6, .70) 84%, rgba(8, 7, 6, .90) 100%);
  }

  .sun-open {
    top: auto;
    bottom: 26svh;
    font-size: 10px;
    letter-spacing: .32em;
  }

  .sun-main {
    left: 8vw;
    right: 8vw;
    top: auto;
    bottom: 13svh;
    width: auto;
    transform: none;
    text-align: left;
  }

  .sun-main__h {
    font-size: clamp(21px, 6.2vw, 36px);
    line-height: 1.2;
  }

  .sun-main__sub {
    margin-top: 2.2svh;
    font-size: 9.5px;
    letter-spacing: .3em;
  }

  /* The shafts and the floor lift are landscape geometry: in
     portrait the picture is a band inside its own blurred fill, and a
     32-degree beam drawn across the full viewport would cross the
     fill as often as the room. The bloom stays, moved into the band. */
  .sun-main__glow { display: none; }
  .sun__beam,
  .sun__floor { display: none; }

  .sun__bloom {
    background:
      radial-gradient(17% 16% at calc(var(--sx) * 1%) 40.5%,
        rgba(255, 246, 226, .30), rgba(255, 226, 176, .10) 44%, transparent 72%),
      radial-gradient(40% 2.4% at calc(var(--sx) * 1%) 40.5%,
        rgba(255, 240, 210, .12), transparent 74%);
  }
}

/* short landscape */
@media (max-height: 560px) and (min-aspect-ratio: 1/1) {
  .sun-open  { top: 66%; }
  .sun-main  { top: 2.6vh; width: min(58vw, 700px); }
  .sun-main__h { font-size: clamp(18px, 2.3vw, 32px); }
}

/* ============================================================
   REDUCED MOTION
   The light still answers the scroll — it is the content. What stops
   is everything autonomous.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  .sun__plate { filter: none !important; transform: none !important; }
  .sun__grain { display: none; }
  .sun-dust { animation: none !important; }
  .sun-main__glow { display: none; }
}
