/* ============================================================
   UbiRing landing — premium colorway layer (v1).
   Loaded after styles.css. Adds:
   1. Aurora gradient system (jewel-tone ambient identity)
   2. Cinematic unbox hero (full-bleed scroll film)
   3. Colorways turntable (3 finishes, morphing aurora)
   4. Overlap story stack (sticky sheet cards)
   5. Gradient polish for existing chapters (titles, badges,
      buttons, bento glows)
   Every effect respects prefers-reduced-motion and both themes.
   ============================================================ */

/* -- 1. Aurora tokens ---------------------------------------- */

/* Sapphire palette: the old violet/magenta jewel tones are remapped
   into the blue family (indigo / ice-cyan) so the whole page reads
   cool blue. Variable names stay so every downstream usage follows.
   --aur-amber survives solely as the Solar Gold finish accent. */
:root {
  --aur-violet: oklch(0.58 0.20 265);
  --aur-magenta: oklch(0.68 0.15 225);
  --aur-amber: oklch(0.78 0.16 75);
  --aur-teal: oklch(0.72 0.14 195);
  --aur-blue: oklch(0.66 0.19 255);

  /* Gradient text used on display <em> accents. */
  --grad-ink: linear-gradient(
    92deg,
    var(--aur-teal) 0%,
    var(--aur-blue) 34%,
    var(--aur-violet) 68%,
    var(--aur-magenta) 100%
  );
}

[data-theme="light"] {
  --aur-violet: oklch(0.50 0.19 265);
  --aur-magenta: oklch(0.55 0.14 225);
  /* Dark enough for AA on light surfaces (colorways tag, story kicker). */
  --aur-amber: oklch(0.55 0.15 75);
  --aur-teal: oklch(0.55 0.13 195);
  --aur-blue: oklch(0.52 0.19 255);
}

/* Deck edge treatment, theme-aware: dark junctions need a lit inset
   rim (a cast shadow is invisible black-on-black); light junctions
   need a navy plume instead of a 65%-black smear. The inset rim
   follows border-radius, tracing the rounded sheet corners. */
:root {
  --deck-shadow:
    inset 0 1px 0 oklch(1 0 0 / 0.13),
    0 -28px 70px -34px oklch(0 0 0 / 0.80);
  --card-lift-shadow: 0 -18px 50px -28px oklch(0 0 0 / 0.7);
  /* Hold beat: scroll distance a sheet stays fully readable before the
     next one starts sliding over it. Without it the successor sheet sits
     exactly at the viewport bottom the instant a sheet finishes arriving,
     so a chapter is covered while its 0.9s reveals are still running. */
  --deck-dwell: clamp(260px, 45svh, 480px);
}

[data-theme="light"] {
  --deck-shadow:
    inset 0 1px 0 oklch(1 0 0 / 0.55),
    0 -20px 50px -30px oklch(0.20 0.03 260 / 0.28);
  --card-lift-shadow: 0 -14px 40px -26px oklch(0.20 0.04 260 / 0.24);
}

/* -- 2. Cinematic unbox hero --------------------------------- */

.hero--unbox {
  min-height: 100svh;
  display: grid;
  align-items: end;
  padding-block: 0;
  overflow: clip;
  isolation: isolate;
  /* Match the film's near-black charcoal so the shifted canvas edge
     dissolves into the section instead of exposing the page bloom. */
  background: linear-gradient(180deg, oklch(0.115 0.008 262), oklch(0.13 0.012 258));
}

/* The film fills the stage edge-to-edge behind everything. */
.hero--unbox .hero__film-wrap {
  position: absolute;
  inset: 0;
  z-index: 0;
  will-change: transform;
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 16%);
  mask-image: linear-gradient(180deg, transparent 0%, #000 16%);
}

.hero--unbox .hero__film {
  width: 100%;
  height: 100%;
  display: block;
}

/* Aurora scrims: keep copy legible and tint the film's horizon. */
.hero--unbox .hero__film-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 108%, oklch(0 0 0 / 0.55), transparent 55%),
    radial-gradient(110% 78% at 50% -12%, oklch(0 0 0 / 0.78), transparent 64%),
    radial-gradient(55% 42% at 18% 88%, oklch(0.45 0.18 258 / 0.22), transparent 70%),
    radial-gradient(55% 42% at 84% 86%, oklch(0.58 0.13 215 / 0.16), transparent 70%);
}

/* Copy floats over the film, centred high while the box waits below. */
.hero--unbox .hero__overlay {
  position: relative;
  z-index: 2;
  display: grid;
  justify-items: center;
  padding-top: clamp(108px, 16vh, 170px);
  padding-bottom: clamp(240px, 38vh, 430px);
}

.hero--unbox .hero__copy {
  position: relative;
  max-width: 780px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  will-change: transform, opacity;
}

/* Local scrim pooled behind the copy so it stays readable where it
   overlaps the bright case — the film is dark in BOTH themes, so a
   black pool works for each. Fades out with the copy on scroll. */
.hero--unbox .hero__copy::before {
  content: "";
  position: absolute;
  inset: -10% -20% -12%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    56% 58% at 50% 44%,
    oklch(0.09 0.008 280 / 0.85),
    oklch(0.09 0.008 280 / 0.5) 55%,
    transparent 80%
  );
}

.hero--unbox .hero__lede,
.hero--unbox .hero__eyebrow {
  text-shadow: 0 1px 22px oklch(0 0 0 / 0.7), 0 1px 4px oklch(0 0 0 / 0.5);
}

.hero--unbox .hero__display {
  text-shadow: 0 2px 34px oklch(0 0 0 / 0.55);
}

/* text-shadow bleeds through gradient-clipped glyphs — keep the aurora
   ink clean. */
.hero--unbox .hero__display em { text-shadow: none; }

.hero--unbox .hero__display {
  font-size: var(--t-3xl);
  line-height: 1.02;
  letter-spacing: -0.03em;
  margin-top: var(--s-4);
}

.hero--unbox .hero__display em {
  background: var(--grad-ink);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* background-position never composites — keep the shimmer finite. */
  animation: aurora-slide 9s ease-in-out 4 alternate;
}

.hero--unbox .hero__display em::after { display: none; }

@keyframes aurora-slide {
  from { background-position: 0% 50%; }
  to { background-position: 100% 50%; }
}

