/* ==========================================================================
   LB Speakers — brand page styles
   ========================================================================== */

/* Montserrat 800 — scoped to the "INVISIBLE" word only. Loaded via
   Google Fonts because it is not part of the global child-theme font
   stack (which only ships Spline Sans + Google Sans variable). */
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@800&display=swap');

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

#lb-speakers-page {
  position: relative;
  width: 100%;
  margin: 0;
  padding: 0;
  background: #fff;
  color: #1a1a1a;
  overflow: clip;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* --- Override theme body background so Safari status bar is white --------- */
body.sonic-brand-lb-speakers {
  background-color: #fff !important;
}

/* --- Elementor header — lower z-index on this page so pinned story
      content isn't obscured ------------------------------------------------ */
body.sonic-brand-lb-speakers .elementor .e-53db346-fd41007 {
  z-index: 10 !important;
}

/* --- Scroll lock (applied by JS while video plays + reveal runs) --------- */
html.lbs-hero-locked,
html.lbs-hero-locked body {
  overflow: hidden !important;
  overscroll-behavior: none;
  height: 100%;
}
html.lbs-hero-locked {
  scrollbar-gutter: stable;
}
html.lbs-hero-locked body {
  touch-action: none;
}

/* --- Skip link ----------------------------------------------------------- */
.lbs-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;
}
.lbs-skip-link:focus,
.lbs-skip-link:focus-visible {
  top: 12px;
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* ==========================================================================
   HERO — 100svh video, title reveals after video ends
   ========================================================================== */
.lbs-hero {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100svh;
  overflow: visible;
  background: #fff;
}

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

/* --- Title wrap — centred overlay ---------------------------------------- */
.lbs-hero__title-wrap {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-inline: 6vw;
  padding-block-start: 3vh;
  z-index: 3;
  pointer-events: none;
}

.lbs-hero__title {
  margin: 0;
  text-align: center;
  line-height: 1;
}

/* --- LB logo — small, above INVISIBLE ------------------------------------ */
.lbs-hero__logo {
  display: block;
  width: clamp(32px, 6.5vw, 52px);
  height: auto;
  margin: 0 auto 0.6em;
  opacity: 0;
  /* Force own compositor layer so the adjacent ripple's huge
     scale(0.5 → 14) animation doesn't re-rasterise the logo and
     cause a pixel-snap shake during the first animation cycles. */
  transform: translateZ(0);
  backface-visibility: hidden;
  will-change: opacity, transform;
}

/* --- "INVISIBLE" — gradient text, starts hidden for JS reveal ------------ */
/* The #lbsHero selector prefix raises specificity above the site-wide
   `html[lang^="en"] body *:not(...)` font-family rule that uses
   !important — without it, spline-sans-varz would win. */
#lbsHero .lbs-hero__title-main,
.lbs-hero__title-main {
  display: block;
  font-family: 'Montserrat', 'Helvetica Neue', Arial, sans-serif !important;
  font-weight: 800 !important;
  font-size: clamp(2.4rem, 7.2vw, 6rem);
  line-height: 0.95;
  letter-spacing: 0.06em;
  background-image: linear-gradient(135deg, #000000, #606060);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
  opacity: 0;
  transform: scale(0.85);
  filter: blur(20px);
  will-change: opacity, transform, filter;
}

/* Hebrew: revert to the site font stack (Google Sans / Spline Sans).
   Montserrat 800 is a Latin-only cut and doesn't cover Hebrew glyphs. */
html[lang^="he"] #lbsHero .lbs-hero__title-main,
html[lang^="he"] .lbs-hero__title-main {
  font-family: inherit !important;
  font-size: clamp(1.9rem, 5.8vw, 4.8rem);
}

/* --- "Until you start playing" ------------------------------------------- */
.lbs-hero__title-sub {
  display: block;
  margin-block-start: 0.5em;
  font-size: clamp(0.9rem, 1.7vw, 1.25rem);
  font-weight: 400;
  color: #636363;
  letter-spacing: 0.01em;
  line-height: 1.3;
  opacity: 0;
  will-change: opacity;
}

/* --- "Scroll down" CTA -------------------------------------------------- */
.lbs-hero__scroll-btn {
  display: inline-block;
  margin-block-start: 1.6em;
  padding: 14px 48px;
  border: none;
  border-radius: 60px;
  background: #0065ff;
  color: #fff !important;
  font-size: clamp(0.85rem, 1.4vw, 1rem);
  font-weight: 500;
  letter-spacing: normal;
  text-decoration: none;
  cursor: pointer;
  pointer-events: auto;
  opacity: 0;
  will-change: opacity;
  transition: background 0.2s ease, transform 0.2s ease;
}
.lbs-hero__scroll-btn:hover {
  background: #0052d6;
}
.lbs-hero__scroll-btn:active {
  transform: scale(0.96);
}

/* --- Ripple rings — positioned behind the title in the hero -------------- */
.lbs-hero__ripples {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  overflow: visible;
  will-change: opacity;
}

.lbs-hero__ripple {
  position: absolute;
  width: 60px;
  height: 60px;
  border: 0.5px solid rgba(0, 0, 0, 0.15);
  border-radius: 50%;
  opacity: 0;
  transform: scale(0);
  will-change: transform, opacity;
}

.lbs-ripples--active .lbs-hero__ripple {
  animation: lbs-ripple 3.5s ease-out infinite;
}

.lbs-ripples--active .lbs-hero__ripple:nth-child(2) {
  animation-delay: 0.9s;
}
.lbs-ripples--active .lbs-hero__ripple:nth-child(3) {
  animation-delay: 1.8s;
}

@keyframes lbs-ripple {
  0% {
    transform: scale(0.5);
    opacity: 0.5;
  }
  100% {
    transform: scale(14);
    opacity: 0;
  }
}

/* --- Noscript fallback --------------------------------------------------- */
.lbs-hero__noscript {
  position: absolute;
  inset-inline-start: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
  padding: 16px 24px;
  background: rgba(0, 0, 0, 0.72);
  color: #fff;
  font-size: 15px;
  text-align: center;
  border-radius: 4px;
  z-index: 4;
}
html[dir="rtl"] .lbs-hero__noscript {
  transform: translate(50%, -50%);
}

/* --- Mobile tweaks ------------------------------------------------------- */
@media (max-width: 767px) {
  .lbs-hero__ripple {
    width: 50px;
    height: 50px;
  }
}

/* ==========================================================================
   STORY — overlay inside hero, char-fill text reveal
   ========================================================================== */
.lbs-story__overlay {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 8vw;
  background: #fff;
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
}

.lbs-story__inner {
  max-width: 680px;
  text-align: center;
}

.lbs-story__text {
  font-size: clamp(0.95rem, 1.6vw, 1.15rem);
  font-weight: 400;
  line-height: 1.85;
  margin: 0 0 1.2em;
  white-space: normal;
}

.lbs-story__text:last-child {
  margin-block-end: 0;
}

.lbs-story__text .char {
  color: rgba(0, 0, 0, 0.1);
  transition: none;
}

.lbs-story__text--accent {
  font-weight: 500;
}
.lbs-story__text--accent .char {
  color: rgba(0, 0, 0, 0.1);
}

/* --- Mobile tweaks for story --------------------------------------------- */
@media (max-width: 767px) {
  .lbs-story__inner {
    max-width: 100%;
  }
  .lbs-story__text {
    font-size: clamp(0.85rem, 3.8vw, 1rem);
    line-height: 1.75;
  }
}

/* --- Spacer -------------------------------------------------------------- */
.lbs-spacer {
  height: 20vh;
  background: #fff;
}

/* Trailing spacer after the last ceiling section. Small gap so the
   final label has a little breathing room before the "More by" row
   begins, but without a huge blank white gap. */
.lbs-spacer--tail {
  height: 15vh;
}

/* ==========================================================================
   IN-CEILING — scroll-scrub video, fullscreen → card
   --------------------------------------------------------------------------
   Layout model:
     - Pin the `.lbs-ceiling__sticky` element. It is a column flex
       container whose natural height grows to fit its real content:
       top-padding (clears the Elementor header + its overflowing logo),
       a card-frame placeholder, and the full title + paragraph.
     - `.lbs-ceiling__card-frame` is a transparent block that reserves
       the final card rect. JS measures its boundingClientRect and
       animates the absolutely-positioned video-wrap to match. This is
       the single source of truth for the card's final position.
     - `.lbs-ceiling__label` flows naturally below the card-frame, so
       its height is whatever the real text takes. No magic `labelH`
       estimate to fall short and clip long paragraphs.
     - If the natural height exceeds 100vh (long paragraph), only the
       first 100vh is visible during the pin. When the pin releases,
       the page scrolls normally and the rest of the paragraph reveals.
   ========================================================================== */
.lbs-ceiling {
  position: relative;
  background: #fff;
}

.lbs-ceiling__sticky {
  position: relative;
  width: 100%;
  min-height: 100vh;
  min-height: 100lvh;  /* lvh = LARGEST viewport height, constant per
                          device regardless of iOS Safari URL-bar state.
                          We tried `dvh` first — it tracks the bar
                          dynamically, but GSAP records a pixel
                          snapshot at animation start and the bar-
                          animation transient produced a visible snap
                          from small → large mid-scrub. `lvh` is
                          invariant during the pin, so GSAP's snapshot
                          stays truthful end-to-end. The trade-off:
                          when the URL bar is visible, the bottom
                          sliver of the fullscreen frame sits behind
                          it — acceptable because the frame subject
                          is centered and the bottom is mostly
                          product context. */
  padding: 200px 6vw 56px;
  background: #fff;
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow: hidden;
  box-sizing: border-box;
  /* Keep the absolute video-wrap in its own stacking context so it
     never renders above the Elementor site header (z-index 10 on
     this page). */
  isolation: isolate;
}

/* Transparent placeholder — holds the exact rect the video-wrap
   animates to at the end of the shrink. Its width/height are the
   card's final dimensions. The JS measures this element, so to
   change the card size just change these values. */
.lbs-ceiling__card-frame {
  width: 340px;
  height: 340px;
  flex-shrink: 0;
  margin-bottom: 40px;
}

.lbs-ceiling__label {
  width: 100%;
  max-width: 680px;
  text-align: center;
  opacity: 0;
  will-change: opacity;
}

.lbs-ceiling__video-wrap {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  height: 100lvh;  /* Matches sticky — see note above. Must stay in
                      sync with sticky's min-height unit. */
  border-radius: 0;
  overflow: hidden;
  pointer-events: none;
  will-change: top, left, width, height, border-radius;
  z-index: 1;
}

.lbs-ceiling__canvas {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  display: block;
  background: transparent;
}

.lbs-ceiling__title {
  margin: 0;
  font-size: clamp(1.4rem, 2.2vw, 1.8rem);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: #1a1a1a;
}

/* Typography matches .lbs-more__card-desc ("Installation Series"). */
.lbs-ceiling__desc {
  margin: 0.9em auto 0;
  font-size: clamp(0.9rem, 1.1vw, 0.95rem);
  font-weight: 400;
  line-height: 1.6;
  color: #707070;
  max-width: 620px;
}

/* --- Mobile tweaks for ceiling ------------------------------------------- */
@media (max-width: 767px) {
  .lbs-spacer {
    height: 12vh;
  }
  .lbs-spacer--tail {
    height: 10vh;
  }
  .lbs-ceiling__sticky {
    /* 240px top padding clears the Elementor header pill + its circular
       logo bubble (the bubble extends ~260px below viewport top on most
       phones; measuring headerEl.boundingClientRect() only catches the
       pill, which is why the earlier pixel-gap logic failed). */
    padding-top: 240px;
    padding-bottom: 40px;
  }
  .lbs-ceiling__card-frame {
    width: 58vw;
    height: 58vw;
    margin-bottom: 28px;
  }
  .lbs-ceiling__title {
    font-size: 1.25rem;
  }
  .lbs-ceiling__desc {
    max-width: 100%;
    font-size: 0.9rem;
    line-height: 1.6;
  }
}

/* ==========================================================================
   STICKY BUY BUTTON — fixed bottom-centre pill. Hidden by default; JS
   adds `.is-visible` when the first ceiling section enters the viewport.
   ========================================================================== */
.lbs-buy {
  position: fixed;
  bottom: 1.25rem;
  /* Use plain `left: 50%` (not inset-inline-start) — in RTL the
     logical property flips to `right: 50%` while transform:
     translateX(-50%) does NOT flip, so the button drifts off-centre
     to the left in Hebrew. Valerion uses the 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;
}

.lbs-buy.is-visible {
  opacity: 1;
  filter: blur(0);
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}

.lbs-buy:hover {
  background: #0052d6;
  transform: translateX(-50%) translateY(0) scale(1.05);
}

.lbs-buy:active {
  transform: translateX(-50%) translateY(0) scale(0.97);
}

@media (max-width: 767px) {
  .lbs-buy {
    font-size: 0.9rem;
    padding: 0.65rem 1.8rem;
  }
}

html[dir="rtl"] .lbs-buy {
  letter-spacing: 0;
}

/* ==========================================================================
   MORE BY LB SPEAKERS — 3-card showcase
   Desktop: CSS grid, 3 cards side by side (no dots).
   Mobile:  stacked-grid carousel. All 3 cards live in the same grid
            cell; JS assigns .is-active / .is-prev / .is-next and the
            CSS transforms animate between positions with an Apple-style
            cubic-bezier easing. Loops infinitely via modulo in JS.
   ========================================================================== */
.lbs-more {
  padding: 4rem 6vw 5rem;
  background: #fff;
}

.lbs-more__inner {
  max-width: 1200px;
  margin: 0 auto;
}

.lbs-more__title {
  font-size: clamp(1.6rem, 2.6vw, 2.2rem);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-align: center;
  color: #1a1a1a;
  margin: 0 0 2.5rem;
}

.lbs-more__carousel {
  position: relative;
}

.lbs-more__track {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
  list-style: none;
  padding: 0;
  margin: 0;
}

.lbs-more__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  margin: 0;
}

.lbs-more__img {
  width: 100%;
  max-width: 260px;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 20px;
  display: block;
  margin: 0 auto 1.2rem;
  background: #f3f3f3;
}

.lbs-more__card-title {
  margin: 0 0 0.5rem;
  font-size: clamp(1.05rem, 1.4vw, 1.2rem);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: #1a1a1a;
}

.lbs-more__card-desc {
  margin: 0;
  font-size: clamp(0.9rem, 1.1vw, 0.95rem);
  font-weight: 400;
  line-height: 1.6;
  color: #707070;
  max-width: 52ch;
}

/* Dots hidden on desktop (grid mode). */
.lbs-more__dots {
  display: none;
}

/* --- Mobile carousel --------------------------------------------------- */
@media (max-width: 767px) {
  .lbs-more {
    padding: 2.5rem 0 3rem;
  }

  .lbs-more__title {
    padding: 0 6vw;
    margin-bottom: 1.8rem;
  }

  /* The carousel is full-bleed so the off-screen neighbour cards are
     clipped at the viewport edge. overflow-hidden is what makes the
     horizontal translation look clean instead of spilling. */
  .lbs-more__carousel {
    overflow: hidden;
  }

  /* All 3 cards stack into a single 1x1 grid cell — they overlap at
     the CSS layout level, and JS transforms move each one into its
     active/prev/next visual position. Grid height = tallest card. */
  .lbs-more__track {
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
    gap: 0;
    padding: 0;
  }

  /* Apple-style directional slide: active card sits centered, sharp,
     full-opacity. Prev card is parked off to the inline-start with a
     scale-down + blur + fade-out; next card mirrors on the inline-end.
     On advance/retreat, the incoming card glides in from its parked
     position while the outgoing card glides out — no visible teleport,
     a clear sense of direction, and the "glass/depth" feel from the
     scale + blur combination. */
  .lbs-more__card {
    grid-column: 1;
    grid-row: 1;
    width: 82vw;
    justify-self: center;
    padding: 0 0.25rem;
    opacity: 0;
    transform: translate3d(24%, 0, 0) scale(0.92);
    filter: blur(10px);
    pointer-events: none;
    transition:
      transform 0.8s cubic-bezier(0.22, 1, 0.36, 1),
      opacity   0.55s cubic-bezier(0.22, 1, 0.36, 1),
      filter    0.55s cubic-bezier(0.22, 1, 0.36, 1);
    will-change: transform, opacity, filter;
    backface-visibility: hidden;
  }

  .lbs-more__card.is-active {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
    filter: blur(0);
    z-index: 2;
    pointer-events: auto;
  }
  .lbs-more__card.is-prev {
    opacity: 0;
    transform: translate3d(-24%, 0, 0) scale(0.92);
    filter: blur(10px);
    z-index: 1;
  }
  .lbs-more__card.is-next {
    opacity: 0;
    transform: translate3d(24%, 0, 0) scale(0.92);
    filter: blur(10px);
    z-index: 1;
  }

  /* RTL: inline axis is mirrored — prev sits on the right, next on
     the left. CSS transforms are not automatically flipped by the
     dir attribute, so we override translateX explicitly. */
  html[dir="rtl"] .lbs-more__card.is-prev {
    transform: translate3d(24%, 0, 0) scale(0.92);
  }
  html[dir="rtl"] .lbs-more__card.is-next {
    transform: translate3d(-24%, 0, 0) scale(0.92);
  }

  .lbs-more__img {
    max-width: 62vw;
    margin-bottom: 1rem;
  }

  .lbs-more__card-title {
    font-size: 1.05rem;
  }

  .lbs-more__card-desc {
    font-size: 0.9rem;
    max-width: none;
  }

  /* Dots are <button>s with an invisible 44×44 tap target. The visible
     pill renders inside ::before, so the hit area meets iOS/Android
     accessibility guidance (44pt minimum) without bloating the layout. */
  .lbs-more__dots {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 4px;
    margin-top: 1.6rem;
  }
  .lbs-more__dot {
    position: relative;
    width: 44px;
    height: 44px;
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
    outline: 0;
    box-shadow: none;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    -webkit-tap-highlight-color: transparent;
    /* Container shows nothing — the visible pill is the ::before. */
  }
  .lbs-more__dot::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.2);
    transform: translate(-50%, -50%);
    transition:
      background 0.35s cubic-bezier(0.22, 1, 0.36, 1),
      width      0.45s cubic-bezier(0.22, 1, 0.36, 1),
      border-radius 0.45s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .lbs-more__dot:focus,
  .lbs-more__dot:focus-visible,
  .lbs-more__dot:hover,
  .lbs-more__dot:active {
    outline: 0;
    box-shadow: none;
    border: 0;
  }
  .lbs-more__dot:focus-visible::before {
    box-shadow: 0 0 0 3px rgba(0, 101, 255, 0.25);
  }
  .lbs-more__dot[aria-current="true"]::before,
  .lbs-more__dot.is-active::before {
    background: #0065ff;
    width: 24px;
    border-radius: 4px;
  }
}

/* --- Reduced motion — skip video, show everything immediately ------------ */
@media (prefers-reduced-motion: reduce) {
  .lbs-hero {
    background: #111;
  }
  .lbs-hero__title-main {
    opacity: 1;
    transform: scale(1);
  }
  .lbs-hero__title-sub,
  .lbs-hero__scroll-btn,
  .lbs-hero__ripples {
    opacity: 1;
  }
  .lbs-ripples--active .lbs-hero__ripple {
    animation: none;
  }
  .lbs-buy {
    opacity: 1;
    filter: none;
    transform: translateX(-50%);
    pointer-events: auto;
  }

  /* Drop the blur + slide from the carousel — a plain crossfade is
     friendlier to vestibular-sensitive viewers. */
  .lbs-more__card,
  .lbs-more__card.is-prev,
  .lbs-more__card.is-next,
  .lbs-more__card.is-active {
    filter: none;
    transform: none;
    transition: opacity 0.25s linear;
  }
}
