/* ==========================================================================
   Perlisten — brand page styles (scaffolding)
   --------------------------------------------------------------------------
   Scoped under `#perlisten-page` / `.perlisten` to keep brand styling out
   of the rest of the site. Sections, hero, and scene-specific rules will
   be added as each section is designed. Only the foundational layer
   lives here for now:
     - box-sizing reset
     - body background scope (placeholder — set the real value once the
       design direction is decided)
     - skip-link accessibility
     - reduced-motion baseline
   ========================================================================== */

/* --- Reset & base -------------------------------------------------------- */
#perlisten-page,
#perlisten-page *,
#perlisten-page *::before,
#perlisten-page *::after {
  box-sizing: border-box;
}

#perlisten-page {
  position: relative;
  width: 100%;
  margin: 0;
  padding: 0;
  /* Clip the horizontal axis only (kills sideways overflow from the scroll
     scenes) while leaving the block axis visible. A blanket `overflow: clip`
     here would silently disable the slider nav's `position: sticky`, since a
     clip/hidden/auto ancestor establishes a clip context for sticky. */
  overflow-x: clip;
  overflow-y: visible;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Defensive: many WP/Elementor themes set `overflow-x: hidden` on <body> to
   stop sideways scroll — but `hidden` makes <body> a scroll container, which
   silently disables the slider nav's position: sticky. Re-assert `clip`
   (clips the same, but is NOT a scroll container) on this brand page only. */
body.sonic-brand-perlisten {
  overflow-x: clip !important;
  /* The page's own backdrop — explicit per brand (the global body-black
     was breaking the Gutenberg editor and is being phased out). */
  background-color: #19191f !important;
}

/* NO focus rings on this page's interactive elements (client requirement;
   Safari repaints them on programmatic refocus even with :focus-visible).
   The skip link keeps its own visible focus below. */
#perlisten-page a:focus,
#perlisten-page button:focus,
#perlisten-page [tabindex]:focus,
#perlisten-page a:focus-visible,
#perlisten-page button:focus-visible {
  outline: none !important;
}
#perlisten-page a,
#perlisten-page button {
  -webkit-tap-highlight-color: transparent;
}
#perlisten-page .perlisten-skip-link:focus,
#perlisten-page .perlisten-skip-link:focus-visible {
  outline: 2px solid #fff !important;
}

/* --- Body background scope ---------------------------------------------
   The global child-theme Custom CSS paints body black. If Perlisten's
   design calls for a different background, override here so the change
   only applies on this brand page. Left commented until the direction
   is decided.

body.sonic-brand-perlisten {
  background-color: #fff !important;
}
   ---------------------------------------------------------------------- */

/* (The old hero scroll-lock — html.prl-scroll-locked — is GONE. Locking
   the page and swallowing wheel/touch for the length of the clip read as
   a broken page. Scroll is always native now; initHero() reveals the
   lockup near the clip's end or on the first scroll intent.) */

/* --- Skip link ----------------------------------------------------------- */
.perlisten-skip-link {
  position: absolute;
  top: -60px;
  inset-inline-start: 12px;
  z-index: 9999;
  padding: 10px 18px;
  background: #fff;
  color: #000;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  border-radius: 4px;
  transition: top 0.2s ease;
}
.perlisten-skip-link:focus,
.perlisten-skip-link:focus-visible {
  top: 12px;
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* ==========================================================================
   HERO — fullscreen MP4 with deferred overlay reveal
   --------------------------------------------------------------------------
   Layout model:
     - `.prl-hero` is a 100lvh container (lvh = largest viewport height,
       stable under iOS Safari URL-bar toggles — see the scroll-scrub
       performance memory for why).
     - `<video>` fills the container absolutely, behind everything else.
     - `.prl-hero__overlay` is a full-bleed flex container that tints
       the video 70% black ONLY after `.is-visible` is set. The children
       (logo, H1, subtitle, CTA) each fade up individually via GSAP in
       `initHero()` so the reveal reads as Apple-style — staggered,
       soft, and restrained.
     - The CSS alone is enough for the reduced-motion path — the
       block at the bottom of this file paints the final state with
       no animation.
   ========================================================================== */
.prl-hero {
  position: relative;
  width: 100%;
  height: 100vh;
  /* svh (small viewport) — NOT dvh: dvh resizes DURING scroll when the
     mobile URL bar collapses, so the bottom-anchored lockup visibly
     shifted mid-scroll. svh equals the bar-visible viewport (the state
     at the top of the page, where this hero lives), so the CTA clears
     the URL bar AND the section never resizes under the user. */
  height: 100svh;
  background: #17161a;  /* matches the hero clip's flat backdrop so the
                           letterboxed (object-fit: contain) video reads as
                           seamless full-bleed */
  overflow: hidden;
  isolation: isolate;  /* keep the overlay tint and content in one
                          stacking context; video stays behind */
}

.prl-hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* `contain` (not `cover`) so the whole clip is visible and nothing gets
     cropped at the edges. The clip's own backdrop is a flat #17161a, so we
     paint the letterbox area the same colour — the bars are invisible and
     the video reads as full-bleed on both portrait (mobile) and landscape
     (desktop) renditions. */
  object-fit: contain;
  object-position: center center;
  display: block;
  pointer-events: none;
  background: #17161a;
}