.hero--unbox .hero__lede {
  margin-top: var(--s-4);
  max-width: 56ch;
}

.hero--unbox .hero__actions { justify-content: center; }

/* The two "quiet" cues must read against the dark film from the first
   frame: the Amazon mark gets a glass pill, the scroll cue a glass ring. */
.hero--unbox .amazon-cta {
  padding: 9px 18px 7px;
  border-radius: var(--r-pill);
  border: 1px solid oklch(1 0 0 / 0.18);
  background: oklch(0.2 0.012 260 / 0.5);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--ink-2);
  box-shadow: 0 6px 24px -8px oklch(0 0 0 / 0.5);
  transition: color var(--d-fast) var(--ease), border-color var(--d-fast) var(--ease);
}

.hero--unbox .amazon-cta:hover {
  color: var(--ink);
  border-color: oklch(1 0 0 / 0.32);
}

.hero--unbox .hero__scroll {
  width: 48px;
  height: 48px;
  /* The hero grows past 100svh with its copy, so a bottom anchor lands
     below the fold — pin the cue to the FIRST viewport instead. */
  top: calc(100svh - 88px);
  bottom: auto;
  border-radius: 50%;
  border: 1px solid oklch(1 0 0 / 0.24);
  background: oklch(0.2 0.012 260 / 0.45);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: var(--ink);
  box-shadow: 0 6px 24px -6px oklch(0 0 0 / 0.55);
}

.hero--unbox .hero__scroll svg { width: 22px; height: 22px; }

/* Finale layer: sensor callouts around the risen ring + closing line. */
.hero__finale {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
}

.hero__finale-tag {
  position: absolute;
  left: 50%;
  bottom: clamp(28px, 7vh, 72px);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-3);
  text-align: center;
  pointer-events: auto;
}

/* The product name hands off from the headline to the finale: once the
   ring has fully risen, "UbiRing" returns beneath it and stays. */
.hero__finale-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.4rem, 4.8vw, 3.9rem);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--stage-fg, var(--ink));
  text-shadow: 0 2px 30px oklch(0 0 0 / 0.5);
}

.hero__finale-name em {
  font-style: normal;
  background: var(--grad-ink);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: none;
}

.hero__finale-line {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.02rem, 1.6vw, 1.3rem);
  letter-spacing: -0.01em;
  color: var(--ink-2);
}

.hero__finale-line em {
  font-style: normal;
  background: var(--grad-ink);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Mobile: the film leaves the backdrop and becomes a contained stage
   below the copy — it plays through once when it scrolls into view,
   then the finale line fades in beneath it. */
@media (max-width: 900px) {
  .hero--unbox {
    display: flex;
    flex-direction: column;
    align-items: stretch;
  }
  .hero--unbox .hero__overlay {
    order: 1;
    padding-top: 112px;
    padding-bottom: var(--s-4);
  }
  .hero--unbox .hero__film-wrap {
    order: 2;
    position: relative;
    inset: auto;
    width: 100%;
    aspect-ratio: 5 / 4;
    will-change: auto; /* no scrubbed transform on mobile */
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 10%);
    mask-image: linear-gradient(180deg, transparent 0%, #000 10%);
  }
  .hero__finale {
    order: 3;
    position: static;
    opacity: 1;
    visibility: visible;
  }
  .hero__finale-tag {
    position: static;
    transform: none;
    padding: var(--s-4) var(--s-4) var(--s-7);
    opacity: 0;
    visibility: hidden; /* keeps the CTA unfocusable until the film ends */
    transition: opacity 700ms var(--ease), visibility 0s linear 700ms;
  }
  .hero--unbox.unbox-finale .hero__finale-tag {
    opacity: 1;
    visibility: visible;
    transition: opacity 700ms var(--ease);
  }
  .hero--unbox .hero__scroll { display: none; }
}

/* No-JS / reduced-motion: everything readable, film shows final frame.
   The -tag selectors out-specify the mobile opacity:0 default so the
   finale line + CTA appear even when the film never plays. */
.unbox-done .hero__finale,
html:not(.js) .hero__finale,
.unbox-done .hero__finale-tag,
html:not(.js) .hero__finale-tag {
  opacity: 1;
  visibility: visible;
}

/* The film backdrop is cinematic-dark in BOTH themes, so the hero keeps
   dark-stage ink even when the rest of the page flips to light. */
[data-theme="light"] .hero--unbox {
  color-scheme: dark;
  --bg: oklch(0.135 0.010 260); /* .btn--primary label is var(--bg) */
  --ink: oklch(0.965 0.004 250);
  --ink-2: oklch(0.760 0.010 252);
  --ink-3: oklch(0.600 0.012 252);
  --surface: oklch(0.180 0.012 260);
  --surface-2: oklch(0.220 0.014 260);
  --border: oklch(1 0 0 / 0.09);
  --border-strong: oklch(1 0 0 / 0.17);
  --accent: oklch(0.74 0.145 252);
  --accent-ink: oklch(0.12 0.02 252);
}

/* -- 3. Colorways -------------------------------------------- */

.colorways {
  position: relative;
  padding-block: var(--s-9);
  overflow: clip;
  isolation: isolate;

  /* Finish-reactive accent, morphed by [data-color]. */
  --cw-a: var(--aur-violet);
  --cw-b: var(--aur-blue);
  --cw-glow: oklch(0.58 0.19 262 / 0.30);
}

.colorways[data-color="gold"] {
  --cw-a: var(--aur-amber);
  --cw-b: var(--aur-blue);
  --cw-glow: oklch(0.78 0.16 75 / 0.30);
}

.colorways[data-color="silver"] {
  --cw-a: var(--aur-blue);
  --cw-b: var(--aur-teal);
  --cw-glow: oklch(0.72 0.12 230 / 0.30);
}

.colorways[data-color="black"] {
  --cw-a: var(--aur-violet);
  --cw-b: var(--aur-magenta);
  --cw-glow: oklch(0.58 0.19 262 / 0.32);
}

/* Ambient aurora field behind the whole chapter. */
.colorways::before {
  content: "";
  position: absolute;
  inset: -10% -20%;
  z-index: -1;
  background:
    radial-gradient(46% 40% at 24% 30%, color-mix(in oklab, var(--cw-a) 26%, transparent), transparent 68%),
    radial-gradient(42% 38% at 78% 64%, color-mix(in oklab, var(--cw-b) 20%, transparent), transparent 66%),
    radial-gradient(60% 52% at 50% 110%, color-mix(in oklab, var(--cw-a) 12%, transparent), transparent 70%);
  filter: blur(20px);
  transition: opacity 700ms var(--ease);
  animation: cw-breathe 14s ease-in-out infinite alternate;
}

@keyframes cw-breathe {
  from { transform: translate3d(-1.5%, 0, 0) scale(1); }
  to { transform: translate3d(1.5%, -2%, 0) scale(1.05); }
}

.colorways__grid {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(var(--s-6), 5vw, var(--s-9));
  align-items: center;
  margin-top: var(--s-7);
}

/* Viewer: glass pedestal with the turntable canvas. */
.colorways__viewer {
  position: relative;
  aspect-ratio: 1 / 1;
  max-width: 620px;
  margin-inline: auto;
  width: 100%;
  perspective: 1100px;
  cursor: grab;
  touch-action: pan-y;
}

.colorways__viewer.is-dragging { cursor: grabbing; }

.colorways__viewer:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: var(--r-lg);
}

