/* ==========================================================================
   Dreamscreen — brand page styles (scaffolding)
   --------------------------------------------------------------------------
   Scoped under `#dreamscreen-page` / `.dreamscreen`. FLUID-FIRST like the
   sibling brands: one clamp() type + space scale from ~360px to ~1600px —
   reach for the tokens before writing a one-off px value or @media query.

   Tokens:
     --ds-step--1 … --ds-step-6      fluid font sizes (step-0 = body)
     --ds-space-3xs … --ds-space-2xl fluid spacing
     --ds-gutter                     fluid page side-gutter
     --ds-shell-max                  1024px content column
     --ds-header-shell               966px — the Elementor header's INNER
                                     content column (measured live); use for
                                     anything that must sit on the header line
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
#dreamscreen-page {
  /* — Fluid TYPE scale (≈1.25 ratio; min @360px viewport, max @1600px) — */
  --ds-step--1: clamp(0.80rem, 0.76rem + 0.18vw, 0.94rem);
  --ds-step-0:  clamp(1.00rem, 0.94rem + 0.27vw, 1.18rem);   /* body */
  --ds-step-1:  clamp(1.20rem, 1.08rem + 0.55vw, 1.55rem);
  --ds-step-2:  clamp(1.44rem, 1.22rem + 0.98vw, 2.05rem);
  --ds-step-3:  clamp(1.73rem, 1.37rem + 1.60vw, 2.70rem);
  --ds-step-4:  clamp(2.07rem, 1.50rem + 2.55vw, 3.55rem);
  --ds-step-5:  clamp(2.49rem, 1.62rem + 3.85vw, 4.70rem);
  --ds-step-6:  clamp(2.99rem, 1.55rem + 6.40vw, 6.50rem);   /* hero display */

  /* — Fluid SPACE scale — */
  --ds-space-3xs: clamp(0.25rem, 0.23rem + 0.09vw, 0.31rem);
  --ds-space-2xs: clamp(0.50rem, 0.46rem + 0.18vw, 0.63rem);
  --ds-space-xs:  clamp(0.75rem, 0.69rem + 0.27vw, 0.94rem);
  --ds-space-s:   clamp(1.00rem, 0.91rem + 0.36vw, 1.25rem);
  --ds-space-m:   clamp(1.50rem, 1.24rem + 1.16vw, 2.50rem);
  --ds-space-l:   clamp(2.00rem, 1.48rem + 2.32vw, 4.00rem);
  --ds-space-xl:  clamp(3.00rem, 1.96rem + 4.64vw, 7.00rem);
  --ds-space-2xl: clamp(4.00rem, 2.43rem + 6.96vw, 10.00rem);

  /* — Containers — */
  --ds-shell-max: 1024px;
  --ds-header-shell: 966px;      /* the header's inner column (measured live) */
  --ds-gutter: clamp(1rem, 0.4rem + 3vw, 4rem);

  /* — Palette (placeholders — set real brand values once the look lands) — */
  --ds-bg: #000000;
  --ds-fg: #ffffff;
  --ds-muted: rgba(235, 235, 245, 0.72);
  --ds-accent: #0065ff;

  /* — SECTION DESIGN SYSTEM (one voice for every pinned beat) —
     --ds-title    every section H2 (size only; weight 500 / lh 1.18 /
                   ls -0.015em are repeated per component)
     --ds-pin-pad  top clearance under the floating header pill inside a
                   pinned stage (desktop; the mobile MQ below re-tunes it)
     Paragraph voice: color var(--ds-muted) + line-height 1.6.
     Captions/labels voice: rgba(235,235,245,0.6) + --ds-step--1/0. */
  --ds-title: clamp(1.55rem, 1.05rem + 2.2vw, 2.8rem);
  --ds-pin-pad: clamp(132px, 15svh, 176px);
}
@media (max-width: 767px) {
  #dreamscreen-page { --ds-pin-pad: 128px; }
}

/* --------------------------------------------------------------------------
   2. RESET & SCOPE
   -------------------------------------------------------------------------- */
#dreamscreen-page,
#dreamscreen-page *,
#dreamscreen-page *::before,
#dreamscreen-page *::after {
  box-sizing: border-box;
}

#dreamscreen-page {
  position: relative;
  width: 100%;
  margin: 0;
  padding: 0;
  background: var(--ds-bg);
  color: var(--ds-fg);
  /* Clip the inline axis only — a blanket overflow:hidden would silently
     disable position:sticky (pinned scenes + slider navs rely on it). */
  overflow-x: clip;
  overflow-y: visible;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-size: var(--ds-step-0);
  line-height: 1.6;
}

/* Defensive: body{overflow-x:hidden} would make <body> a scroll container and
   kill sticky. Re-assert `clip` on this brand only. */
body.sonic-brand-dreamscreen {
  overflow-x: clip !important;
  /* Explicit per-brand backdrop (the global body-black is being phased
     out). Flip to white if the design lands light. */
  background-color: #000 !important;
}

/* SUB-PIXEL SEAM GUARD (house rule since Moovia/Duvaltex): fractional
   section heights let the backdrop show through a hairline gap between
   sections. Overlap every section 1px over the one above — invisible on
   solid section backgrounds. */
#dreamscreen-page section + section,
#dreamscreen-page div + section {
  margin-block-start: -1px;
}

/* --------------------------------------------------------------------------
   3. CONTENT SHELLS
   -------------------------------------------------------------------------- */
.ds-shell {
  width: 100%;
  max-width: var(--ds-shell-max);
  margin-inline: auto;
  padding-inline: var(--ds-gutter);
}
/* Align content to the HEADER's inner column (start-edge trick from the
   sibling brands) — use on blocks that must sit exactly on the header's line. */
.ds-align-header {
  padding-inline: max(16px, calc((100% - var(--ds-header-shell)) / 2));
}

/* --------------------------------------------------------------------------
   4. A11Y — skip link, focus policy, reduced motion baseline
   -------------------------------------------------------------------------- */
.dreamscreen-skip-link {
  position: absolute;
  inset-inline-start: var(--ds-space-s);
  inset-block-start: var(--ds-space-s);
  z-index: 1000;
  padding: var(--ds-space-2xs) var(--ds-space-s);
  background: var(--ds-fg);
  color: var(--ds-bg);
  border-radius: 8px;
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform 0.2s ease;
}
.dreamscreen-skip-link:focus { transform: translateY(0); }

/* NO focus rings on this page's interactive elements (client requirement;
   Safari repaints them on programmatic refocus even with :focus-visible). */
#dreamscreen-page a:focus,
#dreamscreen-page button:focus,
#dreamscreen-page [tabindex]:focus,
#dreamscreen-page a:focus-visible,
#dreamscreen-page button:focus-visible {
  outline: none !important;
}
#dreamscreen-page a,
#dreamscreen-page button {
  -webkit-tap-highlight-color: transparent;
}

.ds-sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}