/* DESKTOP ONLY — fill the whole screen (the landscape rendition was letterboxed
   with `contain`, leaving side bars). `cover` crops minimally to full-bleed.
   Mobile keeps `contain` so the portrait clip is never cropped. */
@media (min-width: 768px) {
  .prl-hero__video { object-fit: cover; }
}

.prl-hero__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  /* Content sits at the BOTTOM of the hero (not centred), with breathing
     room below it. The children still fade in via GSAP. */
  align-items: flex-end;
  justify-content: center;
  /* The "Or scroll down" hint adds ~30px to the block, which pushed the
     title up onto the video — the -18px hands that height back down. */
  padding: 0 6vw calc(clamp(1.25rem, 4vh, 3rem) - 18px);
  pointer-events: none;
  z-index: 1;
}
/* No darkening tint over the video — the clip plays and ends clean. The
   overlay only needs to capture pointer events once revealed so the CTA is
   clickable. */
.prl-hero__overlay.is-visible {
  pointer-events: auto;
}

.prl-hero__content {
  position: relative;
  display: grid;
  justify-items: center;
  max-width: 720px;
  width: 100%;
}
/* Logo and lockup share ONE grid cell so they overlap; the JS reveal
   cross-fades between them. */
.prl-hero__logo,
.prl-hero__lockup {
  grid-area: 1 / 1;
}
.prl-hero__lockup {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* Logo — prominent against the H1 below. Clamp covers desktop
   naturally; mobile has its own override (see the `max-width: 767px`
   block below) because the clamp floor was reading too small on
   phones when the logo is a wordmark. */
.prl-hero__logo {
  display: block;
  width: clamp(240px, 22vw, 350px);   /* 2x — was clamp(120px, 11vw, 175px) */
  height: auto;
  margin: 0;
  align-self: center;  /* sits at the vertical centre of the lockup area
                          (the title+paragraph+CTA block that replaces it) */
  opacity: 0;
  will-change: opacity, transform;
}

.prl-hero__title {
  margin: 0;
  font-size: clamp(1.6rem, 5.5vw, 3.1rem);
  font-weight: 400;
  /* 1.15 gives two-line titles room to breathe without looking
     pillowy. Previous 1.08 was tight enough that descenders nearly
     kissed the ascenders of the line below. */
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: #fff;
  opacity: 0;
  text-wrap: balance;
  will-change: opacity, transform;
}
/* DESKTOP: a touch smaller — the "Or scroll down" hint sat pressed
   against the hero's bottom edge; the shorter title hands the cluster
   the missing breathing room. */
@media (min-width: 1024px) {
  .prl-hero__title { font-size: clamp(1.6rem, 4.6vw, 2.7rem); }
}

/* Weight play: the lead "Perceptual Listening" stays regular while the
   "like never before" punch is bumped to 600. The gradient flows across
   both. */
.prl-hero__title strong {
  font-weight: 600;
  /* No own background — inherits the H1's grey/silver gradient
     (.prl-gradient-gray), just at a heavier weight. */
}

/* Eyebrow lead — "Perceptual listening." sits above the main statement
   at ~70% of the H1's size and weight 400. Reads as a quiet setup line
   to the larger second-line punch ("Like you've never heard before.").
   This is the Apple-style "small eyebrow → big headline" hierarchy —
   the same pattern Apple uses on product pages.

   `display: inline-block` is essential here. Without it, the span's
   font-size shrinks but the line-box's leading is still computed
   against the H1's larger font-size, so a noticeable gap opens
   between this line and the second line. inline-block resets the
   line-box per span so the leading collapses to this line's own
   font-size. */
.prl-hero__title-light {
  display: inline-block;
  font-size: 0.7em;
  font-weight: 400;
}

/* --- Gradient text utility ----------------------------------------------
   Same Apple-style gray-white sweep used on Valerion. Lives as its own
   utility class so future section titles on this page can opt in
   without redeclaring the gradient stops. Applied to the hero H1 in
   the template; both child spans inherit transparent fill, so the
   gradient flows continuously across "Perceptual Listening." and
   "Redefined." without breaking at the span boundary.

   Direction: 90deg in LTR, -90deg in RTL. The brightest stops always
   lead the reading eye — same logic as Valerion's gradient classes.
   ---------------------------------------------------------------------- */
.prl-gradient-gray {
  background-image: 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"] .prl-gradient-gray {
  background-image: linear-gradient(-90deg, #fdfdfd, #e6e6e6, #fff, #cfcfcf, #9e9e9e);
}

.prl-hero__subtitle {
  margin: 0.75em 0 0;
  font-size: clamp(1rem, 1.6vw, 1.2rem);
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: 0.005em;
  color: rgba(255, 255, 255, 0.88);
  opacity: 0;
  max-width: 56ch;
  text-wrap: pretty;
  will-change: opacity, transform;
}

.prl-hero__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* The content block is bottom-anchored, so growing this top gap lifts the
     title + paragraph ~13px while the CTA itself stays put at the bottom. */
  margin-top: calc(0.85em + 13px);
  padding: 0.95em 2.4em;
  border-radius: 999px;
  background: #0065ff;
  color: #fff !important;
  font-size: clamp(0.95rem, 1.3vw, 1.05rem);
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
  white-space: nowrap;
  min-height: 44px;  /* iOS tap-target floor */
  opacity: 0;
  will-change: opacity, transform, background;
  transition:
    background 0.25s ease,
    transform  0.25s cubic-bezier(0.22, 1, 0.36, 1);
}
.prl-hero__cta:hover {
  background: #0052d6;
}
.prl-hero__cta:active {
  transform: scale(0.97);
}
/* Quiet "Or scroll down" hint under the CTA pill — same reveal ride. */
.prl-hero__scrollhint {
  margin: 12px 0 0;
  color: rgba(255, 255, 255, 0.55);
  font-size: 0.82rem;
  letter-spacing: 0.02em;
  opacity: 0;
  will-change: opacity;
}

.prl-hero__noscript {
  position: absolute;
  inset-inline-start: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  padding: 1rem 1.5rem;
  background: rgba(0, 0, 0, 0.72);
  color: #fff;
  font-size: 0.95rem;
  text-align: center;
  border-radius: 6px;
  z-index: 2;
}
html[dir="rtl"] .prl-hero__noscript {
  transform: translate(50%, -50%);
}

/* --- Tablet tweaks (explicit per iron rules) ----------------------------- */
@media (min-width: 768px) and (max-width: 1023px) {
  .prl-hero__logo {
    margin-bottom: 1.5em;
  }
  .prl-hero__cta {
    padding: 0.9em 2.2em;
  }
}

/* --- Mobile tweaks -------------------------------------------------------- */
@media (max-width: 767px) {
  .prl-hero__overlay {
    padding-inline: 8vw;
    /* Was +22px — the scroll hint added ~30px of block height; hand it
       back so the title clears the video like before. */
    padding-bottom: calc(clamp(1rem, 3.5vh, 2.25rem) - 8px);
  }
  /* 2x the logo on mobile too (was min(35vw, 150px)). */
  .prl-hero__logo {
    width: min(70vw, 300px);
  }
  .prl-hero__subtitle {
    font-size: 1rem;
  }
  .prl-hero__cta {
    padding: 0.9em 2em;
    font-size: 0.98rem;
  }
}

/* --- Reduced motion — baseline ------------------------------------------
   Any scroll-scrub or autoplay animation on this page MUST honour
   `prefers-reduced-motion: reduce`. For the hero: skip autoplay (JS
   handles that), paint the final state immediately with no transition
   or fade, and leave the CTA interactive.
   ---------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .prl-hero__overlay {
    transition: none;
    pointer-events: auto;
  }
  .prl-hero__title,
  .prl-hero__subtitle,
  .prl-hero__cta,
  .prl-hero__scrollhint {
    opacity: 1;
    transform: none;
    transition: none;
    animation: none;
  }
  /* The logo is a transient intro beat; the resting state is the lockup. */
  .prl-hero__logo {
    opacity: 0;
  }
}