.colorways__stage-3d {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform 180ms ease-out;
  will-change: transform;
}

.colorways__halo {
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  background:
    conic-gradient(
      from 210deg,
      transparent 0deg,
      color-mix(in oklab, var(--cw-a) 45%, transparent) 80deg,
      color-mix(in oklab, var(--cw-b) 38%, transparent) 160deg,
      transparent 260deg
    );
  filter: blur(34px);
  opacity: 0.75;
  transition: background 700ms var(--ease);
  animation: halo-turn 24s linear infinite;
}

@keyframes halo-turn {
  to { transform: rotate(360deg); }
}

.colorways__plinth {
  position: absolute;
  left: 50%;
  bottom: 4%;
  width: 66%;
  height: 12%;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(closest-side, oklch(0 0 0 / 0.65), transparent 78%);
  filter: blur(10px); /* static element — rasterizes once */
}

/* No filter here: a drop-shadow on a canvas that repaints every frame
   forces a full shadow re-raster per frame; the plinth carries the
   grounding shadow instead. */
.colorways__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

#cw-canvas-b { opacity: 0; }

/* 360° badge: tells the visitor the ring is theirs to spin, then
   retires after the first drag or key press. */
.colorways__hint {
  position: absolute;
  left: 50%;
  bottom: -18px;
  transform: translateX(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  color: var(--ink-3);
  white-space: nowrap;
  transition: opacity 480ms var(--ease), visibility 0s linear 480ms;
}

.colorways__viewer.is-explored .colorways__hint {
  opacity: 0;
  visibility: hidden;
}

.cw360 {
  position: relative;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  background: color-mix(in oklab, var(--surface) 74%, transparent);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: var(--shadow-1);
  color: var(--ink-2);
}

.cw360__orbit {
  position: absolute;
  inset: 6px;
  animation: cw360-turn 9s linear infinite;
  opacity: 0.85;
}

@keyframes cw360-turn {
  to { transform: rotate(360deg); }
}

.cw360__label {
  font-family: var(--font-display);
  font-weight: 750;
  font-size: 0.76rem;
  letter-spacing: 0.02em;
  color: var(--ink);
}

.cw360__hint-txt {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Finish rail: metallic chips. */
.colorways__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-bottom: var(--s-5);
}

.cw-chip {
  --chip-metal: linear-gradient(135deg, #3a3a40, #101014 55%, #2c2c33);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px 9px 10px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: color-mix(in oklab, var(--surface) 82%, transparent);
  color: var(--ink-2);
  font-family: var(--font-display);
  font-size: var(--t-sm);
  font-weight: 650;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition:
    border-color var(--d-fast) var(--ease),
    color var(--d-fast) var(--ease),
    transform var(--d-fast) var(--ease),
    box-shadow var(--d-fast) var(--ease);
}

.cw-chip[data-cw-chip="silver"] { --chip-metal: linear-gradient(135deg, #f4f6f8, #b9bec7 55%, #e6e9ee); }
.cw-chip[data-cw-chip="gold"] { --chip-metal: linear-gradient(135deg, #f4dfb2, #c39a55 55%, #e8cf9a); }

.cw-chip__swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--chip-metal);
  box-shadow:
    inset 0 1px 2px oklch(1 0 0 / 0.55),
    inset 0 -2px 4px oklch(0 0 0 / 0.35),
    0 2px 6px oklch(0 0 0 / 0.35);
  flex: 0 0 auto;
}

.cw-chip:hover {
  transform: translateY(-2px);
  color: var(--ink);
  border-color: var(--border-strong);
}

.cw-chip.is-active {
  color: var(--ink);
  border-color: color-mix(in oklab, var(--cw-a) 55%, var(--border));
  box-shadow:
    0 0 0 1px color-mix(in oklab, var(--cw-a) 35%, transparent),
    0 10px 30px -12px var(--cw-glow);
}

.cw-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Meta panel */
.colorways__meta { min-height: 150px; }

.colorways__meta.is-swap [data-cw-name],
.colorways__meta.is-swap [data-cw-tag],
.colorways__meta.is-swap [data-cw-desc] {
  animation: cw-meta-in 560ms var(--ease) both;
}

.colorways__meta.is-swap [data-cw-tag] { animation-delay: 50ms; }
.colorways__meta.is-swap [data-cw-desc] { animation-delay: 100ms; }

@keyframes cw-meta-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

.colorways__name {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 2.6vw, 2.35rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  background: linear-gradient(90deg, var(--ink), color-mix(in oklab, var(--cw-a) 65%, var(--ink)));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  transition: background 700ms var(--ease);
}

.colorways__tag {
  display: inline-block;
  margin-top: 4px;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: color-mix(in oklab, var(--cw-a) 70%, var(--ink-3));
  transition: color 700ms var(--ease);
}

.colorways__desc {
  margin-top: var(--s-3);
  color: var(--ink-2);
  max-width: 44ch;
}

/* “Same box view” — the finish sitting in its case. */
.colorways__case {
  position: relative;
  margin-top: var(--s-5);
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-1);
  transition: transform var(--d-base) var(--ease), box-shadow var(--d-base) var(--ease);
}

.colorways__case img {
  display: block;
  width: 100%;
  height: auto;
}

.colorways__case-ghost {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  pointer-events: none;
}

.colorways__case figcaption {
  position: absolute;
  left: 12px;
  bottom: 10px;
  padding: 5px 12px;
  border-radius: var(--r-pill);
  font-size: var(--t-xs);
  font-weight: 650;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--stage-fg);
  background: oklch(0 0 0 / 0.45);
  border: 1px solid oklch(1 0 0 / 0.14);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.colorways__case:hover {
  transform: translateY(-4px);
  box-shadow: 0 24px 60px -18px var(--cw-glow), var(--shadow-2);
}

.colorways__cta { margin-top: var(--s-5); }

@media (max-width: 1080px) {
  .colorways__grid { grid-template-columns: 1fr; }
  .colorways__viewer { max-width: 480px; }
  .colorways__panel { max-width: 560px; margin-inline: auto; text-align: center; }
  .colorways__chips { justify-content: center; }
  .colorways__desc { margin-inline: auto; }
}

/* -- 3b. Ring blast: exploded engineering view ----------------- */

/* A dark cinematic engineering chapter in BOTH themes — the v4
   decompose film is photoreal (rim lights, glowing sensors), so the
   section forces dark-stage ink the same way the hero does. */
.blast {
  position: relative;
  overflow: clip;
  isolation: isolate;
  color-scheme: dark;
  /* EXACTLY the site's dark --bg (#06080c): the film frames are
     screen-blended over this same color offline, so the canvas, the
     section and the page background fuse into one surface with no
     visible film rectangle. Keep all three in sync. */
  background: #06080c;
  --ink: oklch(0.965 0.004 250);
  --ink-2: oklch(0.76 0.010 252);
  --ink-3: oklch(0.60 0.012 252);
  --surface: oklch(0.185 0.012 260);
  --surface-2: oklch(0.225 0.014 260);
  --border: oklch(1 0 0 / 0.10);
  --border-strong: oklch(1 0 0 / 0.18);
  --accent: oklch(0.74 0.145 252);
  --shadow-1: 0 1px 0 oklch(0 0 0 / 0.3), 0 10px 30px -10px oklch(0 0 0 / 0.6);
}

.blast__stage {
  position: relative;
  min-height: 100svh;
  display: grid;
  place-items: center;
}

.blast__head {
  position: absolute;
  top: clamp(56px, 7vh, 96px);
  left: 50%;
  transform: translateX(-50%);
  width: min(92vw, 720px);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-3);
  z-index: 2;
}

/* The decompose film: 16:9 frames whose light-gray sweep matches the
   section background, so the canvas edge is invisible. */
.blast__film {
  position: relative;
  /* Capped against viewport HEIGHT: the exploded row spans the middle
     half of the frame (measured y 25%-75%), and this keeps clear bands
     above and below it for the annotation cards at any viewport. */
  width: min(100%, 90svh, 1200px);
  aspect-ratio: 16 / 9;
  margin-top: clamp(24px, 4vh, 60px);
}

.blast__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Annotations: obsidian glass cards hugging the exploded row — each
   carries its own aurora hue in a top hairline. */
.blast__note {
  --note-a: var(--aur-violet);
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: flex-start;
  gap: var(--s-4);
  width: min(24vw, 348px);
  padding: var(--s-5) var(--s-6);
  border-radius: calc(var(--r-lg) + 6px);
  background: linear-gradient(
    165deg,
    oklch(0.21 0.012 260 / 0.85),
    oklch(0.155 0.010 260 / 0.72)
  );
  border: 1px solid oklch(1 0 0 / 0.12);
  box-shadow:
    inset 0 1px 0 oklch(1 0 0 / 0.10),
    0 24px 60px -24px oklch(0 0 0 / 0.65),
    var(--shadow-1);
  -webkit-backdrop-filter: blur(14px) saturate(1.15);
  backdrop-filter: blur(14px) saturate(1.15);
  transition: border-color var(--d-fast) var(--ease), box-shadow var(--d-fast) var(--ease), translate var(--d-fast) var(--ease);
}

.blast__note--tl { --note-a: var(--aur-blue); }
.blast__note--tr { --note-a: var(--aur-violet); }
.blast__note--bl { --note-a: var(--aur-magenta); }
.blast__note--br { --note-a: var(--aur-teal); }

/* Hue-matched hairline along the card's top edge. */
.blast__note::before {
  content: "";
  position: absolute;
  top: 0;
  left: 20px;
  right: 20px;
  height: 2px;
  border-radius: 999px;
  background: linear-gradient(
    90deg,
    transparent,
    color-mix(in oklab, var(--note-a) 75%, transparent),
    transparent
  );
}

.blast__note:hover {
  translate: 0 -3px;
  border-color: color-mix(in oklab, var(--note-a) 45%, oklch(1 0 0 / 0.12));
  box-shadow:
    inset 0 1px 0 oklch(1 0 0 / 0.12),
    0 18px 44px -14px color-mix(in oklab, var(--note-a) 40%, transparent),
    var(--shadow-1);
}

/* Clear of the film: the exploded row runs across the middle third of
   the stage, so the top pair sits fully above it (below the head) and
   the bottom pair fully below it, pushed toward the stage edges. */
.blast__note--tl { top: clamp(128px, 16vh, 200px); left: clamp(28px, 5vw, 110px); }
.blast__note--tr { top: clamp(128px, 16vh, 200px); right: clamp(28px, 5vw, 110px); }
.blast__note--bl { bottom: clamp(36px, 6vh, 84px); left: clamp(28px, 5vw, 110px); }
.blast__note--br { bottom: clamp(36px, 6vh, 84px); right: clamp(28px, 5vw, 110px); }

.blast__num {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 2.1rem;
  line-height: 1;
  letter-spacing: -0.02em;
  background: var(--grad-ink);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  flex: 0 0 auto;
  padding-top: 2px;
}

.blast__title {
  font-family: var(--font-display);
  font-size: 1.22rem;
  font-weight: 750;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.blast__desc {
  margin-top: 6px;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink-2);
}

/* Mobile + reduced-motion: static stacked layout, everything visible. */
@media (max-width: 900px) {
  .blast__stage {
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s-5);
    padding: var(--s-8) var(--s-4);
  }
  .blast__head { position: static; transform: none; }
  .blast__film { width: 100%; margin-top: 0; }
  .blast__note {
    position: static;
    width: min(100%, 480px);
  }
}

/* -- 3d. Header: light-theme corrections + stage awareness ------ */

/* Light theme: a glow only reads when its composited result is a soft
   luminous tint against the near-white bar — moderate chroma at LOW
   alpha. (Do not raise the lightness toward white: near-white glow on
   a near-white bar is invisible.) */
[data-theme="light"] .glow-nav__glow {
  background: radial-gradient(circle at center,
    oklch(0.72 0.16 var(--gc, 252) / 0.28),
    oklch(0.72 0.16 var(--gc, 252) / 0.08) 46%,
    transparent 72%);
}

/* Light theme: give the active pill a visible fill so the halo isn't
   the only state indicator. */
[data-theme="light"] .glow-nav__link.is-active {
  background: oklch(0.55 0.18 var(--gc, 252) / 0.16);
}

/* Light theme: toggle/menu coins sit below the bar tone instead of
   floating above it as brighter-than-the-bar white discs. */
[data-theme="light"] .theme-toggle,
[data-theme="light"] .menu-toggle {
  background: var(--surface-2);
  border-color: var(--border-strong);
}

/* Accent line + pill glows share ONE hue: the pills inherit
   --active-hue (set on .site-header by script.js), so the underline
   and the glowing pill always shift color together. Wins over the
   styles.css ::after rule by source order. */
.site-header .glow-nav { --gc: var(--active-hue, 252); }
.site-header::after {
  background: linear-gradient(90deg, transparent,
    oklch(var(--line-l, 0.62) 0.19 var(--active-hue, 252) / 0.95) 50%,
    transparent);
}
[data-theme="light"] .site-header { --line-l: 0.52; }

/* Stage states (both themes): the header adopts the tone of the
   topmost sheet beneath it, tracked by overlap.js via
   [data-stage] from each section's data-header-stage attribute.
   Dark stage = hero, materials, blast, band, footer. (No section
   currently declares a light stage; the state below is kept for any
   future high-key chapter.) Token overrides restyle every header
   child at once (--bg feeds the primary button's label color). */
.site-header[data-stage="dark"] {
  color-scheme: dark;
  background: oklch(0.135 0.010 260 / 0.60);
  --bg: oklch(0.135 0.010 260);
  --ink: oklch(0.965 0.004 250);
  --ink-2: oklch(0.760 0.010 252);
  --ink-3: oklch(0.600 0.012 252);
  --surface: oklch(0.180 0.012 260);
  --surface-2: oklch(0.225 0.014 260);
  --border: oklch(1 0 0 / 0.09);
  --border-strong: oklch(1 0 0 / 0.17);
  --accent: oklch(0.74 0.145 252);
  --accent-soft: oklch(0.74 0.145 252 / 0.13);
  --accent-ink: oklch(0.12 0.02 252);
  --line-l: 0.62;
}

.site-header[data-stage="dark"] .site-header__brand img {
  filter: brightness(0) invert(1);
}

.site-header[data-stage="dark"] .glow-nav { --gl: 0.74; }

.site-header[data-stage="dark"] .glow-nav__glow {
  background: radial-gradient(circle at center,
    oklch(0.74 0.19 var(--gc, 252) / 0.5),
    oklch(0.74 0.19 var(--gc, 252) / 0.12) 46%,
    transparent 72%);
}

.site-header[data-stage="dark"] .glow-nav__link.is-active {
  background: oklch(0.74 0.16 var(--gc, 252) / 0.12);
}

.site-header[data-stage="dark"] .theme-toggle,
.site-header[data-stage="dark"] .menu-toggle {
  background: oklch(0.20 0.012 260 / 0.5);
  border-color: oklch(1 0 0 / 0.18);
}

/* Light stage (any high-key chapter): flips the header light even in
   dark theme, mirroring the section's own forced light ink. */
.site-header[data-stage="light"] {
  color-scheme: light;
  background: oklch(0.965 0.006 250 / 0.60);
  --bg: oklch(0.965 0.006 250);
  --ink: oklch(0.18 0.030 252);
  --ink-2: oklch(0.42 0.020 252);
  --ink-3: oklch(0.50 0.018 252);
  --surface: oklch(0.995 0.002 250);
  --surface-2: oklch(0.925 0.010 250);
  --border: oklch(0 0 0 / 0.10);
  --border-strong: oklch(0 0 0 / 0.20);
  --accent: oklch(0.55 0.20 252);
  --accent-soft: oklch(0.55 0.20 252 / 0.11);
  --accent-ink: oklch(0.99 0.005 252);
  --line-l: 0.52;
}

.site-header[data-stage="light"] .site-header__brand img { filter: none; }

.site-header[data-stage="light"] .glow-nav { --gl: 0.58; }

.site-header[data-stage="light"] .glow-nav__glow {
  background: radial-gradient(circle at center,
    oklch(0.72 0.16 var(--gc, 252) / 0.28),
    oklch(0.72 0.16 var(--gc, 252) / 0.08) 46%,
    transparent 72%);
}

.site-header[data-stage="light"] .glow-nav__link.is-active {
  background: oklch(0.55 0.18 var(--gc, 252) / 0.16);
}

/* The base overrides above tie or out-specify .theme-toggle:hover —
   restate the hover feedback so it survives on every stage in both
   themes (tokens resolve per stage). */
[data-theme="light"] .theme-toggle:hover,
[data-theme="light"] .menu-toggle:hover,
.site-header[data-stage] .theme-toggle:hover,
.site-header[data-stage] .menu-toggle:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
}