@media (prefers-reduced-motion: reduce) {
  #dreamscreen-page *,
  #dreamscreen-page *::before,
  #dreamscreen-page *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------------
   5. HERO — the house composition on a BLACK stage: contained clip at the
   top (clear of the fixed header), gray-gradient title lines, paragraph
   and blue CTA beneath it — everything in normal flow (no overlay).
   svh on purpose (page-top hero; the URL bar is expanded on landing);
   data-ds-pin freezes it in px against in-app chrome collapse.
   -------------------------------------------------------------------------- */
.ds-hero {
  position: relative;
  height: 100vh;                 /* fallback */
  height: 100svh;
  background: #000;
  overflow: hidden;
}
.ds-hero__stage {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  /* Clear the fixed header + air: its pill bottoms at ~117px @1440 and
     ~158px on mobile — the CLIP is the topmost element here. */
  padding-block-start: clamp(135px, 15vh, 180px);
  /* +24px lifts the whole centered cluster — the "Or scroll down" hint
     needed real air from the viewport's bottom edge. */
  padding-block-end: calc(clamp(2.5rem, 7vh, 5rem) + 24px);
  padding-inline: var(--ds-gutter);
  gap: clamp(0.75rem, 1.8vh, 1.25rem);
}
.ds-hero__videowrap {
  --ds-hero-video-h: 40vh;       /* a touch smaller — hands the bottom
                                    cluster (incl. the scroll hint) room */
  width: min(94vw, calc(var(--ds-hero-video-h) * 16 / 9), 1400px);
  aspect-ratio: 16 / 9;
  flex: 0 0 auto;
}
.ds-hero__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;           /* the clip's own bg is black = seamless */
  pointer-events: none;
  background: #000;
}
@media (max-width: 767px) {
  .ds-hero__stage {
    /* The stage CENTERS its content, so the bottom padding is what
       actually pushes the whole cluster (clip + title + paragraph +
       CTA) upward; the 164px top is only the pill-clearance floor
       (mobile pill ~158px). +28px per review. */
    padding-block-start: 164px;
    padding-block-end: calc(clamp(2rem, 6vh, 4rem) + 48px);   /* hint air */
  }
  /* Taller mobile stage, cover-cropped sides (the clip's bg is black, so
     the crop is invisible and the subject scales up). */
  .ds-hero__videowrap {
    width: 100vw;
    aspect-ratio: auto;
    height: min(36vh, 100vw);
  }
  .ds-hero__video { object-fit: cover; }
}
.ds-hero__title {
  margin: 0;
  font-weight: 500;              /* design system — same weight as every H2 */
  font-size: clamp(1.5rem, 1rem + 2.2vw, 2.9rem);   /* a step down per review */
  line-height: 1.18;
  letter-spacing: -0.02em;
}
/* Each title line: its own block + its own gray (Valerion) gradient, so it
   clips and scales cleanly as one unit. Hidden until JS reveals. */