/* --- Screen-reader-only utility ----------------------------------------
   Visually hides the element but keeps it in the accessibility tree.
   Used for landmark headings (e.g. the THX section's H2) where the
   visual design relies on imagery and copy rather than a literal
   "THX Dominus" headline rendered on the page.
   ---------------------------------------------------------------------- */
.prl-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   THX DOMINUS — pinned section with looping background video and
   three sequential cinematic overlays.
   --------------------------------------------------------------------------
   Layout model:
     - `.prl-thx` is the section. GSAP wraps it in a pin spacer that
       provides the scroll distance (+=500%); the section's own
       intrinsic height is just one viewport (whatever .prl-thx__sticky
       takes).
     - `.prl-thx__sticky` is what GSAP pins. Inside it everything is
       absolutely positioned: video at the bottom, tint above, the
       three scenes (logo, logo, paragraph) on top of the tint.
     - Each `.prl-thx__scene` is a fixed-bleed flex container that
       centers its child. JS animates opacity on the scene wrapper
       and scale on the inner element — so the layout work is in CSS
       and the cinematic timing is in JS, cleanly separated.

   Why 100lvh and not 100dvh:
     dvh tracks iOS Safari's URL-bar toggle dynamically. GSAP records
     a pixel snapshot at pin start; if dvh changes mid-pin (URL bar
     hides during scroll), the snapshot is stale and the video frame
     visibly snaps from one height to another. lvh is constant per
     device — pin snapshot stays truthful. LB Speakers hit this exact
     bug; see lb-speakers.css for the original write-up. The trade-off
     here is the same: a thin sliver of video may sit under the URL
     bar when it's visible. Acceptable because the action is centered.
   ========================================================================== */