/* -- 4. Overlap story stack ----------------------------------- */

.story {
  position: relative;
  padding-block: var(--s-9) var(--s-8);
}

.story__stack {
  display: grid;
  gap: clamp(var(--s-7), 8vh, var(--s-9));
}

/* Each card holds still at its sticky position; the next chapter simply
   slides over the top — the overlap IS the transition. */
.story__card {
  position: sticky;
  top: clamp(84px, 11vh, 128px);
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  min-height: min(74vh, 680px);
  border-radius: calc(var(--r-lg) + 8px);
  overflow: hidden;
  border: 1px solid var(--border-strong);
  background:
    linear-gradient(160deg, color-mix(in oklab, var(--story-a, var(--aur-violet)) 14%, var(--surface)), var(--surface) 55%);
  box-shadow: var(--card-lift-shadow), var(--shadow-2);
}

.story__card:nth-child(1) { --story-a: var(--aur-blue); }
.story__card:nth-child(2) { --story-a: var(--aur-violet); }
.story__card:nth-child(3) { --story-a: var(--aur-magenta); }
.story__card:nth-child(4) { --story-a: var(--aur-teal); }

.story__media {
  position: relative;
  overflow: hidden;
  min-height: 320px;
}

.story__media img {
  position: absolute;
  inset: -9% 0;
  width: 100%;
  height: 118%;
  object-fit: cover;
  will-change: transform;
}