.ds-hero__line {
  display: block;
  background: linear-gradient(90deg, #fdfdfd, #e6e6e6, #fff, #cfcfcf, #9e9e9e);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
html[dir="rtl"] .ds-hero__line {
  background: linear-gradient(-90deg, #fdfdfd, #e6e6e6, #fff, #cfcfcf, #9e9e9e);
  -webkit-background-clip: text;
  background-clip: text;
}
.ds-hero__line:first-child { margin-block-end: 0.12em; }
.ds-hero__subtitle {
  margin: clamp(0.2rem, 1vh, 0.6rem) 0 0;
  max-width: 46ch;
  color: var(--ds-muted);
  font-size: clamp(1.02rem, 0.96rem + 0.3vw, 1.25rem);
  font-weight: 400;
  line-height: 1.5;
  text-wrap: pretty;
}
.ds-hero__cta {
  display: inline-flex;
  align-items: center;
  margin-block-start: clamp(0.2rem, 1vh, 0.6rem);
  padding: 0.8em 1.9em;
  background: #0065ff;
  color: #fff !important;
  font-size: var(--ds-step-0);
  font-weight: 500;
  line-height: 1;
  text-decoration: none !important;
  border-radius: 999px;
  transition: background 0.2s ease, transform 0.2s ease;
}
.ds-hero__cta { position: relative; }   /* anchor for the hint below */
.ds-hero__cta:hover { background: #0052d6; transform: translateY(-2px); }
/* MOBILE hero rhythm — MUST sit AFTER the title/subtitle/CTA base rules
   (source order wins at equal specificity; earlier attempts sat before
   them and never applied — the recurring trap). Title drops; the
   paragraph sits EXACTLY midway between title and CTA. */
@media (max-width: 767px) {
  .ds-hero__title { margin-block-start: 14px; }
  .ds-hero__subtitle { margin-block-start: -5px; }
  .ds-hero__cta { margin-block-start: calc(clamp(0.2rem, 1vh, 0.6rem) - 6px); }
}
/* Quiet "Or scroll down" hint hanging UNDER the pill — absolute, so it
   never changes the hero's layout; opacity rides the pill (parent). */
.ds-hero__scrollhint {
  position: absolute;
  top: calc(100% + 12px);
  left: 50%;
  transform: translateX(-50%);
  color: rgba(235, 235, 245, 0.55);
  font-size: 0.82rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  white-space: nowrap;
  pointer-events: none;
}
.ds-hero__noscript {
  position: absolute;
  inset-block-end: 2rem;
  inset-inline: 0;
  text-align: center;
  color: #fff;
}
/* --------------------------------------------------------------------------
   5b. S2 — LOGO MOMENT. Black pinned beat: DreamScreen logo, then the
   UltraWave 7 logo — each fades in with a monotonic zoom, keeps growing
   while fading out. initLogos() drives opacity/scale via the lerp.
   -------------------------------------------------------------------------- */
.ds-logos {
  position: relative;
  height: 260vh;                 /* 100vh stage + ~160vh for the two beats */
  background: #000;
}
.ds-logos__stage {
  position: sticky;
  top: 0;
  height: 100vh;                 /* fallback */
  /* svh, NOT vh: iOS Safari's URL bar expands on scroll-UP and hides the
     stage's bottom ~110px (100vh = the LARGE viewport). svh always fits
     the smallest window; the surplus in the collapsed state is black-on-
     black inside the section — invisible. svh is STABLE (dvh, which
     resizes mid-pin, stays forbidden — house rule). */
  height: 100svh;
  overflow: hidden;
  background: #000;
}
.ds-logos__scene {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 8vw;
  pointer-events: none;
  opacity: 0;                    /* initLogos() drives */
  will-change: opacity;
}
.ds-logos__img {
  display: block;
  height: auto;
  transform: scale(0.72);        /* at-rest pose before the first frame */
  will-change: transform;
}
.ds-logos__img--brand { width: clamp(210px, 42vw, 500px); }
.ds-logos__img--ultra { width: clamp(230px, 48vw, 580px); }
/* Reduced motion: a static, stacked pair — no pin. */
.ds-logos--static { height: auto; }
.ds-logos--static .ds-logos__stage {
  position: relative;
  height: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ds-space-l);
  padding-block: var(--ds-space-2xl);
}
.ds-logos--static .ds-logos__scene {
  position: relative;
  inset: auto;
  opacity: 1;
}
.ds-logos--static .ds-logos__img { transform: none; }
/* Chevron-down Lottie hint — bottom-center of the pinned stage, visible
   only during the DreamScreen-logo beat (initLogos() toggles .is-on). */
.ds-logos__arrow {
  position: absolute;
  inset-inline: 0;
  inset-block-end: clamp(24px, 7svh, 64px);
  margin-inline: auto;
  width: 54px;
  height: 54px;
  opacity: 0;
  transition: opacity 0.6s ease;
  pointer-events: none;
}
.ds-logos__arrow.is-on { opacity: 1; }

/* --------------------------------------------------------------------------
   5c. S3 — "The final surface before your eyes". Dark pinned beat:
   image fades in on approach; the copy reveals at the pin and HOLDS
   (the read moment). Plain vh for the pin per the house rule;
   data-ds-pin freezes it in px. initS2() drives opacity/y via the lerp.
   -------------------------------------------------------------------------- */
.ds-s2 {
  position: relative;
  height: 240vh;                 /* design system — uniform content-pin length */
  background: #000;
}
.ds-s2__stage {
  position: sticky;
  top: 0;
  height: 100vh;                 /* fallback */
  /* svh, NOT vh: iOS Safari's URL bar expands on scroll-UP and hides the
     stage's bottom ~110px (100vh = the LARGE viewport). svh always fits
     the smallest window; the surplus in the collapsed state is black-on-
     black inside the section — invisible. svh is STABLE (dvh, which
     resizes mid-pin, stays forbidden — house rule). */
  height: 100svh;
  overflow: hidden;
  display: flex;
  /* SHORT-copy beat: CENTERED in the band below the pill (the balance
     call from review: short content centers, long content top-anchors —
     S5/S7/S8 stay top-anchored). */
  align-items: center;
  background: #000;
  padding-block: var(--ds-pin-pad) clamp(1.5rem, 4svh, 3rem);
}
.ds-s2__inner {
  width: 100%;
  display: grid;
  gap: var(--ds-space-l);
}
/* Desktop: copy | image, 50/50; the image fills its column height. */
@media (min-width: 768px) {
  .ds-s2__inner {
    grid-template-columns: 1fr 1fr;
    column-gap: clamp(2rem, 4vw, 4.5rem);
    align-items: center;
  }
}
.ds-s2__title {
  margin: 0;
  font-size: var(--ds-title);   /* design system — every section H2 */
  font-weight: 500;
  line-height: 1.18;
  letter-spacing: -0.015em;
  color: #f5f5f7;
  text-wrap: balance;
}
.ds-s2__text {
  margin: var(--ds-space-m) 0 0;
  max-width: 58ch;
  color: var(--ds-muted);        /* design system — paragraph voice */
  font-size: var(--ds-step-0);
  line-height: 1.6;
  font-weight: 400;
  text-wrap: pretty;
}
.ds-s2__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: clamp(14px, 1.8vw, 22px);
}
/* The fade rides the WRAPPER, so the play/pause button fades with the
   clip as one unit. */
.ds-s2__mediawrap {
  opacity: 0;                    /* initS2() fades it in on approach */
  will-change: opacity;
}
@media (min-width: 768px) {
  /* NO cover-crop: the clip must show in full. Natural height (follows
     the width), capped only by max-height with the width shrinking to
     match via the centered column. */
  .ds-s2__img {
    max-height: 72vh;
    width: auto;
    max-width: 100%;
    margin-inline: auto;
  }
  /* fit-content so the corner button hugs the clip itself, not the cell. */
  .ds-s2__mediawrap { width: fit-content; margin-inline: auto; max-width: 100%; }
}
.ds-s2__mediawrap { position: relative; }
/* Play / Pause — glass circle in the clip's bottom-right (physical)
   corner; mirrors the REAL playback state (is-playing -> pause glyph). */
.ds-s2__pp,
.ds-s2__pp:hover,
.ds-s2__pp:focus,
.ds-s2__pp:active {
  position: absolute;
  right: 10px;
  bottom: 10px;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  appearance: none;
  margin: 0;
  padding: 0;
  border-radius: 50%;
  border: 0 !important;
  /* NO backdrop-filter (iOS half-clips it on round elements — see the
     layers nav note); a denser rgba reads the same over the clip. */
  background: rgba(110, 110, 115, 0.72) !important;   /* beat the kit */
  color: #fff !important;
  box-shadow: none !important;
  cursor: pointer;
  transition: background-color 0.25s ease;
}
.ds-s2__pp:hover { background: rgba(140, 140, 145, 0.65) !important; }
.ds-s2__pp svg { width: 15px; height: 15px; }
.ds-s2__pp .ds-s2__pp-pause { display: none; }
.ds-s2__pp.is-playing .ds-s2__pp-play  { display: none; }
.ds-s2__pp.is-playing .ds-s2__pp-pause { display: block; }
/* Copy reveal — TIME-BASED (CSS transitions on .is-in), NOT scroll-
   scrubbed: desktop wheels scroll in discrete steps, and a scrubbed
   fade advanced in visible chunks. initS2() toggles .is-in at the pin
   (and un-toggles below it, so it replays). The scrubbed EXIT fade is
   applied by JS to .ds-s2__copy (the wrapper), so it never fights
   these transitions. */
.ds-s2__copy { will-change: opacity; }
.ds-s2__reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.9s linear, transform 1s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.ds-s2.is-in .ds-s2__reveal {
  opacity: 1;
  transform: translateY(0);
}
.ds-s2.is-in .ds-s2__text { transition-delay: 0.15s; }
/* Reduced motion / no-JS fallback: everything visible, no pin. */
.ds-s2--static { height: auto; }
.ds-s2--static .ds-s2__stage {
  position: relative;
  height: auto;
  padding-block: var(--ds-space-2xl);
}
.ds-s2--static .ds-s2__img,
.ds-s2--static .ds-s2__mediawrap,
.ds-s2--static .ds-s2__reveal {
  opacity: 1 !important;
  transform: none !important;
}

/* --------------------------------------------------------------------------
   5d. S4 — THE LAYERS ("Four layers. One invisible surface."). Dark
   pinned beat: section head (title + intro) on the header column, then
   image (with numbered hotspots) | panel — counter, layer title, layer
   description and round chevron arrows — split by a hairline divider.
   Hotspot coordinates are PHYSICAL percentages of the shot (the footage
   never mirrors under RTL); the chevrons flip visually in RTL while
   prev/next stay logical. initLayers() drives the scrub + switching.
   -------------------------------------------------------------------------- */
.ds-layers {
  position: relative;
  height: 240vh;                 /* 100vh stage + ~140vh of pinned beat */
  background: #000;
}

.ds-layers__stage {
  position: sticky;
  top: 0;
  height: 100vh;                 /* fallback */
  /* svh, NOT vh: iOS Safari's URL bar expands on scroll-UP and hides the
     stage's bottom ~110px (100vh = the LARGE viewport). svh always fits
     the smallest window; the surplus in the collapsed state is black-on-
     black inside the section — invisible. svh is STABLE (dvh, which
     resizes mid-pin, stays forbidden — house rule). */
  height: 100svh;
  overflow: hidden;
  display: flex;
  /* SHORT-copy beat: CENTERED in the band below the pill (review). */
  align-items: center;
  background: #000;
  padding-block: var(--ds-pin-pad) clamp(1.5rem, 4svh, 3rem);   /* design system */
}
@media (max-width: 767px) {
  .ds-layers__stage { padding-block-start: 170px; }
}
.ds-layers__wrap { width: 100%; }

/* — Section head — */
.ds-layers__title {
  margin: 0;
  color: #f5f5f7;
  font-size: var(--ds-title);   /* design system — every section H2 */
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.ds-layers__intro {
  margin: var(--ds-space-s) 0 0;
  max-width: 62ch;
  color: var(--ds-muted);        /* design system — paragraph voice */
  font-size: var(--ds-step-0);
  line-height: 1.6;
  font-weight: 400;
  text-wrap: pretty;
}

/* — The split: image | panel — */
.ds-layers__inner {
  width: 100%;
  display: grid;
  gap: var(--ds-space-m);
  margin-block-start: var(--ds-space-l);
}
@media (min-width: 768px) {
  .ds-layers__inner {
    grid-template-columns: 1.15fr 1fr;
    column-gap: clamp(2rem, 4vw, 4rem);
    align-items: center;
  }
  /* Hairline divider between the shot and the panel. */
  .ds-layers__panel {
    border-inline-start: 1px solid rgba(255, 255, 255, 0.14);
    padding-inline-start: clamp(1.5rem, 3vw, 3rem);
  }
  /* Image height is bounded via its width so head + split always fit
     the 100vh stage (proportional -> hotspot % anchors stay true). */
  .ds-layers__media { max-width: min(100%, calc((100vh - 470px) * 1.79)); }
}
.ds-layers__media {
  position: relative;
  border-radius: clamp(14px, 1.8vw, 22px);
  overflow: hidden;
  opacity: 0;                    /* initLayers() fades it in on approach */
  will-change: opacity;
}
.ds-layers__img {
  display: block;
  width: 100%;
  height: auto;
  background: #000;
  pointer-events: none;
}
/* Numbered hotspots — glass dots on the shot; hidden until the media has
   fully faded in (.is-ready on the section). PHYSICAL left/top on purpose. */
.ds-layers__spot,
.ds-layers__spot:hover,
.ds-layers__spot:focus,
.ds-layers__spot:active {
  position: absolute;
  left: var(--x);
  top: var(--y);
  transform: translate(-50%, -50%);
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  appearance: none;
  margin: 0;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.75) !important;
  background: rgba(255, 255, 255, 0.16) !important;   /* beat the kit */
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: #fff !important;
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  box-shadow: none !important;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s ease, background-color 0.25s ease,
              border-color 0.25s ease, transform 0.25s ease;
}
.ds-layers.is-ready .ds-layers__spot {
  opacity: 1;
  pointer-events: auto;
}
.ds-layers__spot:hover { transform: translate(-50%, -50%) scale(1.12); }
.ds-layers__spot.is-active,
.ds-layers__spot.is-active:hover,
.ds-layers__spot.is-active:focus {
  background: #0065ff !important;
  border-color: #0065ff !important;
}
@media (max-width: 767px) {
  .ds-layers__spot { width: 26px; height: 26px; font-size: 12px; }
}

/* — The panel: counter, layer title + description, chevrons — */
.ds-layers__count {
  margin: 0 0 var(--ds-space-2xs);
  color: rgba(235, 235, 245, 0.55);
  font-size: var(--ds-step-0);
  font-variant-numeric: tabular-nums;          /* 1/4 -> 4/4 without wobble */
}
.ds-layers__items { display: grid; }
.ds-layers__item {
  grid-area: 1 / 1;              /* all four share one cell */
  opacity: 0;
  pointer-events: none;
}
.ds-layers__item.is-active { opacity: 1; pointer-events: auto; }
/* Switching (spots or arrows) — a slower, two-part entrance: the layer
   TITLE slides in from the reading side (fade-in-left; mirrored in RTL)
   and the description rises (fade-in-up) a beat behind it.
   initLayers() re-adds .is-switch so it restarts every time. */
.ds-layers__item.is-switch .ds-layers__ltitle {
  animation: ds-lt-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.ds-layers__item.is-switch .ds-layers__ldesc {
  animation: ds-ld-in 0.75s cubic-bezier(0.22, 1, 0.36, 1) 0.1s both;
}
@keyframes ds-lt-in {
  from { opacity: 0; transform: translateX(-26px); }
  to   { opacity: 1; transform: none; }
}
@keyframes ds-lt-in-rtl {
  from { opacity: 0; transform: translateX(26px); }
  to   { opacity: 1; transform: none; }
}
html[dir="rtl"] .ds-layers__item.is-switch .ds-layers__ltitle {
  animation-name: ds-lt-in-rtl;
}
@keyframes ds-ld-in {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}
.ds-layers__ltitle {
  margin: 0;
  color: #f5f5f7;
  font-size: clamp(1.3rem, 1rem + 1.4vw, 2rem);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.015em;
}
.ds-layers__ldesc {
  margin: var(--ds-space-xs) 0 0;
  max-width: 38ch;
  color: rgba(235, 235, 245, 0.6);
  font-size: var(--ds-step-0);
  line-height: 1.55;
  font-weight: 400;
  text-wrap: pretty;
}
/* Round chevron arrows. */
.ds-layers__nav {
  display: flex;
  align-items: center;
  gap: var(--ds-space-xs);
  margin-block-start: var(--ds-space-l);
}
.ds-layers__navbtn,
.ds-layers__navbtn:hover,
.ds-layers__navbtn:focus,
.ds-layers__navbtn:active {
  -webkit-appearance: none;
  appearance: none;
  margin: 0;
  padding: 0;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  /* Solid-ish surface, NO backdrop-filter: iOS Safari half-clips
     backdrop-filter on border-radius:50% elements — the buttons were
     rendering as faint top arcs (the "cut arrows"). On the black stage
     a plain rgba surface looks identical anyway. */
  border: 1px solid rgba(255, 255, 255, 0.42) !important;
  background: rgba(255, 255, 255, 0.18) !important;    /* beat the kit */
  box-shadow: none !important;
  color: #f5f5f7 !important;
  cursor: pointer;
  transition: border-color 0.25s ease, background-color 0.25s ease;
}
.ds-layers__navbtn:hover {
  border-color: rgba(255, 255, 255, 0.75) !important;
  background: rgba(255, 255, 255, 0.22) !important;
}
.ds-layers__chev { width: 18px; height: 18px; }
html[dir="rtl"] .ds-layers__chev { transform: scaleX(-1); }

/* Reveal targets — TIME-BASED like S3 (.is-in transitions; a scrubbed
   fade advanced in chunks with desktop wheel steps). The scrubbed exit
   fade rides .ds-layers__wrap (no transition there). */
.ds-layers__wrap { will-change: opacity; }
.ds-layers__reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.9s linear, transform 1s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.ds-layers.is-in .ds-layers__reveal {
  opacity: 1;
  transform: translateY(0);
}
.ds-layers.is-in .ds-layers__intro { transition-delay: 0.12s; }
.ds-layers.is-in .ds-layers__panel { transition-delay: 0.22s; }

/* Reduced motion / no-JS: no pin, everything visible, all items listed. */
.ds-layers--static { height: auto; }
.ds-layers--static .ds-layers__stage {
  position: relative;
  height: auto;
  padding-block: var(--ds-space-2xl);
}
.ds-layers--static .ds-layers__media,
.ds-layers--static .ds-layers__reveal {
  opacity: 1 !important;
  transform: none !important;
}
.ds-layers--static .ds-layers__items { display: block; }
.ds-layers--static .ds-layers__item {
  opacity: 1;
  margin-block-end: var(--ds-space-m);
}
.ds-layers--static .ds-layers__spot { display: none; }
.ds-layers--static .ds-layers__nav  { display: none; }
.ds-layers--static .ds-layers__count { display: none; }

/* MOBILE OVERRIDES — MUST come AFTER every base rule above (same
   specificity: source order wins; these once sat before the base stage
   rule and silently lost — the clipped-arrows saga). */
@media (max-width: 767px) {
  /* THE PAUSE-AT-TOP: the section scrolls in normally; when the title
     reaches its resting spot (150px, under the pill) the WHOLE block
     freezes for a short beat — even though it is taller than the
     screen — then releases and scrolls on normally. Mechanic: the
     stage is sticky (top 150) and the section's ::after spacer is the
     pause length; no clipping, no size compression. */
  /* S3 mobile: shorter pin — its exit fade is OFF on mobile (JS), so
     the content scrolls out naturally instead of leaving a full-screen
     black void between it and the Layers. */
  .ds-s2 { height: 200vh; }   /* uniform mobile pin length */
  .ds-layers { height: auto !important; padding-block-start: 132px; }
  .ds-layers::after { content: ''; display: block; height: 30vh; }
  .ds-layers__stage {
    position: sticky;
    top: 132px;
    height: auto;
    overflow: visible;
    display: block;
    /* 6px floor: the nav circles are the stage's last pixel row and
       their bottom edge was shaved by compositing rounding. */
    padding-block: 0 6px;
  }
  .ds-layers__inner { margin-block-start: var(--ds-space-m); }
  .ds-layers__nav { margin-block-start: var(--ds-space-s); }
  /* ONE-BLOCK entrance: the shot joins the copy's fade-in-up. */
  .ds-layers__media {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity 0.9s linear, transform 1s cubic-bezier(0.22, 1, 0.36, 1);
    will-change: opacity, transform;
  }
  .ds-layers.is-in .ds-layers__media { opacity: 1; transform: none; }
  .ds-layers.is-in .ds-layers__intro { transition-delay: 0s; }
  .ds-layers.is-in .ds-layers__panel { transition-delay: 0s; }
}

/* --------------------------------------------------------------------------
   5e. S5 — "The image, preserved." Dark band: copy + orange stat rows on
   the start side, before/after comparison on the other. The divider
   position is --pos (initCompare() writes it, default 50%); the overlay
   (Bad) is clipped to the divider's left. PHYSICAL geometry throughout —
   the imagery never mirrors under RTL.
   -------------------------------------------------------------------------- */
.ds-cmp {
  position: relative;
  background: #000;
  /* Desktop: the SAME pin length as the sibling beats (S3/S6) — land,
     HOLD long enough to read the stats, scrubbed exit. */
  height: 240vh;                 /* design system — uniform content-pin length */
}
.ds-cmp__stage {
  position: sticky;
  top: 0;
  height: 100vh;                 /* fallback */
  /* svh, NOT vh: iOS Safari's URL bar expands on scroll-UP and hides the
     stage's bottom ~110px (100vh = the LARGE viewport). svh always fits
     the smallest window; the surplus in the collapsed state is black-on-
     black inside the section — invisible. svh is STABLE (dvh, which
     resizes mid-pin, stays forbidden — house rule). */
  height: 100svh;
  overflow: hidden;
  display: flex;
  /* Design system: TOP-anchored under the pill like every sibling beat. */
  align-items: flex-start;
  background: #000;
  padding-block: var(--ds-pin-pad) clamp(1.5rem, 4svh, 3rem);   /* design system */
}

.ds-cmp__inner {
  width: 100%;
  display: grid;
  gap: var(--ds-space-l);
}
@media (min-width: 768px) {
  .ds-cmp__inner {
    grid-template-columns: 0.9fr 1.25fr;
    column-gap: clamp(2.5rem, 5vw, 5rem);
    align-items: center;
  }
  /* DOM puts the media first (mobile order); on desktop the copy takes
     the FIRST column and the comparison the second (the mock). */
  .ds-cmp__copy  { grid-column: 1; grid-row: 1; }
  .ds-cmp__media { grid-column: 2; grid-row: 1; }
}
.ds-cmp__title {
  margin: 0;
  color: #f5f5f7;
  font-size: var(--ds-title);   /* design system — every section H2 */
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.ds-cmp__text {
  margin: var(--ds-space-s) 0 0;
  max-width: 44ch;
  color: var(--ds-muted);        /* design system — paragraph voice */
  font-size: var(--ds-step-0);
  line-height: 1.6;
  font-weight: 400;
  text-wrap: pretty;
}
/* Desktop: the title must hold ONE line inside the copy column — capped
   size (+ .ds-no-widow in the markup keeps preventWidows off it). */
@media (min-width: 768px) {
  .ds-cmp__title { font-size: clamp(1.55rem, 1rem + 1.35vw, 2.2rem); }
}
/* Stat rows — orange figure over its label, hairline between rows. */
.ds-cmp__stats {
  list-style: none;
  margin: var(--ds-space-m) 0 0;
  padding: 0;
  max-width: 30ch;
}
.ds-cmp__stat {
  padding-block: var(--ds-space-s);
  border-block-end: 1px solid rgba(255, 255, 255, 0.14);
}
.ds-cmp__stat:last-child { border-block-end: 0; }
.ds-cmp__num {
  display: block;
  color: #ff6b00;
  font-size: var(--ds-step-1);
  font-weight: 500;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;   /* steady width while counting up */
}
.ds-cmp__label {
  display: block;
  margin-block-start: 0.15em;
  color: rgba(235, 235, 245, 0.8);
  font-size: var(--ds-step-0);
  line-height: 1.4;
}

/* — The comparison slider — */
.ds-cmp__slider {
  --pos: 50%;
  position: relative;
  border-radius: clamp(14px, 1.8vw, 22px);
  overflow: hidden;
  cursor: ew-resize;
  /* Horizontal drags belong to the slider; vertical swipes still scroll. */
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}
.ds-cmp__img {
  display: block;
  width: 100%;
  height: auto;
  pointer-events: none;
}
/* Bad rides ABOVE Good, clipped to the divider's LEFT. */
.ds-cmp__overlay {
  position: absolute;
  inset: 0;
  clip-path: inset(0 calc(100% - var(--pos)) 0 0);
  pointer-events: none;
}
.ds-cmp__overlay .ds-cmp__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* The white divider line (the whole slider surface is draggable, so the
   line is purely visual). */
.ds-cmp__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--pos);
  width: 3px;
  transform: translateX(-50%);
  background: #fff;
  pointer-events: none;
}

/* ONE reveal unit: the whole inner (image + title + copy + stats) fades
   in/up together, and fades back out the same way when the section
   leaves the viewport (initCompare() toggles .is-in BOTH ways). */
.ds-cmp__inner {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.9s linear, transform 1s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.ds-cmp.is-in .ds-cmp__inner {
  opacity: 1;
  transform: translateY(0);
}

/* MOBILE OVERRIDES — after every base rule (source order wins). */
@media (max-width: 767px) {
  /* Same PAUSE-AT-TOP as the Layers: freeze at the section's top for a
     beat, then release into normal scroll. 150px top = shared rhythm. */
  .ds-cmp {
    height: auto !important;
    padding-block-start: 132px;
    /* A clean black beat BEFORE the section (the Layers' spacer is
       consumed by its pause, so without this the two sections shared
       the screen), and air below the page's last section. Margins sit
       outside the sticky containment — the pause length is untouched. */
    margin-block-start: 45vh;
    margin-block-end: var(--ds-space-xl);
  }
  .ds-cmp::after { content: ''; display: block; height: 30vh; }
  .ds-cmp__stage {
    position: sticky;
    top: 132px;
    height: auto;
    overflow: visible;
    display: block;
    padding-block: 0;
  }
}

/* --------------------------------------------------------------------------
   5f. S6 — "Surface pattern matters." Scroll-scrubbed pyramid. The three
   discs sit at their FINAL pyramid spots in the CSS (no-JS shows the
   finished composition); initPattern() interpolates them back to the
   stacked start and scrubs the split. All geometry hangs off --pat-d
   (disc diameter) + --pat-sx / --pat-ty (bottom-disc offsets, in D).
   -------------------------------------------------------------------------- */
.ds-pat {
  --pat-d: clamp(140px, min(22vw, 22vh), 250px);
  --pat-sx: 0.85;                /* bottom-disc horizontal center offset */
  --pat-ty: 1.45;                /* bottom-disc top (leaves a caption band
                                    under the main disc, above the pair) */
  position: relative;
  height: 250vh;
  background: #000;
}
.ds-pat__stage {
  position: sticky;
  top: 0;
  height: 100vh;                 /* fallback */
  /* svh, NOT vh: iOS Safari's URL bar expands on scroll-UP and hides the
     stage's bottom ~110px (100vh = the LARGE viewport). svh always fits
     the smallest window; the surplus in the collapsed state is black-on-
     black inside the section — invisible. svh is STABLE (dvh, which
     resizes mid-pin, stays forbidden — house rule). */
  height: 100svh;
  overflow: hidden;
  display: flex;
  /* TOP-aligned (not centered): the head hugs the header pill's line and
     the whole composition sits high — centering left a dead band. */
  align-items: flex-start;
  background: #000;
}
.ds-pat__inner {
  width: 100%;
  /* Pill clearance — the shared design-system token. */
  padding-block-start: var(--ds-pin-pad);
}
.ds-pat__head {
  text-align: center;
  max-width: 56ch;
  margin-inline: auto;
}
.ds-pat__title {
  margin: 0;
  font-size: var(--ds-title);   /* design system — every section H2 */
  font-weight: 500;
  line-height: 1.18;
  letter-spacing: -0.015em;
  color: #f5f5f7;
  text-wrap: balance;
}
.ds-pat__text {
  margin: var(--ds-space-s) auto 0;
  max-width: 52ch;
  color: var(--ds-muted);        /* design system — paragraph voice */
  font-size: var(--ds-step-0);
  line-height: 1.6;
  text-wrap: pretty;
}
/* Head reveal — TIME-BASED like the siblings (.is-in transitions). */
.ds-pat__reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.9s linear, transform 1s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.ds-pat.is-in .ds-pat__reveal { opacity: 1; transform: translateY(0); }
.ds-pat.is-in .ds-pat__text { transition-delay: 0.15s; }

/* The scene: a fixed box the pyramid is laid out in. JS fades it in on
   approach (like the S3 clip), so it starts hidden only via JS. */
.ds-pat__scene {
  position: relative;
  margin-inline: auto;
  margin-block-start: clamp(16px, 3.5vh, 40px);
  width: calc(var(--pat-d) * (1 + 2 * var(--pat-sx)));
  max-width: 100%;
  height: calc(var(--pat-d) * (1 + var(--pat-ty)) + 4.6em);
  will-change: opacity;
}
.ds-pat__fig {
  position: absolute;
  top: 0;
  margin: 0;
  width: var(--pat-d);
  display: flex;
  flex-direction: column;
  align-items: center;
  will-change: transform, opacity;
}
/* PHYSICAL geometry on purpose (like the compare slider) — the pyramid
   does not mirror in Hebrew. */
.ds-pat__fig--main { left: calc(50% - var(--pat-d) / 2); z-index: 3; }
.ds-pat__fig--a {
  left: calc(50% - var(--pat-d) * (0.5 + var(--pat-sx)));
  top: calc(var(--pat-d) * var(--pat-ty));
  z-index: 1;
}
.ds-pat__fig--b {
  left: calc(50% + var(--pat-d) * (var(--pat-sx) - 0.5));
  top: calc(var(--pat-d) * var(--pat-ty));
  z-index: 1;
}
.ds-pat__disc {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  height: auto;
  border-radius: 50%;
  object-fit: cover;
}
/* Captions rise under each disc once the split LANDS (initPattern()
   toggles .is-split both ways, so they retract when scrolling back). */
.ds-pat__cap {
  margin-block-start: 12px;
  display: grid;
  gap: 2px;
  text-align: center;
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.7s linear, transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.ds-pat.is-split .ds-pat__cap { opacity: 1; transform: translateY(0); }
.ds-pat.is-split .ds-pat__fig--a .ds-pat__cap { transition-delay: 0.08s; }
.ds-pat.is-split .ds-pat__fig--b .ds-pat__cap { transition-delay: 0.16s; }
.ds-pat__name {
  color: #f5f5f7;
  font-size: var(--ds-step-0);
  font-weight: 600;
}
.ds-pat__note {
  color: rgba(235, 235, 245, 0.6);
  font-size: var(--ds-step--1);
}
/* DESKTOP OVERRIDES — after every base rule (source order wins). No
   pyramid: ONE ROW, the pair opening PURELY SIDEWAYS out of the main
   disc; the UltraWeave disc is LARGER (1.25D) than the pair (0.85D),
   smaller overall and spread wider. The JS measures disc CENTERS, so
   the mixed sizes still stack exactly behind the main at the start. */
@media (min-width: 768px) {
  .ds-pat { --pat-d: clamp(140px, min(15vw, 26vh), 240px); }
  /* SHORT-copy beat (review): CENTER the composition in the band below
     the pill — the clearance moves from the inner onto the stage so the
     centering math excludes it. Mobile keeps its approved top rhythm. */
  .ds-pat__stage {
    align-items: center;
    padding-block: var(--ds-pin-pad) clamp(1.5rem, 4svh, 3rem);
  }
  .ds-pat__inner { padding-block-start: 0; }
  .ds-pat__scene {
    width: calc(var(--pat-d) * 3.6);
    height: calc(var(--pat-d) * 1.25 + 5.2em);
  }
  .ds-pat__fig--main {
    width: calc(var(--pat-d) * 1.25);
    left: calc(50% - var(--pat-d) * 0.625);
    top: 0;
  }
  /* Side discs: centers at ±1.35D on the main's axis (the top offset
     compensates the size difference), a 0.3D edge gap to the main. */
  .ds-pat__fig--a,
  .ds-pat__fig--b { width: calc(var(--pat-d) * 0.85); top: calc(var(--pat-d) * 0.2); }
  .ds-pat__fig--a { left: calc(50% - var(--pat-d) * 1.775); }
  .ds-pat__fig--b { left: calc(50% + var(--pat-d) * 0.925); }
  /* One shared caption line: pad the smaller figs' captions down to the
     main disc's bottom edge. */
  .ds-pat__fig--a .ds-pat__cap,
  .ds-pat__fig--b .ds-pat__cap { margin-block-start: calc(12px + var(--pat-d) * 0.2); }
}

/* Reduced motion / static: no pin, finished pyramid, everything visible. */
.ds-pat--static { height: auto; }
.ds-pat--static .ds-pat__stage {
  position: relative;
  height: auto;
  padding-block: var(--ds-space-2xl);
}
.ds-pat--static .ds-pat__reveal,
.ds-pat--static .ds-pat__cap { opacity: 1; transform: none; }

/* MOBILE OVERRIDES — after every base rule (source order wins). */
@media (max-width: 767px) {
  .ds-pat {
    /* Sized so head + pyramid clear a small-phone viewport inside the
       100vh pinned stage. */
    --pat-d: min(34vw, 18vh);
    --pat-sx: 0.78;
    height: 200vh;   /* uniform mobile pin length */
    /* Black beat after the compare block releases (its spacer is
       consumed by its pause) + air below the page's last section. */
    margin-block-start: 25vh;
    margin-block-end: var(--ds-space-xl);
  }
  /* Tuned LIVE against the pill (user's red-line screenshot): the title
     renders ~35px lower than the raw padding suggests, so this sits it
     just under the pill's bottom edge without colliding. */
  .ds-pat__inner { padding-block-start: var(--ds-pin-pad); }   /* 128px token */
  .ds-pat__text { max-width: 40ch; }
}

/* --------------------------------------------------------------------------
   5g. S7 — "The sound, preserved." One pin, three beats: clip plays
   centered -> clip fades out (still pinned) -> copy reveals -> the
   centered 3.3dB stat rises (slow count-up). initSound() scrubs the
   media/exit opacity; the copy + stat reveals are time-based (.is-in /
   .is-stat transitions), same rhythm as every sibling beat.
   -------------------------------------------------------------------------- */
.ds-snd {
  position: relative;
  height: 240vh;                 /* design system — uniform content-pin length */
  background: #000;
}
.ds-snd__stage {
  position: sticky;
  top: 0;
  height: 100vh;                 /* fallback */
  /* svh, NOT vh: iOS Safari's URL bar expands on scroll-UP and hides the
     stage's bottom ~110px (100vh = the LARGE viewport). svh always fits
     the smallest window; the surplus in the collapsed state is black-on-
     black inside the section — invisible. svh is STABLE (dvh, which
     resizes mid-pin, stays forbidden — house rule). */
  height: 100svh;
  overflow: hidden;
  display: flex;
  /* TOP-aligned (not centered): centering pushed the overflow of a tall
     stack UP under the header pill — flex-start makes the clip's top
     line fixed and any overflow clip at the bottom instead. */
  align-items: flex-start;
  background: #000;
  /* Pill clearance while pinned. */
  padding-block-start: var(--ds-pin-pad);   /* design system */
  padding-block-end: clamp(1.5rem, 4vh, 3rem);
}
/* Clip ABOVE the copy — one composition, revealed together at the pin. */
.ds-snd__inner { width: 100%; }
/* The media column is sized to the CLIP (cap by height on desktop, full
   width on phones); clip + control fade as one. The trans2 frame carries
   its own dark margins (cinema-room composition), which read as natural
   spacing around the screen. */
.ds-snd__media {
  width: min(100%, calc(34svh * 1.779));  /* 1.779 = 1672/940; 34svh (was
                                             38) lifts the stack — the
                                             3.3dB stat hugged the bottom */
  margin-inline: auto;
  will-change: opacity;
}
/* No crop and no rounding: the frame's edges are pure black and melt
   into the section background. */
.ds-snd__mediawrap { width: 100%; }
.ds-snd__video {
  display: block;
  width: 100%;
  height: auto;
}
.ds-snd__copy {
  text-align: center;
  /* The user's blue-line measure: a TIGHT beat below the control. */
  margin-block-start: 16px;
}
/* Play / Pause — the SAME glass circle recipe as the S3 clip (NO
   backdrop-filter: iOS half-clips it on round elements), but here it
   sits CENTERED below the clip, clear of the imagery. */
.ds-snd__pp,
.ds-snd__pp:hover,
.ds-snd__pp:focus,
.ds-snd__pp:active {
  position: static;
  width: 36px;
  height: 36px;
  display: flex;                 /* block-level -> margin-inline centers */
  align-items: center;
  justify-content: center;
  /* The user's green-line measure: the control rides UP into the trans2
     frame's baked dark strip, hugging the visible chairs' lower edge.
     %-margin tracks the media width, so it scales with the clip. */
  margin: -7% auto 0;
  position: relative;            /* paints above the frame's dark strip */
  z-index: 2;
  appearance: none;
  padding: 0;
  border-radius: 50%;
  border: 0 !important;
  background: rgba(110, 110, 115, 0.72) !important;   /* beat the kit */
  color: #fff !important;
  box-shadow: none !important;
  cursor: pointer;
  transition: background-color 0.25s ease;
}
.ds-snd__pp:hover { background: rgba(140, 140, 145, 0.65) !important; }
.ds-snd__pp svg { width: 15px; height: 15px; }
.ds-snd__pp .ds-snd__pp-pause { display: none; }
.ds-snd__pp.is-playing .ds-snd__pp-play  { display: none; }
.ds-snd__pp.is-playing .ds-snd__pp-pause { display: block; }
.ds-snd__eyebrow {
  margin: 0;
  color: #ff6b00;
  font-size: var(--ds-step--1);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.ds-snd__title {
  margin: var(--ds-space-2xs) 0 0;
  font-size: var(--ds-title);   /* design system — every section H2 */
  font-weight: 500;
  line-height: 1.18;
  letter-spacing: -0.015em;
  color: #f5f5f7;
  text-wrap: balance;
}
.ds-snd__text {
  margin: var(--ds-space-m) auto 0;
  max-width: 58ch;
  color: var(--ds-muted);        /* design system — paragraph voice */
  font-size: var(--ds-step-0);
  line-height: 1.6;
  text-wrap: pretty;
}
/* Copy reveal — time-based, one block with a soft stagger. */
.ds-snd__reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.9s linear, transform 1s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.ds-snd.is-in .ds-snd__reveal { opacity: 1; transform: translateY(0); }
.ds-snd.is-in .ds-snd__title { transition-delay: 0.1s; }
.ds-snd.is-in .ds-snd__text { transition-delay: 0.2s; }
/* The stat beat — centered, same orange voice as the compare stats. */
.ds-snd__stat {
  /* svh-based: the whole stack must fit the SMALL viewport state. */
  margin-block-start: clamp(16px, 3svh, 28px);
  display: grid;
  gap: 4px;
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.9s linear, transform 1s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.ds-snd.is-stat .ds-snd__stat { opacity: 1; transform: translateY(0); }
.ds-snd__num {
  color: #ff6b00;
  font-size: var(--ds-step-4);
  font-weight: 500;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;   /* steady width while counting up */
}
.ds-snd__label {
  color: rgba(235, 235, 245, 0.6);
  font-size: var(--ds-step-0);
}
/* Reduced motion / static: no pin, everything visible, clip in place. */
.ds-snd--static { height: auto; }
.ds-snd--static .ds-snd__stage {
  position: relative;
  height: auto;
  display: block;
  padding-block: var(--ds-space-2xl);
}
.ds-snd--static .ds-snd__reveal,
.ds-snd--static .ds-snd__stat { opacity: 1; transform: none; }

/* MOBILE OVERRIDES — after every base rule (source order wins). */
@media (max-width: 767px) {
  .ds-snd {
    height: 200vh;   /* uniform mobile pin length */
    /* Black beat after the pattern section + air below the page's last
       section. */
    margin-block-start: 25vh;
    margin-block-end: var(--ds-space-xl);
  }
  /* (video width handled by the media column's min() — full width on
     phones; the mobile top clearance comes from the --ds-pin-pad token,
     and the frame's baked dark top puts the VISIBLE screen below it.) */
  /* The WHOLE stack must fit 100svh (the toolbar-expanded window) — the
     stage overflow hard-clips anything below it. Tightened rhythm: */
  .ds-snd__pp,
  .ds-snd__pp:hover,
  .ds-snd__pp:focus,
  .ds-snd__pp:active { margin-block-start: -9%; }
  .ds-snd__copy { margin-block-start: 12px; }
  .ds-snd__text { margin-block-start: 14px; line-height: 1.55; }
  .ds-snd__stat { margin-block-start: 12px; }
  .ds-snd__label { font-size: var(--ds-step--1); }
}

/* --------------------------------------------------------------------------
   5h. S8 — BLOOMING. Two identical square shots stacked; initBloom()
   scrubs the clean one (top) away to reveal the blooming demo. Copy
   below. Full design-system voice: --ds-pin-pad clearance, --ds-muted
   paragraph, time-based .is-in reveal, shared exit constants.
   -------------------------------------------------------------------------- */
.ds-blm {
  position: relative;
  height: 240vh;                 /* design system — uniform content-pin length */
  background: #000;
}
.ds-blm__stage {
  position: sticky;
  top: 0;
  height: 100vh;                 /* fallback */
  height: 100svh;                /* fits the toolbar-expanded window */
  overflow: hidden;
  display: flex;
  align-items: flex-start;
  background: #000;
  padding-block: var(--ds-pin-pad) clamp(1.5rem, 4svh, 3rem);
}
.ds-blm__inner { width: 100%; }
/* Square 1500x1500 shots — cap by svh so shot + eyebrow + title + copy
   all fit the pin. */
.ds-blm__media {
  position: relative;
  width: min(100%, 38svh);
  margin-inline: auto;
  will-change: opacity;
}
.ds-blm__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: clamp(14px, 1.8vw, 22px);
}
/* The clean shot rides ON TOP; JS scrubs its opacity 1 -> 0 (no-JS
   keeps it visible — the "before" state). */
.ds-blm__img--top {
  position: absolute;
  inset: 0;
  will-change: opacity;
}
.ds-blm__copy {
  text-align: center;
  margin-block-start: clamp(24px, 4svh, 44px);
}
/* Eyebrow + title — the same voice as the sound beat. */
.ds-blm__eyebrow {
  margin: 0;
  color: #ff6b00;
  font-size: var(--ds-step--1);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.ds-blm__title {
  margin: var(--ds-space-2xs) 0 0;
  font-size: var(--ds-title);   /* design system — every section H2 */
  font-weight: 500;
  line-height: 1.18;
  letter-spacing: -0.015em;
  color: #f5f5f7;
  text-wrap: balance;
}
.ds-blm__text {
  margin: var(--ds-space-s) auto 0;
  max-width: 58ch;
  color: var(--ds-muted);        /* design system — paragraph voice */
  font-size: var(--ds-step-0);
  line-height: 1.6;
  text-wrap: pretty;
}
/* Copy reveal — time-based, same rhythm as every sibling beat. */
.ds-blm__reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.9s linear, transform 1s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.ds-blm.is-in .ds-blm__reveal { opacity: 1; transform: translateY(0); }
.ds-blm.is-in .ds-blm__title { transition-delay: 0.1s; }
.ds-blm.is-in .ds-blm__text { transition-delay: 0.2s; }
/* Reduced motion / static: no pin, the demo's final state, copy shown. */
.ds-blm--static { height: auto; }
.ds-blm--static .ds-blm__stage {
  position: relative;
  height: auto;
  display: block;
  padding-block: var(--ds-space-2xl);
}
.ds-blm--static .ds-blm__img--top { opacity: 0; }
.ds-blm--static .ds-blm__reveal { opacity: 1; transform: none; }

/* MOBILE OVERRIDES — after every base rule (source order wins). */
@media (max-width: 767px) {
  .ds-blm {
    height: 200vh;   /* uniform mobile pin length */
    /* Black beat after the sound section + air below the page's last
       section. */
    margin-block-start: 25vh;
    margin-block-end: var(--ds-space-xl);
  }
  .ds-blm__media { width: min(100%, 36svh); }
}

/* --------------------------------------------------------------------------
   5i. S9 — OUTRO. The Storm Audio closing band ("Make it right" / "For
   dealers" / "Contact us"), reskinned BLACK for this page. Static — no
   pin, no JS. Quiet gray body text, hairline dividers, WhatsApp chip,
   dark-mode blue links.
   -------------------------------------------------------------------------- */
.ds-outro {
  background: #000;
  padding-block: var(--ds-space-xl) clamp(7rem, 15vh, 11rem);
}
/* Make it right | For dealers side by side (desktop); Contact us below. */
.ds-outro__cols { display: grid; gap: var(--ds-space-l); }
@media (min-width: 768px) {
  .ds-outro__cols { grid-template-columns: 1fr 1fr; gap: clamp(24px, 3vw, 48px); }
}
/* Hairline divider under each of the two blocks — a shade lighter than
   the black band (the dark twin of Storm's #e3e3e6). */
.ds-outro__cols .ds-outro__block {
  padding-bottom: var(--ds-space-l);
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}
.ds-outro__block--contact { margin-top: var(--ds-space-xl); }
/* Outro headings: a quieter size than the section H2s (matches Storm's
   st-wtitle--sm scale), same weight/voice. */
.ds-outro__title {
  margin: 0;
  color: #f5f5f7;
  font-size: var(--ds-step-2);
  font-weight: 500;
  line-height: 1.14;
  letter-spacing: -0.015em;
  text-wrap: pretty;
}
@media (max-width: 767px) {
  .ds-outro__title { font-size: 1.35rem; }
}
.ds-outro__text {
  margin: var(--ds-space-xs) 0 0;
  max-width: 58ch;
  color: #98989d;
  font-size: clamp(0.92rem, 0.86rem + 0.3vw, 1.1rem);  /* significantly smaller */
  line-height: 1.55;
  text-wrap: pretty;
}
/* Contact details — same quiet body style; phone/email are underlined
   dark-mode blue links. */
.ds-outro__contact {
  list-style: none;
  margin: var(--ds-space-xs) 0 0;
  padding: 0;
  color: #98989d;
  font-size: clamp(0.92rem, 0.86rem + 0.3vw, 1.1rem);
  line-height: 1.9;
}
/* Small round WhatsApp chip above the phone number — brand green, white
   glyph. #id + !important beat the theme/Elementor kit link paint. */
#dreamscreen-page .ds-outro__contact .ds-outro__wa-btn,
#dreamscreen-page .ds-outro__wa-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: #25d366;
  color: #fff !important;
  margin-bottom: 4px;
  text-decoration: none !important;
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), background 0.2s ease;
}
#dreamscreen-page .ds-outro__contact .ds-outro__wa-btn:hover  { background: #1fb85a; transform: translateY(-2px); }
#dreamscreen-page .ds-outro__contact .ds-outro__wa-btn:active { transform: translateY(0); }
.ds-outro__wa-btn svg { width: 20px; height: 20px; }
/* Apple dark-mode blue — readable on black (Storm's #0066ff is too dark
   here). */
#dreamscreen-page .ds-outro__contact a {
  color: #0a84ff !important;
  text-decoration: underline !important;
  text-underline-offset: 0.15em;
}
#dreamscreen-page .ds-outro__contact a:hover { color: #409cff !important; }

/* --------------------------------------------------------------------------
   5x. FURTHER SECTIONS — added here, one at a time, as each is designed.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   6. HEADER LIGHT SKIN — the proven recipe (see memory:
   feedback_header_light_swap; NEVER server-render header template 5861 — it
   fatals). initHeaderSwap() in js/dreamscreen-scroll.js toggles
   body.ds-header-light while a [data-ds-header="light"] section sits under
   the header, tags the glass pill with .ds-hdr-pill, flips svg ink inline,
   swaps the logo, and sets the hamburger plugin's data-theme.
   -------------------------------------------------------------------------- */
[data-elementor-type="header"] a { transition: color 0.35s ease; }
body.ds-header-light [data-elementor-type="header"] a,
body.ds-header-light [data-elementor-type="header"] .elementor-item,
body.ds-header-light [data-elementor-type="header"] .elementor-nav-menu a {
  color: rgba(49, 49, 49, 0.97) !important;
}
body.ds-header-light [data-elementor-type="header"] .dub-dropdown {
  background: rgba(255, 255, 255, 0.92) !important;
  color: #1d1d1f !important;
}
/* Non-link labels (the "EN" language switcher is a span) + widget toggles. */
body.ds-header-light [data-elementor-type="header"] .dub-lang-current,
body.ds-header-light [data-elementor-type="header"] .dub-lang-toggle,
body.ds-header-light [data-elementor-type="header"] .dub-user-toggle,
body.ds-header-light [data-elementor-type="header"] .dub-cart-toggle {
  color: rgba(49, 49, 49, 0.97) !important;
}
body.ds-header-light [data-elementor-type="header"] .dub-input {
  background: rgba(0, 0, 0, 0.04) !important;
  color: #1d1d1f !important;
}
/* The glass pill (tagged .ds-hdr-pill by JS). Elementor's scrolled state uses
   !important — the doubled class + !important here wins. */
[data-elementor-type="header"] .ds-hdr-pill { transition: background-color 0.35s ease, border-color 0.35s ease; }
body.ds-header-light [data-elementor-type="header"] .ds-hdr-pill.ds-hdr-pill {
  background-color: rgba(255, 255, 255, 0.47) !important;
  border: 1px solid rgba(0, 0, 0, 0.11) !important;
}
/* Icon svgs that carry stroke/fill ATTRIBUTES; computed-white ones are flipped
   inline by the JS. */
body.ds-header-light [data-elementor-type="header"] svg [stroke],
body.ds-header-light [data-elementor-type="header"] svg[stroke] {
  stroke: rgb(26, 26, 26) !important;
}
body.ds-header-light [data-elementor-type="header"] svg [fill="white"],
body.ds-header-light [data-elementor-type="header"] svg [fill="#fff"],
body.ds-header-light [data-elementor-type="header"] svg [fill="#ffffff"] {
  fill: rgb(26, 26, 26) !important;
}
/* Mobile cart (FunnelKit shortcode) — white icon -> black ink; the count badge
   keeps its own red/white (scoped to the svg only). */
body.ds-header-light [data-elementor-type="header"] .fkcart-shortcode-container svg,
body.ds-header-light [data-elementor-type="header"] .fkcart-shortcode-icon-wrap svg {
  color: rgb(0, 0, 0) !important;
  fill: rgb(0, 0, 0) !important;
}
/* Cart DRAWER — FunnelKit styles via `#fkcart-modal ... !important`, so these
   must use the ID too. */
body.ds-header-light #fkcart-modal {
  --fkcart-primary-text-color: rgb(26, 26, 26);
}
body.ds-header-light #fkcart-modal .fkcart-preview-ui {
  background: rgba(250, 248, 255, 0.85) !important;
}
body.ds-header-light #fkcart-modal .fkcart-title,
body.ds-header-light #fkcart-modal .fkcart-zero-state-title {
  color: rgb(26, 26, 26) !important;
}
body.ds-header-light #fkcart-modal .fkcart-zero-state-text {
  color: rgb(99, 99, 102) !important;
}
body.ds-header-light #fkcart-modal .fkcart-modal-close,
body.ds-header-light #fkcart-modal .fkcart-modal-close svg,
body.ds-header-light #fkcart-modal .fkcart-modal-close svg * {
  color: rgb(26, 26, 26) !important;
  fill: rgb(26, 26, 26) !important;
}