.prl-thx {
  position: relative;
  background: #000;
  /* 1px separator from the hero above — a dark grey that draws a clean
     seam between the two sections without reading as a bright white line. */
  border-top: 1px solid #333;
}

.prl-thx__sticky {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100lvh;
  overflow: hidden;
  isolation: isolate;
  background: #000;
}

/* --- Enhanced (JS) scroll-scene: NATIVE CSS sticky, not a GSAP pin ---------
   The section is made tall (700lvh = the 100lvh sticky + 600lvh of travel) and
   the inner element uses position:sticky. ScrollTrigger then only READS the
   scroll progress (no pin / no position:fixed), so scrolling stays 100% native
   — iOS collapses the URL bar, and there's no fixed-position pin-release jump.
   Gated on .is-enhanced so the reduced-motion / no-JS fallback keeps its normal
   one-viewport layout (the @media reduced-motion block below still wins). */
.prl-thx.is-enhanced {
  height: 700vh;
  height: 700lvh;
}
.prl-thx.is-enhanced .prl-thx__sticky {
  position: sticky;
  top: 0;
}

.prl-thx__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  display: block;
  pointer-events: none;
  background: #000;
  z-index: 1;
}

/* Second overlay — a soft dark vignette over the footage for a cinematic,
   graded mood. Sits ABOVE the animated black tint and below the
   scene content; static (CSS only). Tune the gradient stops / alpha to
   taste. */
.prl-thx__overlay2 {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background: radial-gradient(ellipse at center, transparent 45%, rgba(0, 0, 0, 0.55) 100%);
}

/* Black tint — sits above the video, below the scenes. JS sweeps its
   opacity from 0 → 0.6 across the first 4% of the pin (calming the logo
   sequence), then deepens it again to 0.9 as the paragraphs begin, so the
   reading passage sits on an almost-black backdrop. The element's
   `background: #000` plus the JS-animated `opacity` give us a clean tint
   without ever touching `background-color` per tick. */
.prl-thx__tint {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  will-change: opacity;
}

.prl-thx__scene {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 8vw;
  pointer-events: none;
  opacity: 0;
  z-index: 3;
  will-change: opacity;
}

/* Logos start small, scale to peak (1.0), then keep growing while
   fading. JS owns the live transform; these are at-rest defaults
   (matter for the first paint before the JS pin attaches and for
   reduced-motion / no-JS paths). */
.prl-thx__logo {
  display: block;
  width: clamp(160px, 24vw, 320px);
  height: auto;
  transform: scale(0.6);
  will-change: transform;
}

/* The paragraph scene is the readable fallback, so unlike the decorative
   logo scenes (which stay hidden until JS animates them) it is visible by
   default. */
.prl-thx__scene--paragraph {
  opacity: 1;
}

/* THX paragraphs — two states.

   DEFAULT (no-JS / reduced-motion): the three paragraphs stack in normal
   flow, centred and fully visible, so the copy is always readable even if
   the scene animation never runs.

   ENHANCED (`.prl-thx.is-enhanced`, added by JS once the pinned scene is
   wired): the three paragraphs are collapsed into ONE grid cell so they
   occupy the exact same spot, and start hidden. JS then fades them in and
   out one at a time as the user scrolls, so only one is on screen at any
   moment — each takes its turn in the same place. Text is centred per the
   art direction for this section. */
.prl-thx__copy {
  max-width: 60ch;
  margin-inline: auto;
}

.prl-thx__paragraph {
  margin: 0;
  font-size: clamp(1rem, 1.5vw, 1.2rem);
  font-weight: 400;
  line-height: 1.7;
  color: #fff;
  text-align: center;
  text-wrap: pretty;
}