.story__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 55%, color-mix(in oklab, var(--surface) 55%, transparent));
}

.story__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s-3);
  padding: clamp(var(--s-6), 4.5vw, var(--s-8));
}

.story__kicker {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: color-mix(in oklab, var(--story-a) 70%, var(--ink-3));
}

.story__title {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 3vw, 2.6rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.08;
  color: var(--ink);
}

.story__title em {
  font-style: normal;
  background: linear-gradient(92deg, var(--story-a), color-mix(in oklab, var(--story-a) 40%, var(--ink)));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.story__desc { color: var(--ink-2); max-width: 46ch; }

.story__chips { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-2); }

@media (max-width: 900px) {
  .story__card {
    position: relative;
    top: auto;
    grid-template-columns: 1fr;
    min-height: 0;
  }
  .story__media { min-height: 240px; }
  .story__media img { position: absolute; inset: 0; height: 100%; will-change: auto; }
}

/* -- 5. Premium gradient polish for existing chapters --------- */

/* Display accents get the aurora ink instead of flat accent blue.
   (.materials__title em keeps its own ti-shimmer from styles.css.)
   The shimmer is finite and only starts once the section-head reveals,
   so offscreen titles never burn paint. */
.section-head__title em {
  background: var(--grad-ink);
  background-size: 240% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: aurora-slide 11s ease-in-out 4 alternate;
  animation-play-state: paused;
}