/* Emphasised spec phrases — wrapped in <strong> inside the copy. Heavier
   weight makes the key numbers (120dB SPL, distortion, 92 dB) pop out of
   the body text. */
.prl-thx__paragraph strong {
  font-weight: 600;
}
/* DESKTOP ONLY: the four reading beats (three paragraphs + the outro
   line with the Perlisten logo) sat too small on big screens. */
@media (min-width: 1024px) {
  .prl-thx__paragraph { font-size: clamp(1.2rem, 0.75rem + 0.85vw, 1.4rem); }
  .prl-thx__outro-text { font-size: clamp(1.25rem, 0.8rem + 0.9vw, 1.5rem); }
}

/* Vertical rhythm between paragraphs — only matters in the stacked
   fallback; the enhanced state overlaps them so the gap is moot. */
.prl-thx__paragraph + .prl-thx__paragraph {
  margin-block-start: 1.1em;
}

.prl-thx.is-enhanced .prl-thx__copy {
  display: grid;
  place-items: center;
  max-width: none;            /* the measure moves onto each paragraph */
}

/* The scroll "text clipping" fill — WORD BY WORD, in reading order across
   line wraps (LTR and RTL alike, since it follows the DOM word order).
   JS writes ONE var per paragraph per frame (--prl-w = the sweep position
   in words); each word span carries its static index (--i) and CSS
   computes its brightness: dim 0.25 white → solid, with a 2-word soft
   leading edge. No per-word JS writes. */
.prl-thx.is-enhanced .prl-thx__paragraph {
  grid-area: 1 / 1;           /* all three share one cell → same position */
  max-width: 60ch;
  opacity: 0;                 /* JS reveals one at a time */
  will-change: opacity;
  --prl-w: 0;
}
.prl-thx.is-enhanced .prl-word {
  color: rgba(255, 255, 255, calc(0.25 + 0.75 * clamp(0, (var(--prl-w, 0) - var(--i, 0)) / 2, 1)));
}

/* --- Outro (closing claim) ----------------------------------------------
   Perlisten logo INLINE with the certification line. Like the paragraph
   scene this is real content, so it is visible by default; the enhanced
   state hides it so JS can fade it in last and hold it to the end. */
.prl-thx__scene--outro {
  opacity: 1;
}
.prl-thx.is-enhanced .prl-thx__scene--outro {
  opacity: 0;                 /* JS reveals it as the closing beat */
  will-change: opacity, transform;
}

.prl-thx__outro {
  display: flex;
  flex-wrap: wrap;            /* logo drops above the text on narrow screens */
  align-items: center;
  justify-content: center;
  gap: 0.5em 0.7em;
  max-width: 60ch;
  margin: 0;
  color: #fff;
  text-align: center;
  text-wrap: pretty;
}
.prl-thx__outro-logo {
  display: block;
  /* Sized to sit on the text's line — scales with the copy. */
  height: clamp(1.5em, 2.4vw, 2em);
  width: auto;
}
.prl-thx__outro-text {
  font-size: clamp(1.05rem, 1.6vw, 1.35rem);
  font-weight: 400;
  line-height: 1.5;
}
/* Only "THX Dominus" carries the emphasis weight; the rest stays regular. */
.prl-thx__outro-text strong {
  font-weight: 600;
}

/* --- Mobile tweaks ------------------------------------------------------- */
@media (max-width: 767px) {
  .prl-thx__scene {
    padding: 0 6vw;
  }
  .prl-thx__logo {
    width: clamp(120px, 44vw, 210px);
  }
  .prl-thx__paragraph {
    font-size: clamp(0.95rem, 3.6vw, 1.1rem);
    line-height: 1.65;
  }
}

/* --- Reduced motion -----------------------------------------------------
   Skip the pin/scrub theatrics: render the section as a static block with
   all three paragraphs stacked and visible (the non-enhanced fallback),
   and hide the decorative logos. The backdrop video still attaches and
   plays, so the tint is pushed heavier here (0.85) to keep the static
   white copy readable over the moving footage.
   ---------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .prl-thx__sticky {
    height: auto;
    min-height: 60vh;
    padding: 8vh 6vw;
    display: flex;
    flex-direction: column;   /* paragraphs + outro stack vertically */
    align-items: center;
    justify-content: center;
    gap: 1.5em;
  }
  .prl-thx__tint {
    opacity: 0.85;
  }
  .prl-thx__scene--thx,
  .prl-thx__scene--dominus {
    display: none;
  }
  .prl-thx__scene--paragraph,
  .prl-thx__scene--outro {
    position: relative;
    inset: auto;
    opacity: 1;
    padding: 0;
  }
}

/* ==========================================================================
   SECTION 3 — slider section wrapper
   --------------------------------------------------------------------------
   Background is #18181b — the colour the THX section fades up to as it
   exits, so Section 2 → 3 reads as one continuous surface. The reusable
   .sonic-slider component (css/sonic-slider.css) sits centred inside, capped
   to a comfortable width on desktop.
   ========================================================================== */
.prl-slider-section {
  position: relative;
  width: 100%;
  background: #18181b;
  /* No horizontal padding — the slider runs edge to edge so the next-slide
     peek reaches the right screen edge (full-bleed, like Apple on mobile).
     NO `overflow: hidden` here — it would establish a clip context that kills
     the nav's position: sticky (the lead-in). The off-screen peek is already
     clipped by .sonic-slider__viewport (its own subtree, not an ancestor of
     the nav).
     TOP padding gives the heading + card air on entry. The BOTTOM padding is
     deliberately SMALL: the sticky lead-in's float room (the slider min-height
     below) already supplies the breathing space under the docked controller,
     so a full symmetric bottom clamp would double it (the "too much space"
     the client flagged). Shorten the lead-in via the slider min-height below. */
  padding: clamp(3rem, 14vh, 7rem) 0
           calc(1.5rem + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;      /* heading stacks ABOVE the slider */
  align-items: center;
}

/* Section heading — "Technology". Aligned to the START (left in English, right
   in Hebrew via logical props), in line with the carousel's first card: the
   slider viewport's inline-start inset is --ss-edge (16px), so the heading gets
   the same 16px so its text and the card's left edge share one line. */
.prl-slider-head {
  width: 100%;
  /* Align the heading's START edge to the SITE HEADER's centred column (~1024px,
     measured from the live header pill) instead of the screen edge. The padding
     is the header's own side gutter: (viewport − 1024)/2 on desktop, with a 16px
     floor so on mobile it collapses to the same 16px the cards use (no media
     query needed → mobile is untouched). */
  padding-inline: max(16px, calc((100% - 1024px) / 2));
  margin: 0 0 clamp(1.6rem, 5vh, 3rem);
  text-align: start;
}
.prl-slider-title {
  margin: 0;
  color: #fff;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.1;
  font-size: clamp(1.6rem, 5vw, 2.8rem);
}

/* THE STICKY LEAD-IN (restored). The slider is taller than its content so the
   nav has float room: as the section scrolls in, the component's
   `position: sticky; bottom: …` pulls the controller to the viewport bottom and
   it FLOATS there (birth animation playing) while the card scrolls, then DOCKS
   ~10px below the card and resumes normal scroll. The min-height IS the lead-in
   length AND the trailing room below the docked nav — lower it to shorten both,
   raise it for a longer float. Keep margin-top small so the nav docks right
   under the card (NOT margin-top:auto — that parked it far from the card). */
.prl-slider-section .sonic-slider {
  width: 100%;
  min-height: 88vh;            /* lead-in float room (was 105vh — trimmed to cut the trailing gap) */
  display: flex;
  flex-direction: column;
}
.prl-slider-section .sonic-slider__nav {
  margin-top: 10px;            /* docks just below the card; keeps the component's position:sticky */
}
@media (min-width: 768px) {
  .prl-slider-section .sonic-slider {
    max-width: none;           /* full-bleed (was capped at 1100 — the peek then
                                  reached the screen edge, not a mid-screen cut) */
    min-height: 92vh;          /* taller carousel on desktop */
  }
}

/* ==========================================================================
   STICKY BUY BUTTON — fixed bottom-centre pill (same pattern as Valerion /
   LB Speakers). Hidden by default; js/perlisten-scroll.js adds `.is-visible`
   during the THX pinned scene (in as the THX logo appears, out before the
   pin releases).
   ========================================================================== */
.prl-buy {
  position: fixed;
  bottom: 1.25rem;
  /* Plain `left: 50%` (NOT inset-inline-start): in RTL the logical prop flips
     to right while translateX(-50%) does not, drifting the pill off-centre.
     Valerion / LB use this same approach. */
  left: 50%;
  transform: translateX(-50%) translateY(30px);
  z-index: 900;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.7rem 2.2rem;
  background: #0065ff;
  color: #fff !important;
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
  border-radius: 50px;
  white-space: nowrap;
  cursor: pointer;
  opacity: 0;
  filter: blur(10px);
  pointer-events: none;
  will-change: opacity, filter, transform;
  transition: opacity 0.5s ease, filter 0.5s ease,
              transform 0.5s cubic-bezier(0.22, 1, 0.36, 1),
              background 0.25s ease;
}
.prl-buy.is-visible {
  opacity: 1;
  filter: blur(0);
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
.prl-buy:hover {
  background: #0052d6;
  transform: translateX(-50%) translateY(0) scale(1.05);
}
.prl-buy:active {
  transform: translateX(-50%) translateY(0) scale(0.97);
}
@media (prefers-reduced-motion: reduce) {
  .prl-buy { filter: none; transition: opacity 0.3s ease; }
  .prl-buy.is-visible { filter: none; }
}

/* ==========================================================================
   SECTION 4 — "Make it yours": pure-black shop section with Categories /
   Series tabs and a --shop sonic-slider variation per tab.
   ========================================================================== */
.prl-shop-section {
  position: relative;
  width: 100%;
  background: #000;                         /* absolute black — clean break */
  /* TOP padding for air; SMALL bottom padding — like the Technology section, the
     sticky lead-in's float room (slider min-height) supplies the trailing space.
     NO overflow:hidden — it would establish a clip context that kills the nav's
     position:sticky; the page-level overflow-x:clip already contains the
     horizontal card peek. */
  padding: clamp(3rem, 14vh, 7rem) 0 calc(1.5rem + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Tabs WRAPPER — spans the full content column with the SAME gutter as the
   heading/cards (the client wanted a WIDE bar, not a compact centred pill). */
.prl-shop-tabs-wrap {
  width: 100%;
  /* Same header-aligned column as the headings (the segmented bar then spans
     exactly the ~1024px header width, centred). 16px floor keeps mobile intact. */
  padding-inline: max(16px, calc((100% - 1024px) / 2));
  margin: 0 auto clamp(1.6rem, 5vh, 3rem);
}

/* Segmented control — a FULL-WIDTH dark bar; the two tabs stay centred at their
   natural width (justify-content:center). The dark surface + the goo "birth"
   live in their own layers (__goo / __glass) so the bar is BORN exactly like the
   carousel nav controller: a ball rises from below, splits, melds into the bar.
   `.prl-tabs-prebirth` hides it until JS sets the birth state (no FOUC); JS
   removes it on init (and the reduced-motion / no-GSAP paths reveal statically). */
.prl-shop-tabs {
  position: relative;
  display: flex;
  justify-content: center;                   /* tabs centred inside the wide bar */
  align-items: center;
  width: 100%;
  padding: 5px;
  border-radius: 999px;
  background: transparent;                    /* the dark surface is the __glass layer */
}
.prl-shop-tabs.prl-tabs-prebirth { visibility: hidden; }

/* DESKTOP ONLY — the bar shrinks to the tabs' natural width (centred), instead of
   spanning the full header column. Mobile keeps the full-width bar (perfect now). */
@media (min-width: 768px) {
  .prl-shop-tabs {
    width: fit-content;
    margin-inline: auto;
  }
}

/* Goo layer — dark metaball(s) that rise + split into the bar (#ss-goo melds them). */
.prl-shop-tabs__goo {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  filter: url(#ss-goo);
}
.prl-shop-tabs__goo-a,
.prl-shop-tabs__goo-b {
  position: absolute;
  top: 0;
  left: 0;                                     /* deterministic origin for the GSAP x transform */
  height: 100%;
  border-radius: 999px;
  background: #2c2c31;                        /* solid; the goo threshold makes it opaque */
}

/* Glass layer — the final dark bar surface; JS cross-fades it in over the goo. */
.prl-shop-tabs__glass {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: 999px;
  background: rgba(44, 44, 49, 0.92);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  opacity: 0;                                 /* GSAP fades this to 1 at the end of the birth */
  pointer-events: none;
}

.prl-shop-tabs__thumb {
  position: absolute;
  top: 5px;
  bottom: 5px;
  left: 0;
  width: 0;                                  /* JS sets left + width to the active tab */
  z-index: 1;                                /* above goo/glass, below the labels */
  background: #f4f5f7;
  border-radius: 999px;
  transition: left 0.4s cubic-bezier(0.22, 1, 0.36, 1),
              width 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}

.prl-shop-tab,
.prl-shop-tab:hover,
.prl-shop-tab:focus,
.prl-shop-tab:focus-visible,
.prl-shop-tab:active {
  position: relative;
  z-index: 2;                                /* above thumb + goo/glass */
  flex: 1 1 0;                               /* each tab fills 50% of the wide bar */
  text-align: center;
  appearance: none;
  border: 0 !important;
  background: transparent !important;        /* beat Elementor's pink buttons */
  box-shadow: none !important;
  outline: none !important;
  margin: 0;
  padding: 0.5rem clamp(1.1rem, 4vw, 1.8rem);
  border-radius: 999px;
  font-size: clamp(0.9rem, 2.4vw, 1.05rem);
  font-weight: 500;
  line-height: 1.1;
  color: rgba(235, 235, 245, 0.6) !important; /* inactive */
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.3s ease;
}
.prl-shop-tab.is-active { color: #262628 !important; }   /* active — dark on the white thumb */

/* Panel — one carousel per tab; the inactive one is [hidden] (display:none). */
.prl-shop-panel { width: 100%; }
.prl-shop-panel[hidden] { display: none !important; }
/* Gentle fade replayed on every tab switch (initShop() re-adds it). */
.prl-shop-panel.is-switch { animation: prl-panel-in 0.45s ease; }
@keyframes prl-panel-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Shop carousel: SAME sticky lead-in as the Technology slider (#4) — the nav
   floats in (birth animation) right after the tabs, then docks. The min-height
   is the lead-in length + trailing room; the component owns position:sticky. */
.prl-shop-section .sonic-slider {
  width: 100%;
  min-height: 88vh;
  display: flex;
  flex-direction: column;
}
.prl-shop-section .sonic-slider__nav { margin-top: 10px; }
@media (min-width: 768px) {
  .prl-shop-section .sonic-slider {
    max-width: none;           /* full-bleed — fixes the right-side cut-off on desktop */
    min-height: 92vh;          /* taller carousel on desktop */
  }
}

/* Reduced motion: show the tab bar + its surface statically (no goo birth). */
@media (prefers-reduced-motion: reduce) {
  .prl-shop-tabs__glass { opacity: 1; }
  .prl-shop-tabs__goo   { display: none; }
  .prl-shop-tabs__thumb { transition: none; }
}

/* ==========================================================================
   FINISH / CONSULT — full-width SQUARE ambient video, then the "do it right"
   copy + WhatsApp CTA. Matches the existing dark sections (white heading like
   .prl-slider-title, lighter body text, pill CTA).
   ========================================================================== */
.prl-finish {
  width: 100%;
  background: #18181b;            /* matches the Technology section */
}

/* Full-width, SQUARE (1:1) video — NOT full viewport height (client's spec). */
.prl-finish__video {
  width: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: #18181b;
}
.prl-finish__video video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.prl-finish__text {
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  padding: clamp(2.5rem, 8vh, 5rem) 20px clamp(1.5rem, 4vh, 2.5rem);
  text-align: start;             /* right in Hebrew, left in English */
}
.prl-finish__title {
  margin: 0 0 clamp(1.2rem, 4vh, 2rem);
  color: #fff;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.1;
  font-size: clamp(1.7rem, 5vw, 2.8rem);
}
.prl-finish__body p {
  margin: 0 0 1.1em;
  color: rgba(235, 235, 245, 0.78);
  font-size: clamp(1rem, 2.2vw, 1.12rem);
  line-height: 1.65;
  text-wrap: pretty;
}
.prl-finish__body p:last-child { margin-bottom: 0; }

/* Small sub-heading inside the body ("For dealers, installers…"). */
.prl-finish__mini {
  margin: clamp(1.6rem, 5vh, 2.4rem) 0 0.7em;
  color: #fff;
  font-weight: 600;
  font-size: clamp(1.05rem, 2.4vw, 1.25rem);
  line-height: 1.3;
}

/* CTA — STICKY: floats at the viewport bottom while the section scrolls, then
   docks at its final spot (the buy-now feel). Centred; the empty wrap passes
   clicks through, the pill re-enables them. */
.prl-finish__cta-wrap {
  position: sticky;
  bottom: clamp(16px, 3vh, 28px);
  z-index: 10;
  text-align: center;
  padding-bottom: clamp(1.5rem, 5vh, 3rem);
  pointer-events: none;
}

/* WhatsApp CTA — green pill with the glyph. Enters with a blur + rise fade
   (.is-visible, added by JS when the section scrolls in) — NO box-shadow. */
.prl-finish__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.9rem;
  background: #1daa21;
  color: #fff !important;
  font-size: 1rem;
  font-weight: 500;
  text-decoration: none;
  border-radius: 50px;
  white-space: nowrap;
  pointer-events: auto;
  opacity: 0;
  transform: translateY(24px);
  filter: blur(8px);
  transition: opacity 0.5s ease, filter 0.5s ease,
              transform 0.6s cubic-bezier(0.22, 1, 0.36, 1), background 0.2s ease;
}
.prl-finish.is-visible .prl-finish__cta {
  opacity: 1;
  transform: none;
  filter: blur(0);
}
.prl-finish__cta:hover  { background: #178c1b; transform: translateY(-2px); }
.prl-finish__cta:active { transform: translateY(0); }
.prl-finish__wa { width: 1.3em; height: 1.3em; flex: 0 0 auto; }

@media (prefers-reduced-motion: reduce) {
  .prl-finish__cta { opacity: 1; transform: none; filter: none; transition: none; }
  .prl-finish__cta:hover { transform: none; }
}