.is-visible .section-head__title em,
html:not(.js) .section-head__title em {
  animation-play-state: running;
}

/* Section badges: gradient hairline ring. */
.section-badge {
  position: relative;
  border: 1px solid transparent;
  background:
    linear-gradient(color-mix(in oklab, var(--surface) 92%, transparent), color-mix(in oklab, var(--surface) 92%, transparent)) padding-box,
    linear-gradient(120deg,
      color-mix(in oklab, var(--aur-blue) 55%, transparent),
      color-mix(in oklab, var(--aur-violet) 45%, transparent),
      color-mix(in oklab, var(--aur-teal) 45%, transparent)) border-box;
}

/* Primary buttons: sheen sweep on hover. */
.btn--primary {
  position: relative;
  overflow: hidden;
}

.btn--primary::after {
  content: "";
  position: absolute;
  top: 0;
  left: -80%;
  width: 55%;
  height: 100%;
  background: linear-gradient(105deg, transparent, oklch(1 0 0 / 0.34), transparent);
  transform: skewX(-18deg);
  transition: left 640ms var(--ease);
  pointer-events: none;
}

.btn--primary:hover::after { left: 130%; }

/* Bento tiles: each carries a whisper of a different aurora hue. */
.bento-tile { --tile-a: var(--aur-blue); }
.bento-tile:nth-child(2) { --tile-a: var(--aur-teal); }
.bento-tile:nth-child(3) { --tile-a: var(--aur-violet); }
.bento-tile:nth-child(4) { --tile-a: var(--aur-magenta); }
.bento-tile:nth-child(5) { --tile-a: var(--aur-blue); }
.bento-tile:nth-child(6) { --tile-a: var(--aur-teal); }

/* Resting state joins the aurora system: a tinted wash pooled in the
   tile's corner, a hue-matched hairline, and an icon chip that carries
   the tile's color even before hover. */
.bento-tile {
  border-radius: calc(var(--r-lg) + 6px);
  border-color: color-mix(in oklab, var(--tile-a) 15%, var(--border));
  background:
    radial-gradient(130% 100% at 14% 0%, color-mix(in oklab, var(--tile-a) 9%, transparent), transparent 54%),
    var(--surface);
}

.bento .feature__icon {
  border: 1px solid color-mix(in oklab, var(--tile-a) 28%, var(--border));
  background: linear-gradient(
    150deg,
    color-mix(in oklab, var(--tile-a) 20%, var(--surface)),
    color-mix(in oklab, var(--tile-a) 6%, var(--surface)) 70%
  );
  color: color-mix(in oklab, var(--tile-a) 72%, var(--ink));
  box-shadow: 0 10px 26px -14px color-mix(in oklab, var(--tile-a) 55%, transparent);
}

/* Hover hairline ring picks up the tile hue instead of flat accent. */
.bento-tile::before {
  background: linear-gradient(
    135deg,
    color-mix(in oklab, var(--tile-a) 85%, transparent),
    color-mix(in oklab, var(--tile-a) 30%, transparent) 45%,
    transparent 75%
  );
}

.bento-tile:hover {
  border-color: color-mix(in oklab, var(--tile-a) 40%, var(--border));
  box-shadow:
    0 0 0 1px color-mix(in oklab, var(--tile-a) 22%, transparent),
    0 24px 60px -22px color-mix(in oklab, var(--tile-a) 40%, transparent);
}

.bento-tile:hover .feature__icon {
  color: color-mix(in oklab, var(--tile-a) 75%, var(--ink));
  border-color: color-mix(in oklab, var(--tile-a) 45%, var(--border));
  background: color-mix(in oklab, var(--tile-a) 14%, transparent);
}

/* CTA tile: aurora wash + gradient headline number (both themes — the
   selector out-specifies styles.css's [data-theme="dark"] override). */
.bento .bento-tile--cta {
  --tile-a: var(--aur-violet);
  background:
    radial-gradient(120% 130% at 85% 110%, color-mix(in oklab, var(--aur-magenta) 15%, transparent), transparent 60%),
    radial-gradient(120% 130% at 10% -10%, color-mix(in oklab, var(--aur-violet) 17%, transparent), transparent 60%),
    var(--surface);
  border-color: color-mix(in oklab, var(--aur-violet) 26%, var(--border));
}

.bento .bento-tile--cta .bento-cta-k {
  background: var(--grad-ink);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Premium cards pick up warm/cool split glows. */
.premium__card:first-child:hover {
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--aur-violet) 26%, transparent),
    0 30px 70px -24px color-mix(in oklab, var(--aur-violet) 45%, transparent);
}

.premium__card:last-child:hover {
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--aur-teal) 26%, transparent),
    0 30px 70px -24px color-mix(in oklab, var(--aur-teal) 45%, transparent);
}

/* -- Header: room for the 6th nav item ------------------------ */

/* Without shrink protection the square logo gets crushed to a sliver
   once the wider nav lands; compacting the nav 901–1120px keeps the
   row fitting without clipping the header CTA. */
.site-header__brand { flex-shrink: 0; }

@media (max-width: 1120px) and (min-width: 901px) {
  .glow-nav__ic { display: none; }
  .glow-nav__link,
  .glow-nav__face--back { padding: 8px 11px; }
}

/* -- 6. Section overlap deck ---------------------------------- */

/* Every top-level chapter holds perfectly still once it has been seen
   (position: sticky against the viewport) while the next chapter simply
   slides over the top of it — the whole page reads as a deck of premium
   sheets, the same move the story stack already makes internally.
   Sections taller than the viewport get a negative --deck-top from
   overlap.js so they only pin once their bottom edge has been read.
   The GSAP-pinned chapters (hero film, blast) opt out: their pins
   already hold them, extended with a post-scrub dead-zone + a pull-up
   margin on the following sheet (set by overlap.js) so the next sheet
   covers them before they ever unpin. */
@media (min-width: 901px) {
  /* Gated on html.js: without overlap.js the tall sheets would pin at
     top:0 and trap their below-the-fold content. */
  html.js main > section {
    position: sticky;
    top: var(--deck-top, 0px);
    min-height: 100svh;
    /* Sheets must be opaque — the held chapter is still painted
       beneath them. */
    background-color: var(--bg);
    border-radius: clamp(22px, 3vw, 34px) clamp(22px, 3vw, 34px) 0 0;
    box-shadow: var(--deck-shadow);
    border-top: 1px solid var(--border);
    /* Each sheet is its own stacking context. Held sheets below contain
       permanently promoted children (will-change: transform on the
       unfold card, story photos, testimonial and colorway stages); with
       no stacking context to confine them those compositor layers are
       ordered by Chrome's overlap heuristics against the sheets stacked
       on top, which lose the race while sticky offsets are still being
       resolved — the held chapter tears through the arriving one. */
    isolation: isolate;
    /* Hold beat before the next sheet starts covering this one. */
    margin-bottom: var(--deck-dwell);
  }

  /* GSAP-pinned chapters: kept positioned (so the deck's document-order
     painting holds while they slide in) but never sticky. Selectors
     also match inside the runtime .pin-spacer wrap, where the
     `main > section` sheet rule above stops applying. */
  html.js main .hero--unbox,
  html.js main .blast {
    position: relative;
    top: auto;
    /* No dwell: overlap.js pulls the NEXT sheet up by exactly this
       chapter's height so it covers the held film during the post-scrub
       dead-zone. A margin here collapses against that negative pull-up
       and shortens it, opening a gap mid-film. */
    margin-bottom: 0;
  }
  html.js main .hero--unbox { border-radius: 0; box-shadow: none; border-top: 0; }
  html.js main .blast {
    border-radius: clamp(22px, 3vw, 34px) clamp(22px, 3vw, 34px) 0 0;
    box-shadow: var(--deck-shadow);
  }

  /* -- Deck sheet palette --------------------------------------
     Every chapter gets its own quiet tint so overlapping sheets stay
     distinguishable in BOTH themes (the base rule above would flatten
     them all to --bg). color-mix against theme tokens resolves per
     theme automatically. Sections with their own opaque stages (hero,
     materials, blast, splash, band) keep them — their rules just pin
     the matching sheet color underneath. */

  /* features + testi base: cool blue sheet. */
  html.js main > .section--cool {
    background-color: color-mix(in oklab, var(--aur-blue) 6%, var(--bg));
  }

  /* testi: same family as features, one step quieter, so it separates
     from the stronger pricing panel before it AND the dark stage
     footer after it. Equal specificity with the .section--cool rule —
     MUST stay after it in source order. */
  html.js main > .testi {
    background-color: color-mix(in oklab, var(--aur-blue) 3%, var(--bg));
  }

  /* materials: restore its own dark photo stage in BOTH themes — its
     scrims and hard-coded light copy are keyed to it. */
  html.js main > .materials {
    background-color: oklch(0.105 0.008 260);
  }

  /* colorways: violet whisper under the aurora blobs. */
  html.js main > .colorways {
    background-color: color-mix(in oklab, var(--aur-violet) 4%, var(--bg));
  }

  /* blast: pin the sheet color to the film's screen-blend ground so a
     corner-radius reveal or load gap can never flash a mismatch. */
  html.js main .blast { background-color: #06080c; }

  /* statement: neutral graphite (dark) / porcelain (light) lift
     after the near-black blast. */
  html.js main > .statement {
    background-color: color-mix(in oklab, var(--ink) 4.5%, var(--bg));
  }

  /* story: intentionally PLAIN --bg (deck base rule) — the quiet base
     sheet that sets up the violet lift after it. Documented, not
     accidental. */

  /* premium: violet raised to a real hue cast beside the plain story
     sheet. */
  html.js main > .section--violet {
    background-color: color-mix(in oklab, var(--aur-violet) 10%, var(--bg));
  }

  /* unfold: sea-glass teal, kept low so premium's violet before it and
     the band's gradient after it both read as steps. */
  html.js main > .section--mint {
    background-color: color-mix(in oklab, var(--aur-teal) 3%, var(--bg));
  }

  /* technology: blue (not teal — unfold owns teal two sheets back). */
  html.js main > .section--warm {
    background-color: color-mix(in oklab, var(--aur-blue) 7%, var(--bg));
  }

  /* vapor: intentionally plain --bg — the quiet beat between
     technology (blue) and pricing (panel). No rule. */

  /* pricing: strongest neutral lift on the page. */
  html.js main > .section--panel {
    background-color: color-mix(in oklab, var(--ink) 6%, var(--bg));
  }

  /* Low-content chapters OPT OUT of the deck: stretched to 100svh they
     read as big empty sheets, so instead they keep their natural height
     and simply ride across the held sheet beneath them as rounded
     strips (positioned so DOM order still paints them on top). */
  html.js main > .statement,
  html.js main > .vapor,
  html.js main > .band {
    position: relative;
    top: auto;
    min-height: 0;
    border-radius: clamp(22px, 3vw, 34px);
    /* No dwell on the strips. They don't hold anything themselves — they
       ride across the sheet beneath — so delaying the next sheet only
       widens the window where that sheet has already scrolled away,
       falling back through chapters the reader has finished. The hold
       beat belongs to the full sheets. */
    margin-bottom: 0;
  }

  /* The last sheet gets no dwell. A sticky box may only travel inside its
     containing block's content box less its own margins, so a trailing
     margin on the final sheet ends its stick early and uncovers a strip
     of bare <main> before the footer arrives. The footer's own arrival
     is that chapter's hold beat. */
  html.js main > section:last-child { margin-bottom: 0; }

  /* testi stays a full sheet but centres its deck so the last held
     sheet doesn't pin with a top-anchored dead band under the
     arriving footer. */
  html.js main > .testi {
    display: grid;
    align-content: center;
  }

  /* materials: the media must fill the stretched 100svh sheet, or its
     bottom-anchored light copy slides onto an exposed --bg strip. */
  html.js .materials__media {
    height: max(100svh, clamp(560px, 104vh, 920px));
  }

  /* Footer arrives as the final sheet over the held testimonials —
     on its designed dark stage in BOTH themes (the wordmark, column
     headings, hairlines and the X social chip are all hard-coded
     light and keyed to it). Hairline uses --stage-border because
     --border is near-black in light theme, invisible on navy. */
  html.js .site-footer {
    position: relative;
    z-index: 1;
    background-color: var(--stage);
    border-radius: clamp(22px, 3vw, 34px) clamp(22px, 3vw, 34px) 0 0;
    box-shadow: var(--deck-shadow);
    border-top: 1px solid var(--stage-border);
  }

  /* -- Deck paint safety: no permanent layers inside the sheets ---
     A held sheet keeps painting underneath every sheet stacked on top
     of it, so a permanently composited descendant is a hazard: the
     compositor orders that layer against the covering sheets by
     overlap heuristics, and when it wins it draws straight through
     them. `isolation` above gives each sheet a stacking context but
     does NOT force the sheet above onto its own layer, so it cannot
     settle this on its own.

     Both reported artefacts were exactly this — a .blast__note tearing
     through the statement sheet, and .story__media img tearing through
     the premium sheet. Nothing listed here animates continuously (the
     photo parallax is scrub-driven, the cards are hover/drag driven),
     so `will-change` was only ever a hint here; dropping it costs no
     smoothness and takes a dozen full-size layers out of the
     compositor's budget, which is what was shedding tiles as the dark
     rectangles. .hero__film-wrap keeps its promotion — that canvas is
     genuinely scrubbed every frame. */
  html.js .story__media img,
  html.js .materials__media img,
  html.js .unfold__card,
  html.js .testi__card,
  html.js .colorways__stage-3d,
  html.js .hero__copy {
    will-change: auto;
  }

  /* The blast annotations were a backdrop-filter over an almost
     transparent gradient: a composited layer with next to nothing of
     its own to paint, sitting inside the GSAP-pinned (position: fixed)
     film and covered by the statement sheet — which is why it was the
     fragment that tore through. Over the film's near-black ground
     (#06080c) the blur was doing almost no visible work, so the card
     carries its own opaque gradient instead. */
  html.js .blast__note {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: linear-gradient(
      165deg,
      oklch(0.21 0.012 260 / 0.97),
      oklch(0.155 0.010 260 / 0.94)
    );
  }

  /* Same story for the 360° hint inside the colorways sheet: a 55px
     badge blurring a flat sheet tint, so the blur was invisible work
     for a whole compositor layer under three sheets of cover. */
  html.js .cw360 {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background-color: oklch(0.18 0.006 260 / 0.95);
  }
}

/* -- 7. Light-theme corrections (audit 2026-07-16) -------------- */

/* Hero: keep the vignette on the forced-dark stage in light theme
   (it was gated on [data-theme="dark"]). */
[data-theme="light"] .hero--unbox::after { opacity: 1; }

/* Unfold dash mock: legible sleep stages + ring track in light theme.
   Equal specificity with styles.css — premium.css wins by order. */
.dash__bars .s-awake {
  background: color-mix(in oklab, var(--ink) 28%, var(--surface-2));
}

[data-theme="light"] .dash__bars .s-rem { background: oklch(0.55 0.13 200); }

.dash__track { stroke: color-mix(in oklab, var(--ink) 14%, transparent); }

/* Colorways: derive the finish glow from the theme-aware --cw-a in
   light theme so the selected-chip and case-hover halos stop
   vanishing. (0,3,0) beats the per-finish [data-color] rules. */
[data-theme="light"] .colorways,
[data-theme="light"] .colorways[data-color] {
  --cw-glow: color-mix(in oklab, var(--cw-a) 38%, transparent);
}

/* Testimonial avatars: white initials need a darker ground in light
   theme (accent → accent-press ≈ 5.5:1). */
[data-theme="light"] .testi__avatar {
  background: linear-gradient(145deg, var(--accent), var(--accent-press));
}

/* Footer focus ring tracks the actual foreground color — on the
   always-dark footer stage, currentColor is the light link ink.
   Ties styles.css's grouped rule and wins by source order. */
.site-footer :focus-visible { outline-color: currentColor; }

/* -- Reduced motion ------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .hero--unbox .hero__display em,
  .section-head__title em,
  .materials__title em {
    animation: none;
  }
  .colorways::before,
  .colorways__halo,
  .cw360__orbit { animation: none; }
  .btn--primary::after { display: none; }
  .colorways__meta.is-swap [data-cw-name],
  .colorways__meta.is-swap [data-cw-tag],
  .colorways__meta.is-swap [data-cw-desc] { animation: none; }
}
