/* ============================================================
   AI Lipsync & Voice-Cloning Showcase
   Interactive case/language switcher + drag-reveal comparison.
   NOTE: this template sets html { font-size: 62.5% } so 1rem = 10px.
   Sizes below are on that scale; fonts use the site tokens
   (--_font-default = Funnel Sans, --_font-accent = Funnel Display).
   ============================================================ */

.ls-showcase {
  --ls-radius: 24px;
  --ls-gap: clamp(1.6rem, 2vw, 2.8rem);
  --ls-stage-ratio: 16 / 9;
  --ls-stage-max: 880px;
  position: relative;
  font-family: var(--_font-default);
}
.ls-showcase * { box-sizing: border-box; }

/* ---- Intro / heading ---- */
.ls-showcase__head {
  display: flex;
  flex-direction: column;
  gap: 1.6rem;
  margin-bottom: clamp(2.8rem, 4vw, 5.2rem);
  max-width: 72rem;
}
.ls-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 1rem;
  width: fit-content;
  padding: 0.8rem 1.6rem;
  border-radius: 100px;
  border: 1px solid rgba(var(--accent-rgb), 0.35);
  background: rgba(var(--accent-rgb), 0.08);
  color: var(--t-bright);
  font-size: 1.3rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  line-height: 1;
}
.ls-eyebrow::before {
  content: "";
  width: 0.8rem; height: 0.8rem;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0.4rem rgba(var(--accent-rgb), 0.25);
  animation: ls-pulse 2.4s ease-in-out infinite;
}
@keyframes ls-pulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.5;transform:scale(.7)} }

.ls-showcase__title {
  font-family: var(--_font-accent);
  font-size: clamp(3.2rem, 5vw, 5.4rem);
  line-height: 1.04;
  letter-spacing: -0.02em;
  font-weight: var(--fw-medium);
  color: var(--t-bright);
  margin: 0;
}
.ls-showcase__title em {
  font-family: 'Playfair Display', serif;
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
}
.ls-showcase__lead {
  color: var(--t-muted);
  font-family: var(--_font-default);
  font-size: clamp(1.6rem, 1.4vw, 1.8rem);
  line-height: 1.55;
  margin: 0;
}

/* ---- Cycle player opener + hand-off divider (index hero) ----
   The hero borrows the Lipsmatch auto-cycling player (styles in
   css/lipsmatch.css) as act one; this divider passes the remote
   to the interactive A/B flip stage below it. */
.ls-showcase__cycle {
  /* keep the attract-mode player in step with the interactive stage below
     (--ls-stage-max) so the whole section reads as one width;
     the Lipsmatch page keeps its own full-width hero */
  max-width: var(--ls-stage-max);
  margin: 0 auto clamp(3.6rem, 5vw, 6rem);
}
.ls-showcase__cycle .lm-cycle-note a {
  color: var(--t-bright);
  text-decoration: underline;
  text-underline-offset: 0.3em;
  text-decoration-color: rgba(var(--accent-rgb), 0.5);
}
.ls-handoff {
  display: flex;
  align-items: center;
  gap: clamp(1.4rem, 2.4vw, 2.4rem);
  margin-bottom: 1.6rem;
}
.ls-handoff__line {
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--st-bright));
}
.ls-handoff__line:last-child {
  background: linear-gradient(90deg, var(--st-bright), transparent);
}
.ls-handoff__chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.9rem 1.8rem;
  border-radius: 100px;
  border: 1px solid rgba(var(--accent-rgb), 0.35);
  background: rgba(var(--accent-rgb), 0.06);
  font-family: var(--_font-accent);
  font-size: 1.25rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: var(--t-bright);
  white-space: nowrap;
}
.ls-handoff__chip i { color: var(--accent); font-size: 1.6rem; }
.ls-handoff__note {
  margin: 0 auto clamp(2.8rem, 4vw, 4.4rem);
  max-width: 64ch;
  text-align: center;
  font-size: clamp(1.45rem, 1.3vw, 1.6rem);
  line-height: 1.55;
  color: var(--t-muted);
}

/* ---- Mobile reel gallery (.ls-reels, Home only via .ls-showcase--mreel) ----
   Under 768px the two-act interactive show doesn't build at all
   (data-lm-mobile-off / data-ls-mobile-off in the markup gate the JS). In its
   place: three baked "one beat, every language" reels (no end card, no
   credits) as clean tap-to-play cards — poster at rest, tap to play WITH
   sound, one at a time (js/lipsync-showcase.js). Desktop never shows this.
   No blur/backdrop-filter — the section must stay cheap on phones. */
.ls-lead--mobile { display: none; }
.ls-reels { display: none; }
@media (max-width: 767px) {
  .ls-showcase--mreel .ls-lead--desktop { display: none; }
  .ls-showcase--mreel .ls-lead--mobile { display: inline; }
  /* the whole interactive apparatus folds away — the reels tell the story */
  .ls-showcase--mreel .ls-showcase__cycle,
  .ls-showcase--mreel .ls-handoff,
  .ls-showcase--mreel .ls-handoff__note,
  .ls-showcase--mreel .ls-showcase__mount { display: none; }
  .ls-reels {
    display: flex;
    flex-direction: column;
    gap: 1.4rem;
  }
  /* ---- the single stage ---- */
  .ls-reelstage {
    position: relative;
    aspect-ratio: 16 / 9;
    border-radius: 1.8rem;
    border: 1px solid var(--st-muted);
    background: #0d0d0d;
    overflow: hidden;
    transition: border-color .3s ease, box-shadow .3s ease;
  }
  .ls-reelstage.is-playing {
    border-color: rgba(var(--accent-rgb), .4);
    box-shadow: 0 1.6rem 4rem -1.8rem rgba(var(--accent-rgb), .28);
  }
  .ls-reelstage video {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  /* the whole frame is the play/pause tap target */
  .ls-reelstage__toggle {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: linear-gradient(180deg, rgba(0,0,0,.05), rgba(0,0,0,.4));
    cursor: pointer;
    transition: opacity .3s ease;
  }
  .ls-reelstage.is-playing .ls-reelstage__toggle { opacity: 0; }
  .ls-reelstage.is-playing .ls-reelstage__toggle:focus-visible { opacity: 1; }
  .ls-reelstage__play {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 6rem; height: 6rem;
    border-radius: 50%;
    background: var(--accent);
    color: #12140a;
    font-size: 2.6rem;
    box-shadow: 0 1rem 2.4rem -0.6rem rgba(var(--accent-rgb), .6);
  }
  .ls-reelstage__play i { margin-left: 0.2rem; }
  .ls-reelstage__badge {
    position: absolute;
    top: 1rem; right: 1rem;
    padding: 0.5rem 1rem;
    border-radius: 100px;
    background: rgba(13, 13, 13, .72);
    border: 1px solid rgba(255, 255, 255, .16);
    color: #fff;
    font-family: var(--_font-accent);
    font-size: 1.15rem;
    font-weight: var(--fw-medium);
    letter-spacing: 0.02em;
    line-height: 1;
  }
  /* The baked reels already carry their own brand logo (top-left) and the big
     language label (bottom-left), and the 2×2 chip grid below names the active
     film — so an on-stage brand/hint caption only crowds the frame and covers
     the subject. We drop it; just the small "N languages" badge stays. */
  .ls-reelstage__cap { display: none; }

  /* ---- the film picker: a 2×2 grid so all four films read at a glance
     (a scroll rail hid films 3–4 behind the edge fade — users couldn't tell
     there were four). No overflow, no snap: everything is on screen. ---- */
  .ls-reelpicker {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.9rem;
    margin: 1.2rem 0 0;
    padding: 0.2rem;
  }
  .ls-reelchip {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    min-width: 0;                 /* let long film names ellipsis inside the cell */
    padding: 0.6rem 0.7rem 0.6rem 0.6rem;
    border-radius: 1.4rem;
    border: 1px solid var(--st-muted);
    background: var(--base-tint);
    color: var(--t-bright);
    text-align: left;
    cursor: pointer;
    transition: border-color .25s ease, background .25s ease, transform .25s ease;
  }
  .ls-reelchip.is-active {
    border-color: rgba(var(--accent-rgb), .55);
    background: rgba(var(--accent-rgb), .08);
    transform: translateY(-0.1rem);
  }
  .ls-reelchip__thumb {
    flex: 0 0 auto;
    width: 4rem; height: 2.4rem;
    border-radius: 0.7rem;
    background: #0d0d0d center / cover no-repeat;
    border: 1px solid rgba(255, 255, 255, .12);
  }
  .ls-reelchip__name {
    flex: 1 1 auto;
    min-width: 0;                 /* allow ellipsis inside the grid cell */
    display: flex;
    flex-direction: column;
    font-family: var(--_font-accent);
    font-size: 1.25rem;
    font-weight: var(--fw-medium);
    line-height: 1.15;
  }
  .ls-reelchip__name,
  .ls-reelchip__sub {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .ls-reelchip__sub {
    font-family: var(--_font-primary, inherit);
    font-size: 1.05rem;
    font-weight: var(--fw-regular, 400);
    color: var(--t-muted);
    letter-spacing: 0;
  }
  .ls-reelchip__count {
    flex: 0 0 auto;
    min-width: 1.8rem;
    padding: 0.2rem 0.5rem;
    border-radius: 100px;
    background: rgba(255, 255, 255, .08);
    color: var(--t-muted);
    font-family: var(--_font-accent);
    font-size: 1.05rem;
    line-height: 1.4;
    text-align: center;
  }
  .ls-reelchip.is-active .ls-reelchip__count {
    background: var(--accent);
    color: #12140a;
  }
  .ls-reels__note {
    margin: 0.4rem 0 0;
    color: var(--t-muted);
    font-size: 1.4rem;
    line-height: 1.5;
  }
  .ls-reels__note a {
    color: var(--t-bright);
    text-decoration: underline;
    text-underline-offset: 0.3em;
    text-decoration-color: rgba(var(--accent-rgb), 0.5);
  }
  /* feature strip: four tall cards fold into a boxed 2×2 chip grid. The
     default phone rule (line ~1326) flattens .ls-feature into a transparent
     horizontal list-row; here we re-assert the box, exactly like .sw-atelier.
     minmax(0,1fr) lets the tracks shrink below the cards' min-content so the
     grid can't blow past the viewport (the earlier overflow bug). detail +
     the pointer-driven spotlight frills don't earn phone scrolls. */
  .ls-showcase--mreel .ls-features {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
    margin-top: 2.4rem;
    border-top: none;
  }
  .ls-showcase--mreel .ls-feature {
    display: block;
    padding: 1.6rem 1.5rem;
    border: 1px solid var(--st-muted);
    border-radius: 1.6rem;
    background: var(--base-tint);
    overflow: hidden;
  }
  .ls-showcase--mreel .ls-feature__icon { font-size: 2.4rem; margin: 0 0 1rem; }
  .ls-showcase--mreel .ls-feature__num { font-size: 1.9rem; white-space: normal; }
  .ls-showcase--mreel .ls-feature__label { font-size: 1.3rem; margin: 0.4rem 0 0; }
  .ls-showcase--mreel .ls-feature__detail { display: none; }
}

/* ---- Case tabs: grouped into brand clusters ----
   The rail no longer reads as one flat list of look-alike pills. Each brand /
   campaign becomes its own labelled cluster (monogram + name + type tag), and
   the *type of work* is colour-coded: lip-sync carries the lime brand accent,
   voice-cloning a cool blue — so the two techniques never look identical. */
.ls-cases {
  display: flex;
  align-items: stretch;
  gap: 1.4rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* overflow-x:auto forces overflow-y to auto, which clips anything extending
     below the row — so clusters lift UPWARD (into the top padding) and carry
     no downward glow that could be sliced. */
  padding: 0.7rem 0.4rem 1rem;
  margin-bottom: calc(var(--ls-gap) - 0.4rem);
  scrollbar-width: none;
  -ms-overflow-style: none;
  /* drag-to-browse + gentle snap for effortless navigation */
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  cursor: grab;
  /* edge fades on both sides signal "more to scroll" without a scrollbar */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 3.2rem, #000 calc(100% - 4.8rem), transparent);
  mask-image: linear-gradient(to right, transparent, #000 3.2rem, #000 calc(100% - 4.8rem), transparent);
  transition: -webkit-mask-image .3s, mask-image .3s;
}
/* when scrolled to the very start, drop the left fade so the active tab is crisp */
.ls-cases[data-at-start="1"] {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 4.8rem), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 4.8rem), transparent);
}
.ls-cases[data-at-end="1"] {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 3.2rem, #000 100%);
  mask-image: linear-gradient(to right, transparent, #000 3.2rem, #000 100%);
}
/* nothing to scroll (fits on wide screens): both edges are "at limit" at once —
   drop the mask entirely so the first cluster isn't faded/clipped on the left */
.ls-cases[data-at-start="1"][data-at-end="1"] {
  -webkit-mask-image: none;
  mask-image: none;
}
/* an inner page shows a single brand — centre it (falls back to start if it
   ever overflows, so nothing gets clipped out of reach) */
.ls-cases--single-group { justify-content: safe center; }
.ls-cases.is-grabbing { cursor: grabbing; scroll-behavior: auto; scroll-snap-type: none; }
.ls-cases.is-grabbing .ls-case-tab { pointer-events: none; }
.ls-cases::-webkit-scrollbar { display: none; }
/* Single-case (inner-page) embeds don't need a tab bar */
.ls-showcase__widget--single .ls-cases { display: none; }

/* wrapper holds the scroll rail + its chevrons; chevrons sit OUTSIDE the rail so
   the rail's edge mask never fades them */
.ls-cases-wrap { position: relative; }

/* left/right scroll chevrons — same visual language as the .ls-langs__fade
   chevrons below, shown only when there's more of the rail to reveal */
.ls-cases__nav {
  position: absolute;
  top: calc(50% - 1.7rem);
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.4rem; height: 3.4rem;
  border-radius: 50%;
  border: none;
  background: var(--accent);
  color: #161616;
  font-size: 1.6rem;
  cursor: pointer;
  box-shadow: 0 0.4rem 1.2rem rgba(0, 0, 0, .45);
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease, box-shadow .2s ease, background .2s ease;
}
.ls-cases__nav.is-on { opacity: 1; pointer-events: auto; }
.ls-cases__nav:hover { box-shadow: 0 0.5rem 1.6rem rgba(var(--accent-rgb), .5); }
.ls-cases__nav:active { transform: scale(.92); }
/* inset just inside the rail edges (over the fade) so they're always fully
   on-screen — even on a near-full-bleed mobile layout — and clearly tappable */
.ls-cases__nav--l { left: 0.4rem; }
.ls-cases__nav--r { right: 0.4rem; }
/* gentle outward nudge to read as "swipe for more" (icon-only, so it never fights
   the button's own centering transform) */
.ls-cases__nav.is-on i { animation: ls-nudge-r 1.6s ease-in-out infinite; }
.ls-cases__nav--l.is-on i { animation-name: ls-nudge-l; }

/* ---- brand cluster ---- */
.ls-case-group {
  --grp-accent: var(--accent);
  --grp-accent-rgb: var(--accent-rgb);
  flex: 0 0 auto;
  scroll-snap-align: center;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.1rem 1.1rem 1.2rem;
  border-radius: 1.8rem;
  border: 1px solid var(--st-muted);
  /* faint top sheen over the panel tint reads as brushed, premium glass */
  background:
    linear-gradient(180deg, rgba(255,255,255,.035), rgba(255,255,255,0) 55%),
    var(--base-tint);
  transition: border-color .35s ease, box-shadow .35s ease, background .35s ease;
}
/* voice-cloning is a different technique — give it a distinct cool accent */
.ls-case-group[data-kind="voice"] { --grp-accent: #8ab4ff; --grp-accent-rgb: 138,180,255; }
.ls-case-group.is-active {
  border-color: rgba(var(--grp-accent-rgb), .42);
  /* inset-only emphasis — the rail clips overflow-y, so no downward glow to slice */
  background:
    linear-gradient(180deg, rgba(var(--grp-accent-rgb), .08), rgba(255,255,255,0) 60%),
    var(--base-tint);
  box-shadow: inset 0 0 0 1px rgba(var(--grp-accent-rgb), .18);
}

/* ---- cluster header: monogram · brand · type ---- */
.ls-case-group__label {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.4rem 0.5rem;
  margin: -0.4rem -0.1rem 0;
  border-radius: 1.1rem;
  cursor: pointer;               /* the whole header selects the brand's first film */
  transition: background .25s ease;
}
.ls-case-group__label:hover { background: rgba(var(--grp-accent-rgb), .07); }
.ls-cases.is-grabbing .ls-case-group__label { pointer-events: none; }
.ls-case-group__mono {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 2.8rem; height: 2.8rem;
  border-radius: 0.9rem;
  font-family: var(--_font-accent);
  font-size: 1.25rem;
  font-weight: var(--fw-semibold);
  letter-spacing: -0.02em;
  color: var(--grp-accent);
  background: rgba(var(--grp-accent-rgb), .13);
  border: 1px solid rgba(var(--grp-accent-rgb), .32);
  transition: background .35s ease, color .35s ease, border-color .35s ease;
}
.ls-case-group__mono i { font-size: 1.5rem; }
.ls-case-group.is-active .ls-case-group__mono {
  background: var(--grp-accent);
  color: #10151f;
  border-color: transparent;
}
.ls-case-group__name {
  font-family: var(--_font-accent);
  font-size: 1.5rem;
  font-weight: var(--fw-medium);
  color: var(--t-bright);
  line-height: 1.1;
  white-space: nowrap;
}
.ls-case-group__kind {
  margin-left: auto;
  font-size: 0.95rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: var(--grp-accent);
  padding: 0.4rem 0.8rem;
  border-radius: 100px;
  background: rgba(var(--grp-accent-rgb), .1);
  border: 1px solid rgba(var(--grp-accent-rgb), .24);
  white-space: nowrap;
  line-height: 1;
}

/* ---- pills within a cluster ---- */
.ls-case-group__pills { display: flex; gap: 0.6rem; }
.ls-case-tab {
  flex: 0 0 auto;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 0.3rem;
  padding: 0.9rem 1.5rem;
  border-radius: 1.2rem;
  border: 1px solid var(--st-muted);
  background: rgba(0,0,0,.16);
  color: var(--t-bright);
  cursor: pointer;
  transition: border-color .25s, color .25s, background .3s cubic-bezier(.5,.05,.1,1),
              transform .35s cubic-bezier(.34,1.56,.64,1), box-shadow .3s;
  white-space: nowrap;
  font-family: var(--_font-accent);
}
.ls-case-tab:hover {
  border-color: rgba(var(--grp-accent-rgb), .55);
  background: rgba(var(--grp-accent-rgb), .07);
  transform: translateY(-2px);   /* lifts UP into the top padding — never clipped */
}
.ls-case-tab:active { transform: translateY(0) scale(.97); }
.ls-case-tab__name { font-weight: var(--fw-medium); font-size: 1.5rem; line-height: 1.2; }
.ls-case-tab__meta {
  font-size: 1.05rem; letter-spacing: .07em; opacity: .55;
  text-transform: uppercase; line-height: 1.2; font-weight: var(--fw-semibold);
}
.ls-case-tab.is-active {
  border-color: transparent;
  background: var(--grp-accent);
  color: #10151f;
  /* inset highlight reads as depth without a downward glow the rail would clip */
  box-shadow: inset 0 0.1rem 0 rgba(255,255,255,.35);
}
.ls-case-tab.is-active:hover { background: var(--grp-accent); }
.ls-case-tab.is-active .ls-case-tab__meta { opacity: .7; }

/* ---- centered interactive column ---- */
.ls-stage,
.ls-caption,
.ls-langs { max-width: var(--ls-stage-max); margin-left: auto; margin-right: auto; }
/* single-language case: no sibling to compare against, so the lone chip is a
   dead control — drop the whole strip (JS tags it .ls-langs--solo). Scoped to
   the Lipsmatch (craft) mounts so the studio site keeps its existing behaviour.
   Compound selector so it outranks the base `.ls-langs { display:flex }`. */
[data-ls-craft] .ls-langs.ls-langs--solo { display: none; }
/* controls-above-stage order (everywhere but the case-study hero): the stage
   closes the stack, so it carries the gap the controls used to provide */
.ls-showcase__widget--controls-top .ls-stage { margin-top: var(--ls-gap); }

/* ============================================================
   Editing-suite layout  (laptops & desktops, Home multi-case mount)
   Built by js/lipsync-showcase.js only when wide (>=1024), multi-case,
   and NOT inside a case-study .ie-compare-hero. Turns the two stacked
   horizontal rails into a quiet VERTICAL film "bin" (left) beside a
   dominant player (right); the language rail + A/B flip sit compactly
   with the video. Phones (baked reels) and inner case pages never build
   this, so their layouts above are untouched.
   ============================================================ */
.ls-showcase__widget--suite { max-width: 1180px; margin-inline: auto; }
.ls-suite {
  display: grid;
  grid-template-columns: minmax(24rem, 30rem) minmax(0, 1fr);
  gap: clamp(2rem, 2.4vw, 3.4rem);
  align-items: start;
}

/* ---- left column: the film bin ---- */
.ls-suite__bin {
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
  min-width: 0;
}
.ls-suite__binhead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.2rem 0.4rem 0.4rem;
  border-bottom: 1px solid var(--st-muted);
}
.ls-suite__binttl {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--_font-accent);
  font-size: 1.55rem;
  font-weight: var(--fw-semibold);
  letter-spacing: -0.01em;
  color: var(--t-bright);
}
.ls-suite__binttl i { color: var(--accent); font-size: 1.6rem; }
.ls-suite__binsub {
  font-size: 1.1rem;
  letter-spacing: .02em;
  color: var(--t-muted);
  white-space: nowrap;
}

/* the case rail flips from a horizontal drag-strip into a stacked, scrollable
   list. Its chevrons and edge-fade mask (both horizontal affordances) are
   dropped; the active row auto-centers if the list ever overflows. */
.ls-showcase__widget--suite .ls-cases-wrap { flex: 1 1 auto; min-height: 0; }
.ls-showcase__widget--suite .ls-cases {
  flex-direction: column;
  align-items: stretch;
  gap: 1rem;
  overflow-x: hidden;
  overflow-y: auto;
  max-height: min(66rem, 74vh);
  padding: 0.2rem 0.2rem;
  margin: 0;
  scroll-snap-type: none;
  cursor: default;
  -webkit-mask-image: none;
  mask-image: none;
}
.ls-showcase__widget--suite .ls-cases__nav { display: none; }

/* brand cluster: a quiet grouped block; header reads as a section label,
   films beneath it become full-width list rows */
.ls-showcase__widget--suite .ls-case-group {
  scroll-snap-align: none;
  gap: 0.6rem;
  padding: 0.9rem 0.9rem 1rem;
  border-radius: 1.4rem;
}
.ls-showcase__widget--suite .ls-case-group__label {
  gap: 0.7rem;
  padding: 0.2rem 0.3rem;
  margin: 0;
}
.ls-showcase__widget--suite .ls-case-group__mono {
  width: 2.4rem; height: 2.4rem;
  border-radius: 0.7rem;
  font-size: 1.05rem;
}
.ls-showcase__widget--suite .ls-case-group__mono i { font-size: 1.3rem; }
.ls-showcase__widget--suite .ls-case-group__name { font-size: 1.35rem; }
.ls-showcase__widget--suite .ls-case-group__kind {
  font-size: 0.82rem;
  padding: 0.3rem 0.6rem;
}

/* pills → full-width list rows (film title left, meta right) */
.ls-showcase__widget--suite .ls-case-group__pills {
  flex-direction: column;
  gap: 0.4rem;
}
.ls-showcase__widget--suite .ls-case-tab {
  flex-direction: row;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.9rem;
  width: 100%;
  padding: 0.72rem 1.05rem;
  border-radius: 0.9rem;
}
.ls-showcase__widget--suite .ls-case-tab:hover { transform: none; }  /* no lift inside a list */
.ls-showcase__widget--suite .ls-case-tab:active { transform: scale(.99); }
.ls-showcase__widget--suite .ls-case-tab__name { font-size: 1.35rem; }
.ls-showcase__widget--suite .ls-case-tab__meta { font-size: 0.98rem; }

/* ---- right column: the player ---- */
.ls-suite__main {
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
  min-width: 0;
}
/* inside the suite the player pieces span their column instead of the old
   centered 880px cap */
.ls-showcase__widget--suite .ls-stage,
.ls-showcase__widget--suite .ls-caption,
.ls-showcase__widget--suite .ls-langs {
  max-width: none;
  width: 100%;
  margin: 0;
}
.ls-showcase__widget--suite .ls-caption { order: -1; }   /* the read-along lead sits above the video */
/* Lipsmatch (craft) suite only: lift the language rail above the player too, so
   the "pick a language" control leads the video like the studio case pages do.
   caption and langs share order:-1, so DOM order keeps caption first. The studio
   home suite (no data-ls-craft) keeps the rail under the player. */
[data-ls-craft] .ls-showcase__widget--suite .ls-langs { order: -1; }

/* rare resize-down (a desktop window dragged narrow after load keeps the suite
   DOM): fold the two columns into one so nothing is squeezed */
@media (max-width: 900px) {
  .ls-suite { grid-template-columns: minmax(0, 1fr); }
  .ls-showcase__widget--suite .ls-cases { max-height: 34rem; }
}

/* ---- Main stage ----
   Two stacked layers, only ONE ever plays. Comparison is an opacity crossfade
   between them (the A/B flip), not a spatial clip-path wipe — so there's never
   a second live decode or a per-frame split to repaint. touch-action stays
   `auto` so a finger that lands on the video still scrolls the page. */
.ls-stage {
  position: relative;
  width: 100%;
  aspect-ratio: var(--ls-stage-ratio);
  border-radius: var(--ls-radius);
  overflow: hidden;
  background: #0b0b0b;
  box-shadow: 0 3rem 8rem -4rem rgba(0,0,0,.7);
  isolation: isolate;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
.ls-stage video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* the shown layer fades up over the other; the outgoing one holds its last
   frame beneath during the dissolve */
.ls-layer {
  opacity: 0;
  transition: opacity .4s ease;
  will-change: opacity;
}
.ls-layer.is-active { opacity: 1; }
.ls-layer--after  { z-index: 1; }
.ls-layer--before { z-index: 2; }
.ls-layer.is-active { z-index: 3; }
/* fade BOTH out while a new case/language loads in (wins over .is-active) */
.ls-stage.is-switching .ls-layer { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .ls-layer { transition: none; }
}

/* on-video status badge (which version you're watching) */
.ls-tag {
  position: absolute;
  top: 1.6rem;
  left: 1.6rem;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 1.3rem;
  border-radius: 100px;
  font-size: 1.2rem;
  font-weight: var(--fw-semibold);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: #fff;
  background: rgba(0,0,0,.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.16);
  pointer-events: none;
  line-height: 1;
  transition: background .35s ease, color .35s ease, border-color .35s ease;
}
/* the AI cut carries the brand accent; the original reads neutral */
.ls-tag--after { background: rgba(var(--accent-rgb), .92); color: #161616; border-color: transparent; }
/* the badge labels the visual compare; the voice panel labels voice mode */
.ls-stage[data-mode="voice"] .ls-tag { display: none; }
.ls-tag i { font-size: 1.4rem; }

/* center play / loading overlay */
.ls-stage__overlay {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: grid;
  place-items: center;
  background: rgba(0,0,0,.25);
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s;
}
.ls-stage.is-paused .ls-stage__overlay { opacity: 1; pointer-events: auto; cursor: pointer; }
.ls-stage__play {
  width: 7.2rem; height: 7.2rem;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .14);
  background: rgba(10, 10, 10, .45);
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
  box-shadow: 0 1.6rem 4.4rem -1.2rem rgba(0, 0, 0, .65),
              inset 0 1px 0 rgba(255, 255, 255, .12);
  color: #fff;
  display: grid; place-items: center;
  font-size: 2.8rem;
  cursor: pointer;
  transform: scale(.7);
  transition: transform .5s cubic-bezier(0.34, 1.56, 0.64, 1),
              background .3s, color .3s, border-color .3s;
}
.ls-stage.is-paused .ls-stage__play { transform: scale(1); }
.ls-stage__play:hover {
  background: var(--accent);
  border-color: transparent;
  color: #131313;
  transform: scale(1.07);
}
.ls-stage__play:active { transform: scale(.94); transition-duration: .1s; }
.ls-spinner {
  position: absolute; top: 50%; left: 50%;
  z-index: 8;
  width: 4.4rem; height: 4.4rem;
  margin: -2.2rem 0 0 -2.2rem;
  border: 3px solid rgba(255,255,255,.18);
  border-top-color: var(--accent);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none; /* invisible most of the time — must never eat clicks */
  animation: ls-spin .8s linear infinite;
}
.ls-stage.is-loading .ls-spinner { opacity: 1; }
@keyframes ls-spin { to { transform: rotate(360deg); } }

/* ---- quiet stage (data-ls-quiet): "Tap to unmute" pill --------------
   Rendered only on quiet mounts (JS appends .ls-unmute there). Same look
   and manners as the lipsmatch.com home player's .lm-cycle__unmute:
   visible while the film rolls silently, trails the cursor on fine
   pointers (inline transform once .is-cursor is set), never eats clicks
   (the stage click underneath is the unmute). Hidden while paused or
   loading — the play overlay / spinner owns those moments. */
.ls-unmute {
  position: absolute; top: 50%; left: 50%;
  z-index: 9;
  transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; gap: 0.8rem;
  padding: 1rem 1.8rem;
  border-radius: 100px;
  background: rgba(13, 14, 17, .72);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: #fff;
  font-family: var(--_font-accent);
  font-size: 1.4rem; font-weight: var(--fw-medium);
  letter-spacing: .01em;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s ease;
}
.ls-unmute i { font-size: 1.7rem; }
.ls-stage.is-muted:not(.is-paused):not(.is-loading) .ls-unmute { opacity: 1; }
.ls-unmute.is-cursor {
  top: 0; left: 0;
  transition: transform .18s cubic-bezier(.22,1,.36,1), opacity .3s ease;
  will-change: transform;
}
@media (pointer: coarse) {
  .ls-unmute {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(13, 14, 17, .82);
  }
}

/* ---- floating glass control pill (matches .ievp-bar in video-player.css):
   play · time · seek · volume · replay ---- */
.ls-stage__controls {
  position: absolute;
  left: clamp(1.2rem, 1.8vw, 2.2rem);
  right: clamp(1.2rem, 1.8vw, 2.2rem);
  bottom: clamp(1.2rem, 1.8vw, 2.2rem);
  z-index: 8;
  display: flex;
  align-items: center;
  gap: clamp(.4rem, .8vw, 1rem);
  max-width: 88rem;
  margin-inline: auto;
  padding: .7rem 1rem .7rem .7rem;
  border-radius: 10rem;
  border: 1px solid rgba(255, 255, 255, .1);
  background: rgba(10, 10, 10, .55);
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  backdrop-filter: blur(20px) saturate(1.6);
  box-shadow: 0 1.2rem 3.6rem -1rem rgba(0, 0, 0, .6),
              inset 0 1px 0 rgba(255, 255, 255, .08);
  opacity: 0;
  transform: translateY(1rem) scale(.97);
  transform-origin: bottom center;
  pointer-events: none;
  transition: opacity .35s cubic-bezier(0.22, 1, 0.36, 1),
              transform .45s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
/* revealed while paused, scrubbing, or within the HUD window after an
   interaction (JS toggles .is-hud); keyboard focus pins it */
.ls-stage.is-paused .ls-stage__controls,
.ls-stage.is-hud .ls-stage__controls,
.ls-stage.is-seeking .ls-stage__controls {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.ls-stage__controls:has(:focus-visible) {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
@media (hover: hover) {
  .ls-stage:hover .ls-stage__controls {
    opacity: 1;
    transform: none;
    pointer-events: auto;
  }
}

.ls-ctrl {
  position: relative;
  flex: 0 0 auto;
  width: 3.8rem; height: 3.8rem;
  border-radius: 50%;
  border: 0;
  background: transparent;
  color: #fff;
  display: grid; place-items: center;
  cursor: pointer;
  font-size: 1.7rem;
  transition: background .25s ease, color .25s ease, transform .25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.ls-ctrl:hover { background: rgba(255, 255, 255, .14); }
.ls-ctrl:active { transform: scale(.9); transition-duration: .1s; }
.ls-ctrl.is-on { background: var(--accent); color: #161616; }
.ls-ctrl--play { background: rgba(255, 255, 255, .1); }
.ls-ctrl--play:hover { background: var(--accent); color: #131313; }

/* cross-fading play/pause glyphs (shared language with .ievp-g) */
.ls-g {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 1em; height: 1em;
  fill: currentColor;
  transition: opacity .24s ease, transform .34s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.ls-ctrl--play .ls-g--play { left: 5%; opacity: 1; transform: scale(1) rotate(0deg); }
.ls-ctrl--play .ls-g--pause { opacity: 0; transform: scale(.5) rotate(90deg); }
.ls-ctrl--play.is-playing .ls-g--play { opacity: 0; transform: scale(.5) rotate(-90deg); }
.ls-ctrl--play.is-playing .ls-g--pause { opacity: 1; transform: scale(1) rotate(0deg); }

/* time readout */
.ls-time {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: .4rem;
  min-width: 8.2rem;
  font: var(--fw-medium, 500) 1.25rem/1 var(--_font-default, sans-serif);
  color: #fff;
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
  -webkit-user-select: none;
  user-select: none;
}
.ls-time__sep { opacity: .45; font-size: 1.05rem; }
.ls-time__dur { opacity: .6; }

/* volume group — slider expands on hover/focus */
.ls-vol { flex: 0 0 auto; display: flex; align-items: center; gap: 0.2rem; }
.ls-vol__slider {
  width: 0;
  height: 2.4rem;
  display: flex;
  align-items: center;
  cursor: pointer;
  opacity: 0;
  touch-action: none;
  transition: width .35s cubic-bezier(0.22, 1, 0.36, 1), opacity .25s;
}
.ls-vol:hover .ls-vol__slider,
.ls-vol:focus-within .ls-vol__slider { width: 7.4rem; opacity: 1; margin-right: 0.5rem; }
.ls-vol__track {
  position: relative;
  width: 100%;
  height: 0.4rem;
  border-radius: 100px;
  background: rgba(255, 255, 255, .18);
}
.ls-vol__fill {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 100%;
  border-radius: 100px;
  background: #fff;
}
.ls-vol__thumb {
  position: absolute;
  top: 50%; left: 100%;
  width: 1.2rem; height: 1.2rem;
  border-radius: 50%;
  background: #fff;
  transform: translate(-50%, -50%);
  box-shadow: 0 .2rem .6rem rgba(0, 0, 0, .5);
}
@media (max-width: 767px) {
  /* Touch platforms (notably iOS) ignore programmatic video.volume, so the
     slider does nothing there and only crowds the control row — drop it and let
     the mute button act as the sound toggle. */
  .ls-vol__slider { display: none; }
}

/* ---- seek line (lives inside the control pill) ---- */
.ls-seek {
  position: relative;
  flex: 1 1 auto;
  height: 2.4rem;
  display: flex;
  align-items: center;
  cursor: pointer;
  touch-action: none;
}
.ls-seek__track {
  position: relative;
  width: 100%;
  height: 0.4rem;
  border-radius: 10rem;
  background: rgba(255,255,255,.18);
  transition: height .2s cubic-bezier(0.22, 1, 0.36, 1);
}
.ls-seek:hover .ls-seek__track,
.ls-stage.is-seeking .ls-seek__track { height: 0.65rem; }
/* --sp (played fraction, 0–1) is set on .ls-seek by JS every frame;
   scaleX keeps the per-frame paint compositor-only (no layout) */
.ls-seek__fill {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 100%;
  border-radius: 10rem;
  background: var(--accent);
  box-shadow: 0 0 1.2rem rgba(var(--accent-rgb), .45);
  transform-origin: left center;
  transform: scaleX(var(--sp, 0));
  will-change: transform;
}
.ls-seek__thumb {
  position: absolute;
  top: 50%; left: calc(var(--sp, 0) * 100%);
  width: 1.4rem; height: 1.4rem;
  border-radius: 50%;
  background: #fff;
  transform: translate(-50%, -50%) scale(0);
  box-shadow: 0 0.2rem 0.8rem rgba(0,0,0,.5),
              0 0 0 0.4rem rgba(var(--accent-rgb), .25);
  transition: transform .25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.ls-seek:hover .ls-seek__thumb { transform: translate(-50%, -50%) scale(1); }
.ls-stage.is-seeking .ls-seek__thumb { transform: translate(-50%, -50%) scale(1.25); }

/* ---- A/B compare toggle (lip-sync cases) ----
   Replaces the drag slider. A big, unmissable segmented control: watch the AI
   cut, tap "Original" to flip to the raw source at the same instant. A single
   sliding indicator glides between the two. */
.ls-ab {
  position: relative;
  display: none;
  grid-template-columns: 1fr 1fr;
  gap: 0.4rem;
  width: fit-content;
  max-width: min(100%, 46rem);
  margin: var(--ls-gap) auto 0;
  padding: 0.5rem;
  border-radius: 100px;
  border: 1px solid var(--st-muted);
  background: var(--base-tint);
  box-shadow: inset 0 0.1rem 0.2rem rgba(0,0,0,.18);
}
.ls-ab.is-on { display: grid; }
/* the accent pill that slides under the active segment */
.ls-ab__ind {
  position: absolute;
  top: 0.5rem; left: 0;
  height: calc(100% - 1rem);
  width: var(--w, 50%);
  border-radius: 100px;
  background: var(--accent);
  box-shadow: 0 0.6rem 1.6rem -0.6rem rgba(var(--accent-rgb), .65);
  transform: translateX(var(--x, 0));
  transition: transform .45s cubic-bezier(.5,.05,.1,1), width .45s cubic-bezier(.5,.05,.1,1);
  z-index: 0;
  pointer-events: none;
}
.ls-ab__btn {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.8rem;
  min-height: 4.4rem;
  padding: 0 2rem;
  border: none;
  border-radius: 100px;
  background: transparent;
  color: var(--t-bright);
  font-family: var(--_font-accent);
  font-size: 1.55rem;
  font-weight: var(--fw-medium);
  cursor: pointer;
  white-space: nowrap;
  line-height: 1;
  transition: color .35s ease;
}
.ls-ab__btn i { font-size: 1.7rem; opacity: .8; transition: opacity .35s ease; }
.ls-ab__btn:hover:not(.is-active) { color: var(--accent); }
.ls-ab__btn.is-active { color: #161616; }
.ls-ab__btn.is-active i { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .ls-ab__ind { transition: none; }
}

/* one-time "you can tap to flip me" nudge — a soft wobble + accent ring pulse
   fired by JS when the showcase scrolls into view, until the visitor flips it
   themselves. Amplitude stays under the container padding so mobile never gains
   a horizontal scrollbar. */
@keyframes ls-ab-nudge {
  0%   { transform: translateX(0); }
  9%   { transform: translateX(-0.4rem) rotate(-0.45deg); }
  20%  { transform: translateX(0.36rem) rotate(0.35deg); }
  31%  { transform: translateX(-0.28rem); }
  42%  { transform: translateX(0.2rem); }
  53%  { transform: translateX(-0.12rem); }
  64%  { transform: translateX(0.06rem); }
  75%, 100% { transform: translateX(0); }
}
@keyframes ls-ab-glow {
  0%, 100% { box-shadow: inset 0 0.1rem 0.2rem rgba(0,0,0,.18); }
  40%      { box-shadow: inset 0 0.1rem 0.2rem rgba(0,0,0,.18),
                         0 0 0 0.3rem rgba(var(--accent-rgb), .22); }
}
.ls-ab.is-hinting {
  animation: ls-ab-nudge 1s cubic-bezier(.36,.07,.19,.97) both,
             ls-ab-glow 1s ease both;
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .ls-ab.is-hinting { animation: none; }
}

/* ---- embedded variant: the flip rides on the video's top edge ----
   Applied on every layout (home controls-top mounts + the case-study heroes).
   The toggle doubles as the on-video status, so the corner .ls-tag badge is
   dropped. Centered with left/right:0 + margin:auto (NOT translateX) so the
   attention-nudge keyframes keep transform to themselves. Compound selector
   so it outranks the plain .ls-ab mobile width rule regardless of order. */
.ls-ab.ls-ab--on-stage {
  position: absolute;
  top: 1.4rem;
  left: 0; right: 0;
  margin: 0 auto;
  width: fit-content;
  max-width: calc(100% - 2.4rem);
  z-index: 7;                        /* above the paused overlay (6) so it stays tappable */
  background: rgba(13, 14, 17, .6);
  border-color: rgba(255, 255, 255, .16);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: 0 1.2rem 3rem -1rem rgba(0, 0, 0, .55);
}
.ls-stage:has(.ls-ab--on-stage) .ls-tag { display: none; }

/* ---- caption + voice note ---- */
.ls-caption {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.2rem;
  margin-top: var(--ls-gap);
}
.ls-caption__text {
  flex: 1 1 32rem;
  color: var(--t-muted);
  font-size: 1.6rem;
  line-height: 1.5;
  margin: 0;
}
.ls-caption__text strong { color: var(--t-bright); font-weight: var(--fw-semibold); }
.ls-caption__text.ls-anim { animation: ls-fade-up .5s cubic-bezier(.22, 1, .36, 1) both; }
@keyframes ls-fade-up {
  from { opacity: 0; transform: translateY(0.5rem); }
  to   { opacity: 1; transform: none; }
}
.ls-voice-note {
  display: inline-flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.9rem 1.6rem;
  border-radius: 100px;
  background: rgba(var(--accent-rgb), .12);
  border: 1px solid rgba(var(--accent-rgb), .3);
  color: var(--t-bright);
  font-size: 1.35rem;
  font-weight: var(--fw-medium);
  white-space: nowrap;
  line-height: 1;
}
.ls-voice-note i { color: var(--accent); font-size: 1.6rem; }

/* ---- voice A/B panel (voice-clone cases) ----
   Two selectable voice tracks under a single, continuously-playing film: the
   regional voice actor's reference and the star's AI-cloned voice. Picking one
   routes the sound to it live; its waveform lights up and animates. */
.ls-voices {
  display: none;
  grid-template-columns: 1fr 1fr;
  gap: 1.2rem;
  max-width: var(--ls-stage-max);
  margin: var(--ls-gap) auto 0;
}
.ls-voices.is-on { display: grid; }
.ls-voices.ls-voices--single { grid-template-columns: 1fr; }

.ls-voice {
  --v-accent: var(--accent);
  --v-accent-rgb: var(--accent-rgb);
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 1.6rem;
  text-align: left;
  padding: 1.8rem 2rem;
  border-radius: 1.8rem;
  border: 1px solid var(--st-muted);
  background: var(--base-tint);
  color: var(--t-bright);
  cursor: pointer;
  font-family: var(--_font-default);
  transition: border-color .3s ease, background .3s ease,
              transform .35s cubic-bezier(.22,1,.36,1), box-shadow .35s ease;
}
.ls-voice.is-absent { display: none; }
.ls-voice:hover {
  transform: translateY(-2px);
  border-color: rgba(var(--v-accent-rgb), .45);
  background: rgba(var(--v-accent-rgb), .05);
}
.ls-voice.is-active {
  border-color: transparent;
  background: rgba(var(--v-accent-rgb), .1);
  box-shadow: inset 0 0 0 1px rgba(var(--v-accent-rgb), .55),
              0 1.2rem 3rem -1.4rem rgba(var(--v-accent-rgb), .6);
}
/* the reference-voice card reads in a cooler, neutral tone so the two tracks are
   instantly distinguishable; the cloned-voice card carries the brand accent */
.ls-voice--original { --v-accent: #8ab4ff; --v-accent-rgb: 138,180,255; }

.ls-voice__head {
  display: flex;
  align-items: center;
  gap: 1.2rem;
}
.ls-voice__icon {
  flex: 0 0 auto;
  width: 4rem; height: 4rem;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 1.9rem;
  color: var(--v-accent);
  background: rgba(var(--v-accent-rgb), .14);
  border: 1px solid rgba(var(--v-accent-rgb), .3);
  transition: background .3s, color .3s;
}
.ls-voice.is-active .ls-voice__icon {
  background: var(--v-accent);
  color: #10151f;
  border-color: transparent;
}
.ls-voice__labels { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.ls-voice__label {
  font-family: var(--_font-accent);
  font-size: 1.7rem;
  font-weight: var(--fw-medium);
  line-height: 1.2;
}
.ls-voice__sub {
  font-size: 1.25rem;
  color: var(--t-muted);
  line-height: 1.3;
}
/* state chip on the right: "Playing" when active, "Hear this voice" otherwise */
.ls-voice__state {
  margin-left: auto;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 1.1rem;
  border-radius: 100px;
  font-size: 1.15rem;
  font-weight: var(--fw-semibold);
  letter-spacing: .04em;
  line-height: 1;
  white-space: nowrap;
  color: var(--t-muted);
  background: rgba(255,255,255,.05);
  border: 1px solid var(--st-muted);
  transition: color .3s, background .3s, border-color .3s;
}
.ls-voice.is-active .ls-voice__state {
  color: #10151f;
  background: var(--v-accent);
  border-color: transparent;
}
.ls-voice__state i { font-size: 1.3rem; }
/* swap the icon/label pair between active + inactive */
.ls-voice__on-ic, .ls-voice__on-tx { display: none; }
.ls-voice.is-active .ls-voice__on-ic,
.ls-voice.is-active .ls-voice__on-tx { display: inline-flex; }
.ls-voice.is-active .ls-voice__off-ic,
.ls-voice.is-active .ls-voice__off-tx { display: none; }

/* ---- waveform ---- */
.ls-voice__wave {
  display: flex;
  align-items: center;
  gap: 2px;
  height: 3.4rem;
  width: 100%;
  color: var(--t-muted);
}
.ls-voice.is-active .ls-voice__wave { color: var(--v-accent); }
.ls-voice__bar {
  flex: 1 1 0;
  height: 100%;
  min-width: 2px;
  border-radius: 100px;
  background: currentColor;
  transform-origin: center;
  transform: scaleY(0.1);          /* inactive: near-flat baseline */
  opacity: .4;
  transition: transform .35s ease, opacity .3s ease;
}
/* active but paused: hold the static waveform silhouette */
.ls-voice.is-active .ls-voice__bar {
  transform: scaleY(var(--h, .5));
  opacity: .9;
}
/* active AND the film is rolling: dance (synthetic fallback until Web Audio is
   wired — see .is-live below) */
.ls-voices.is-playing .ls-voice.is-active .ls-voice__bar {
  animation: ls-eq .85s ease-in-out infinite alternate;
  animation-delay: calc(var(--i, 0) * -73ms);
}
@keyframes ls-eq {
  from { transform: scaleY(calc(var(--h, .5) * 0.32)); }
  to   { transform: scaleY(var(--h, .5)); }
}
/* once the live Web Audio graph is driving the active bars per-frame, drop the
   synthetic keyframe and the smoothing transition so the JS transforms are exact
   and immediate (JS does its own attack/release smoothing) */
.ls-voices.is-live .ls-voice.is-active .ls-voice__bar {
  animation: none;
  transition: opacity .2s ease;
}

@media (max-width: 620px) {
  .ls-voices { grid-template-columns: 1fr; }
  .ls-voice { padding: 1.5rem 1.6rem; gap: 1.2rem; }
  .ls-voice__sub { display: none; }
  .ls-voice__wave { height: 2.8rem; }
}

/* ---- language switcher (segmented control with sliding indicator) ---- */
.ls-langs {
  position: relative;
  display: flex;
  flex-wrap: nowrap;            /* single row — scrolls instead of orphaning a chip */
  gap: 0.4rem;
  width: fit-content;          /* hugs content when it fits, caps at the column when it doesn't */
  max-width: min(100%, var(--ls-stage-max));
  margin-top: var(--ls-gap);
  padding: 0.5rem;
  border-radius: 100px;
  border: 1px solid var(--st-muted);
  background: var(--base-tint);
  box-shadow: inset 0 0.1rem 0.2rem rgba(0,0,0,.18);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-behavior: smooth;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  -ms-overflow-style: none;
  cursor: grab;
}
.ls-langs::-webkit-scrollbar { display: none; }
.ls-langs.is-grabbing { cursor: grabbing; scroll-behavior: auto; scroll-snap-type: none; }
.ls-langs.is-grabbing .ls-lang { pointer-events: none; }

/* scroll affordance: gradient fades pinned to the rail edges (kept aligned to the
   viewport by JS as the rail scrolls), shown only when there's more to reveal */
.ls-langs__fade {
  position: absolute;
  top: 0; bottom: 0;
  width: 4.4rem;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  display: flex;
  align-items: center;
  transition: opacity .25s ease;
  will-change: transform, opacity;
}
.ls-langs__fade--l {
  left: 0;
  justify-content: flex-start;
  border-radius: 100px 0 0 100px;
  background: linear-gradient(to right, var(--base-tint) 35%, transparent);
}
.ls-langs__fade--r {
  right: 0;
  justify-content: flex-end;
  border-radius: 0 100px 100px 0;
  background: linear-gradient(to left, var(--base-tint) 35%, transparent);
}
.ls-langs__fade.is-on { opacity: 1; }
/* prominent accent chevron inside each fade — a clear "swipe for more" cue
   (matches the voice-agent scenario tabs) */
.ls-langs__fade i {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  background: var(--accent);
  color: #161616;
  font-size: 1.5rem;
  box-shadow: 0 0.3rem 1rem rgba(0, 0, 0, .4);
}
.ls-langs__fade--l i { margin-left: 0.4rem; animation: ls-nudge-l 1.6s ease-in-out infinite; }
.ls-langs__fade--r i { margin-right: 0.4rem; animation: ls-nudge-r 1.6s ease-in-out infinite; }
@keyframes ls-nudge-r { 0%,100%{ transform: translateX(0) } 50%{ transform: translateX(0.3rem) } }
@keyframes ls-nudge-l { 0%,100%{ transform: translateX(0) } 50%{ transform: translateX(-0.3rem) } }
/* the green pill that glides under the active language */
.ls-langs__indicator {
  position: absolute;
  top: 0; left: 0;
  width: var(--w, 0);
  height: var(--h, 3.8rem);
  border-radius: 100px;
  background: var(--accent);
  box-shadow: 0 0.6rem 1.6rem -0.6rem rgba(var(--accent-rgb), .65);
  transform: translate(var(--x, 0), var(--y, 0));
  transition: transform .55s cubic-bezier(.5, .05, .1, 1),
              width .55s cubic-bezier(.5, .05, .1, 1),
              height .55s cubic-bezier(.5, .05, .1, 1);
  opacity: 0;
  pointer-events: none;
  z-index: 0;
}
.ls-langs__indicator.is-ready { opacity: 1; }
.ls-langs.no-anim .ls-langs__indicator { transition: none; }
.ls-lang {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  scroll-snap-align: center;
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  height: 3.8rem;
  padding: 0 1.6rem;
  border-radius: 100px;
  border: none;
  background: transparent;
  color: var(--t-bright);
  cursor: pointer;
  font-family: var(--_font-accent);
  font-size: 1.5rem;
  font-weight: var(--fw-medium);
  transition: color .35s ease, background .25s ease;
  line-height: 1;
  animation: ls-chip-in .45s cubic-bezier(.22, 1, .36, 1) both;
  animation-delay: calc(var(--i, 0) * 45ms);
}
@keyframes ls-chip-in {
  from { opacity: 0; transform: translateY(0.7rem) scale(.96); }
  to   { opacity: 1; transform: none; }
}
.ls-lang:hover { background: rgba(var(--accent-rgb), 0.1); }
.ls-lang.is-active { color: #161616; background: transparent; }
.ls-lang.is-active:hover { background: transparent; }
.ls-lang__dot {
  width: 0.6rem; height: 0.6rem; border-radius: 50%;
  background: var(--accent);
  transition: background .35s ease;
}
.ls-lang.is-active .ls-lang__dot { background: #161616; }
.ls-lang__type {
  font-size: 1rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  opacity: .55;
}
.ls-lang.is-active .ls-lang__type { opacity: .7; }

/* ---- feature strip ---- */
.ls-features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
  gap: 1.6rem;
  margin-top: clamp(2.8rem, 4vw, 4.8rem);
}
.ls-feature {
  /* pointer position (px, relative to the card) — set by js/card-spotlight.js */
  --mx: 50%;
  --my: 0%;
  position: relative;
  overflow: hidden;
  padding: 2.6rem;
  border-radius: 2rem;
  border: 1px solid var(--st-muted);
  background: var(--base-tint);
  transition: transform .45s cubic-bezier(0.22, 1, 0.36, 1),
              border-color .45s ease,
              box-shadow .45s cubic-bezier(0.22, 1, 0.36, 1);
}
/* keep content above the spotlight layers */
.ls-feature > * { position: relative; z-index: 1; }
/* hairline border that brightens toward the cursor */
.ls-feature::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: radial-gradient(220px circle at var(--mx) var(--my),
              rgba(var(--accent-rgb), .85),
              rgba(var(--accent-rgb), .12) 45%,
              transparent 72%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity .45s ease;
  pointer-events: none;
  z-index: 0;
}
/* soft spotlight on the card surface, tracking the cursor */
.ls-feature::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(340px circle at var(--mx) var(--my),
              rgba(var(--accent-rgb), .12), transparent 60%);
  opacity: 0;
  transition: opacity .45s ease;
  pointer-events: none;
  z-index: 0;
}
.ls-feature:hover {
  transform: translateY(-4px);
  border-color: rgba(var(--accent-rgb), .3);
  box-shadow:
    0 2px 4px rgba(0, 0, 0, .18),
    0 14px 30px -10px rgba(0, 0, 0, .5),
    0 30px 64px -24px rgba(var(--accent-rgb), .22);
}
.ls-feature:hover::before,
.ls-feature:hover::after { opacity: 1; }

.ls-feature__icon {
  position: relative;
  display: block;
  color: var(--accent);
  font-size: 3.6rem;
  line-height: 1;
  margin-bottom: 1.4rem;
  transition: transform .3s ease;
}
.ls-feature:hover .ls-feature__icon {
  transform: translateY(-2px);
}
.ls-feature__num {
  position: relative;
  font-family: var(--_font-accent);
  font-size: 2.6rem;
  font-weight: var(--fw-semibold);
  color: var(--t-bright);
  line-height: 1.05;
  letter-spacing: -0.01em;
}
.ls-feature__label {
  position: relative;
  font-family: var(--_font-default);
  color: var(--t-muted);
  font-size: 1.7rem;
  font-weight: var(--fw-medium);
  margin: 0.6rem 0 0;
  line-height: 1.35;
}
.ls-feature__detail {
  position: relative;
  margin: 1.6rem 0 0;
  padding-top: 1.4rem;
  border-top: 1px solid var(--st-muted);
  color: var(--t-muted);
  font-size: 1.6rem;
  line-height: 1.45;
}
.ls-feature__more { color: var(--accent); font-weight: var(--fw-semibold); }

/* ---- Phone: proof list instead of boxed cards ----
   Four full cards stacked to ~2.5 screens on phones. Below 768px the
   set compresses into a hairline-divided list — icon in the gutter,
   figure + label reading as one line, detail beneath — matching the
   compact treatment of the services index and the stats cross. The
   spotlight layers (pointer-driven) are dropped with the boxes.
   Shared component: also styles the #software proof rail. */
@media only screen and (max-width: 767px) {
  .ls-features {
    grid-template-columns: 1fr;
    gap: 0;
    margin-top: 2.4rem;
    border-top: 1px solid var(--st-muted);
  }
  .ls-feature {
    display: grid;
    grid-template-columns: 3rem auto 1fr;
    column-gap: 1.2rem;
    align-items: baseline;
    padding: 1.6rem 0.2rem;
    border: none;
    border-bottom: 1px solid var(--st-muted);
    border-radius: 0;
    background: transparent;
    overflow: visible;
  }
  .ls-feature::before,
  .ls-feature::after {
    display: none;
  }
  .ls-feature:hover {
    transform: none;
    box-shadow: none;
  }
  .ls-feature__icon {
    grid-column: 1;
    grid-row: 1 / span 2;
    align-self: start;
    font-size: 2.4rem;
    margin: 0.2rem 0 0;
  }
  .ls-feature__num {
    grid-column: 2;
    grid-row: 1;
    font-size: 1.9rem;
    white-space: nowrap;
  }
  .ls-feature__label {
    grid-column: 3;
    grid-row: 1;
    margin: 0;
    font-size: 1.5rem;
    text-align: left;
  }
  .ls-feature__detail {
    grid-column: 2 / span 2;
    grid-row: 2;
    margin: 0.6rem 0 0;
    padding-top: 0;
    border-top: none;
    font-size: 1.35rem;
    line-height: 1.4;
    text-align: left;
  }
}

/* ---- Campaign cards: poster + link variant ----
   Same spotlight card shell, but each .ls-feature becomes an <a> to /work
   with a 16:9 scene frame up top (badge + reveal-on-hover play) and a body
   that ends in a "See the reels" affordance. Scoped so the base proof-list
   treatment (and its phone flatten) is untouched everywhere else. */
.ls-features--campaign {
  grid-template-columns: repeat(auto-fit, minmax(25rem, 1fr));
  gap: 2rem;
}
.ls-features--campaign .ls-feature {
  display: flex;
  flex-direction: column;
  padding: 0;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}
.ls-features--campaign .ls-feature__media {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #000;
}
.ls-features--campaign .ls-feature__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .7s cubic-bezier(0.22, 1, 0.36, 1);
}
.ls-features--campaign .ls-feature:hover .ls-feature__media img { transform: scale(1.06); }
.ls-features--campaign .ls-feature__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 42%, rgba(0, 0, 0, .55) 100%);
  pointer-events: none;
}
.ls-features--campaign .ls-feature__badge {
  position: absolute;
  z-index: 2;
  top: 1.2rem;
  left: 1.2rem;
  display: grid;
  place-items: center;
  width: 3.6rem;
  height: 3.6rem;
  border-radius: 1rem;
  color: var(--accent);
  font-size: 1.9rem;
  background: rgba(0, 0, 0, .5);
  border: 1px solid rgba(255, 255, 255, .14);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.ls-features--campaign .ls-feature__play {
  position: absolute;
  z-index: 2;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(.88);
  display: grid;
  place-items: center;
  width: 5.4rem;
  height: 5.4rem;
  border-radius: 50%;
  color: #000;
  font-size: 2rem;
  background: var(--accent);
  box-shadow: 0 10px 30px -8px rgba(0, 0, 0, .6);
  opacity: 0;
  transition: opacity .4s ease, transform .4s cubic-bezier(0.22, 1, 0.36, 1);
}
.ls-features--campaign .ls-feature__play i { margin-left: 2px; }
.ls-features--campaign .ls-feature:hover .ls-feature__play {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
.ls-features--campaign .ls-feature__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: 2.2rem 2.4rem 2.4rem;
}
.ls-features--campaign .ls-feature__label { margin: 0.5rem 0 0; }
.ls-features--campaign .ls-feature__detail { flex: 1; }
.ls-features--campaign .ls-feature__more {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  margin-top: 2rem;
  color: var(--accent);
  font-family: var(--_font-accent);
  font-weight: var(--fw-semibold);
  font-size: 1.5rem;
  letter-spacing: .01em;
}
.ls-features--campaign .ls-feature__more i {
  transition: transform .35s cubic-bezier(0.22, 1, 0.36, 1);
}
.ls-features--campaign .ls-feature:hover .ls-feature__more i {
  transform: translate(3px, -3px);
}
@media only screen and (max-width: 767px) {
  .ls-features--campaign {
    grid-template-columns: 1fr;
    gap: 1.6rem;
    margin-top: 2.4rem;
    border-top: none;
  }
  .ls-features--campaign .ls-feature {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    padding: 0;
    border: 1px solid var(--st-muted);
    border-radius: 2rem;
    background: var(--base-tint);
    overflow: hidden;
  }
  .ls-features--campaign .ls-feature__body { padding: 1.8rem 1.8rem 2rem; }
  .ls-features--campaign .ls-feature__play {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
    width: 4.8rem;
    height: 4.8rem;
  }
  .ls-features--campaign .ls-feature__num {
    font-size: 2rem;
    white-space: normal;
  }
  .ls-features--campaign .ls-feature__label {
    margin: .4rem 0 0;
    font-size: 1.5rem;
  }
  .ls-features--campaign .ls-feature__detail {
    margin: 1.4rem 0 0;
    padding-top: 1.4rem;
    border-top: 1px solid var(--st-muted);
    font-size: 1.45rem;
  }
  .ls-features--campaign .ls-feature__more { margin-top: 1.6rem; }
}

/* ---- Premiere ticket: the closing hand-off to the full Lipsmatch page ----
   Rebuilt as a cinema "admit one" ticket — a marquee bulb rail, a split-flap
   departures board that live-flips the film through eight scripts, and a
   punched, tear-off stub that is the prominent route home to lipsmatch.html.
   The whole card is one link; the flip board is decorative (aria-hidden). */
.ls-premiere {
  --stub-w: 25rem;
  --notch: 3rem;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: stretch;
  margin-top: clamp(2.4rem, 3.4vw, 4rem);
  border-radius: 2.6rem;
  border: 1px solid rgba(var(--accent-rgb), 0.24);
  background:
    linear-gradient(118deg, rgba(var(--accent-rgb), 0.09), rgba(var(--accent-rgb), 0) 46%),
    linear-gradient(200deg, var(--base-tint), var(--base-shade));
  text-decoration: none;
  transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1),
              border-color 0.55s ease,
              box-shadow 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}

/* marquee bulb rail across the top edge, with a slow travelling highlight */
.ls-premiere__bulbs {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1.4rem;
  pointer-events: none;
  background:
    radial-gradient(circle at 50% 45%,
      rgba(255, 255, 255, 0.55) 0 18%, transparent 55%) 0 0 / var(--dot, 2.6rem) 100%,
    radial-gradient(circle at 50% 45%,
      rgba(var(--accent-rgb), 0.45) 0 22%, transparent 58%) 0 0 / var(--dot, 2.6rem) 100%;
  background-repeat: repeat-x;
  opacity: 0.55;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.ls-premiere__bulbs::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(var(--accent-rgb), 0.9) 50%, transparent);
  -webkit-mask-image: inherit;
          mask-image: inherit;
  animation: ls-bulb-chase 5.5s linear infinite;
}
@keyframes ls-bulb-chase {
  from { transform: translateX(-40%); }
  to   { transform: translateX(140%); }
}

/* soft accent bloom anchored under the stub side */
.ls-premiere__glow {
  position: absolute;
  inset: -30% -10% -30% 40%;
  z-index: -1;
  background: radial-gradient(50% 60% at 78% 50%,
              rgba(var(--accent-rgb), 0.22), transparent 70%);
  opacity: 0.7;
  pointer-events: none;
  transition: opacity 0.6s ease, transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

.ls-premiere__main {
  flex: 1 1 auto;
  min-width: 0;
  padding: clamp(2.8rem, 3.4vw, 4rem) clamp(2.6rem, 3.2vw, 4rem);
}
.ls-premiere__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  font-family: var(--_font-accent);
  font-size: 1.25rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: var(--accent);
  margin-bottom: 1.1rem;
}
.ls-premiere__eyebrow i { font-size: 1.6rem; }
.ls-premiere__head {
  display: block;
  font-family: var(--_font-accent);
  font-size: clamp(2.4rem, 2.8vw, 3.6rem);
  line-height: 1.12;
  font-weight: var(--fw-medium);
  color: var(--t-bright);
  letter-spacing: -0.01em;
}
.ls-premiere__head em {
  font-family: 'Playfair Display', serif;
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
}

/* split-flap departures board */
.ls-premiere__board {
  display: flex;
  align-items: center;
  gap: 1.6rem;
  margin-top: 1.8rem;
  padding: 1.2rem 1.6rem;
  border-radius: 1.4rem;
  border: 1px solid rgba(var(--accent-rgb), 0.3);
  /* a real split-flap board is black in any room — pin it to the permanent
     dark token so the light theme doesn't wash it to a muddy grey */
  background: var(--pt-base-dark);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06),
              0 6px 20px -10px rgba(0, 0, 0, 0.4);
  width: fit-content;
  max-width: 100%;
}
.ls-premiere__board-label {
  font-family: var(--_font-accent);
  font-size: 1.15rem;
  line-height: 1.25;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  /* permanent light ink — the plate stays dark in both themes */
  color: rgba(255, 255, 255, 0.5);
  white-space: nowrap;
}
.ls-premiere__flip {
  --lh: 1.4em;
  display: block;
  height: var(--lh);
  overflow: hidden;
  font-family: var(--_font-accent);
  font-size: clamp(2.2rem, 2.6vw, 3.2rem);
  font-weight: var(--fw-semibold);
  line-height: var(--lh);
  color: var(--accent);
  text-shadow: 0 0 24px rgba(var(--accent-rgb), 0.35);
}
.ls-premiere__flip-track {
  display: flex;
  flex-direction: column;
  will-change: transform;
  animation: ls-flip 18s cubic-bezier(0.76, 0, 0.16, 1) infinite;
}
.ls-premiere__word {
  height: var(--lh);
  line-height: var(--lh);
  white-space: nowrap;
}
@keyframes ls-flip {
  0%,      9%   { transform: translateY(calc(var(--lh) *  0)); }
  12.5%, 21.5%  { transform: translateY(calc(var(--lh) * -1)); }
  25%,    34%   { transform: translateY(calc(var(--lh) * -2)); }
  37.5%, 46.5%  { transform: translateY(calc(var(--lh) * -3)); }
  50%,    59%   { transform: translateY(calc(var(--lh) * -4)); }
  62.5%, 71.5%  { transform: translateY(calc(var(--lh) * -5)); }
  75%,    84%   { transform: translateY(calc(var(--lh) * -6)); }
  87.5%, 96.5%  { transform: translateY(calc(var(--lh) * -7)); }
  100%          { transform: translateY(calc(var(--lh) * -8)); }
}

.ls-premiere__sub {
  display: block;
  margin-top: 1.8rem;
  font-size: clamp(1.4rem, 1.15vw, 1.6rem);
  line-height: 1.6;
  color: var(--t-muted);
  max-width: 54ch;
}
.ls-premiere__sub em {
  font-style: normal;
  font-weight: var(--fw-semibold);
  color: var(--t-bright);
}

/* ---- the tear-off stub ---- */
.ls-premiere__stub {
  position: relative;
  flex: 0 0 var(--stub-w);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.4rem clamp(2rem, 2vw, 2.8rem);
  border-left: 2px dashed rgba(var(--accent-rgb), 0.4);
  background:
    linear-gradient(180deg, rgba(var(--accent-rgb), 0.1), rgba(var(--accent-rgb), 0.03));
  transition: background 0.5s ease;
}
/* punched notches where the perforation meets the card edges */
.ls-premiere__stub::before,
.ls-premiere__stub::after {
  content: "";
  position: absolute;
  left: 0;
  width: var(--notch);
  height: var(--notch);
  border-radius: 50%;
  background: var(--base);
  transform: translate(-50%, -50%);
}
.ls-premiere__stub::before { top: 0; }
.ls-premiere__stub::after  { top: 100%; }

/* vertical "ADMIT ONE" label riding the perforation */
.ls-premiere__stub-edge {
  position: absolute;
  left: 1.4rem;
  top: 50%;
  transform: translateY(-50%);
  writing-mode: vertical-rl;
  font-family: var(--_font-accent);
  font-size: 1.1rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: rgba(var(--accent-rgb), 0.55);
  white-space: nowrap;
}
.ls-premiere__stub-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.4rem;
  text-align: center;
}
.ls-premiere__stub-icon {
  display: grid;
  place-items: center;
  width: 5.6rem;
  height: 5.6rem;
  border-radius: 50%;
  background: var(--accent);
  color: #0a0d08;
  font-size: 2.2rem;
  box-shadow: 0 8px 24px -8px rgba(var(--accent-rgb), 0.6);
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.ls-premiere__stub-icon i { transition: transform 0.45s cubic-bezier(0.5, 0, 0, 1); }
.ls-premiere__stub-cta {
  font-family: var(--_font-accent);
  font-size: 1.55rem;
  font-weight: var(--fw-semibold);
  letter-spacing: 0.01em;
  color: var(--t-bright);
  white-space: nowrap;
}

/* hover / focus */
.no-touch .ls-premiere:hover {
  transform: translateY(-4px);
  border-color: rgba(var(--accent-rgb), 0.5);
  box-shadow:
    0 2px 4px rgba(0, 0, 0, 0.18),
    0 18px 40px -14px rgba(0, 0, 0, 0.55),
    0 44px 90px -32px rgba(var(--accent-rgb), 0.32);
}
.no-touch .ls-premiere:hover .ls-premiere__glow { opacity: 1; }
.no-touch .ls-premiere:hover .ls-premiere__stub { background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.16), rgba(var(--accent-rgb), 0.05)); }
.no-touch .ls-premiere:hover .ls-premiere__stub-icon { transform: scale(1.07); }
.no-touch .ls-premiere:hover .ls-premiere__stub-icon i { transform: translateX(3px); }
.ls-premiere:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

/* ---- how-it-works process ---- */
.ls-process { margin-top: clamp(3.2rem, 5vw, 6rem); }
.ls-process__eyebrow {
  font-family: var(--_font-accent);
  font-size: 1.3rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: var(--fw-semibold);
  margin: 0 0 1.8rem;
}
.ls-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(26rem, 1fr));
  gap: 1.6rem;
}
.ls-step {
  position: relative;
  padding: 2.8rem 2.4rem;
  border-radius: 1.8rem;
  border: 1px solid var(--st-muted);
  background: var(--base-tint);
}
.ls-step__num {
  font-family: var(--_font-accent);
  font-size: 1.8rem;
  font-weight: var(--fw-semibold);
  color: var(--accent);
  letter-spacing: .02em;
}
.ls-step__title {
  font-family: var(--_font-accent);
  font-size: 2.2rem;
  font-weight: var(--fw-medium);
  color: var(--t-bright);
  margin: 1rem 0 1.2rem;
  line-height: 1.15;
}
.ls-step__text {
  color: var(--t-muted);
  font-size: 1.55rem;
  line-height: 1.55;
  margin: 0;
}

/* ---- responsive ---- */
@media (max-width: 767px) {
  /* tighter brand clusters so more of the rail is visible before scrolling */
  .ls-cases { gap: 1rem; }
  .ls-case-group { padding: 0.9rem 0.9rem 1rem; gap: 0.8rem; border-radius: 1.4rem; }
  .ls-case-group__mono { width: 2.4rem; height: 2.4rem; font-size: 1.1rem; }
  .ls-case-group__name { font-size: 1.35rem; }
  .ls-case-tab { padding: 0.8rem 1.2rem; }
  .ls-case-tab__name { font-size: 1.4rem; }
  .ls-tag { font-size: 1.05rem; padding: 0.6rem 1rem; top: 1.2rem; left: 1.2rem; }
  .ls-ab { max-width: 100%; width: 100%; }
  .ls-ab__btn { padding: 0 1.2rem; font-size: 1.45rem; }
  /* compact pill on phones — trim the duration so the seek line keeps room */
  .ls-stage__controls { gap: 0.4rem; padding: 0.5rem 0.8rem 0.5rem 0.5rem; }
  .ls-ctrl { width: 3.4rem; height: 3.4rem; font-size: 1.5rem; }
  .ls-time { min-width: 0; }
  .ls-time__sep, .ls-time__dur { display: none; }
  .ls-vol { gap: 0; }
  .ls-stage__play { width: 6rem; height: 6rem; font-size: 2.4rem; }

  /* Premiere ticket stacks: the stub becomes a bottom tear-off with a
     horizontal perforation and notches punched into the side edges. */
  .ls-premiere {
    flex-direction: column;
    border-radius: 1.8rem;
  }
  .ls-premiere__glow { inset: -20% -20% -10% -20%;
    background: radial-gradient(70% 50% at 50% 92%,
              rgba(var(--accent-rgb), 0.22), transparent 72%); }
  .ls-premiere__board { gap: 1.2rem; }
  .ls-premiere__stub {
    flex: 0 0 auto;
    border-left: 0;
    border-top: 2px dashed rgba(var(--accent-rgb), 0.4);
    padding: 2.2rem 2rem;
  }
  .ls-premiere__stub::before  { left: 0;    top: 0; }
  .ls-premiere__stub::after   { left: 100%; top: 0; }
  .ls-premiere__stub-edge { display: none; }
  /* label + arrow read as ONE centered tap target — spreading them across
     the row made the stub look like a swipe-to-unlock slider */
  .ls-premiere__stub-inner {
    flex-direction: row;
    gap: 1.4rem;
    width: 100%;
    justify-content: center;
  }
  .ls-premiere__stub-cta { order: 1; font-size: 1.7rem; }
  .ls-premiere__stub-icon { order: 2; width: 4.4rem; height: 4.4rem; font-size: 1.9rem; }
}

@media (prefers-reduced-motion: reduce) {
  .ls-premiere, .ls-premiere__glow, .ls-premiere__stub-icon, .ls-premiere__stub-icon i {
    transition: none;
  }
  .ls-premiere__flip-track, .ls-premiere__bulbs::after { animation: none; }
  /* freeze the board on the first language rather than mid-flip */
  .ls-premiere__flip-track { transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .ls-eyebrow::before, .ls-spinner { animation: none; }
  .ls-g, .ls-ctrl, .ls-stage__play, .ls-seek__track, .ls-seek__thumb,
  .ls-vol__slider, .ls-stage__controls { transition: none; }
  .ls-case-tab, .ls-lang, .ls-case-group, .ls-case-group__mono { transition: none; }
  .ls-cases__nav.is-on i { animation: none; }
  .ls-lang, .ls-caption__text.ls-anim { animation: none; }
  .ls-langs__indicator { transition: none; }
  .ls-langs__fade i { animation: none; }
  .ls-stage video { transition: none; }
  .ls-cases, .ls-langs { scroll-behavior: auto; }
  /* hold the static waveform silhouette rather than animating it */
  .ls-voices.is-playing .ls-voice.is-active .ls-voice__bar { animation: none; }
  .ls-voice { transition: none; }
}

/* ============================================================
   Case-study comparison hero (shared across the lip-sync work
   pages: bourbon, goodday, golmaal, nutrichoice).
   An editorial two-column band — full-height text panel on the
   left, the interactive player filling its column on the right.
   Only markup carrying .ie-compare-hero is affected; no other
   page uses this class. Per-page copy (heading/lead/meta and the
   picker descriptor text) lives in each page. Vertical-rhythm
   tightening rides on .ie-case-compact (added to those pages'
   <main>) so the generous default project spacing doesn't leave
   dead bands between sections.
   ============================================================ */
.ie-compare-hero__grid {
  display: flex;
  align-items: stretch;              /* both columns share the player's height */
  gap: clamp(3rem, 4.5vw, 6.4rem);
  max-width: 154rem;
  margin: 0 auto;
}
.ie-compare-hero__intro {
  flex: 0 1 40rem;
  margin-bottom: 0;
  display: flex;
  flex-direction: column;            /* heading top, foot pinned to the bottom */
}
.ie-compare-hero__intro .mxd-project__subtitle { max-width: 13ch; }
.ie-compare-hero__foot {
  margin-top: auto;                  /* anchor supporting copy to the column base */
  padding-top: clamp(3.2rem, 4vw, 5rem);
}
.ie-compare-hero__lead {
  margin: 0;
  max-width: 40ch;
  color: var(--t-muted);
  font-size: clamp(1.6rem, 1.3vw, 1.8rem);
  line-height: 1.6;
}
.ie-compare-hero__lead strong { color: var(--t-bright); font-weight: var(--fw-semibold); }
.ie-compare-hero__meta {
  margin: clamp(2rem, 2.6vw, 2.8rem) 0 0;
  padding-top: clamp(1.6rem, 2vw, 2.2rem);
  border-top: 1px solid var(--st-muted);
  font: normal var(--fw-medium) 1.2rem/1.4 var(--_font-default);
  letter-spacing: 0.16rem;
  text-transform: uppercase;
  color: var(--t-muted);
}
.ie-compare-hero__stage {
  flex: 1 1 auto;
  min-width: 0;                      /* let the flex child shrink; no overflow */
  display: flex;
  align-items: center;               /* centre the player against the tall panel */
}
.ie-compare-hero__stage .ls-showcase { width: 100%; }
/* let the video fill its column instead of capping at 880px and floating */
.ie-compare-hero .ls-showcase { --ls-stage-max: 100%; }
/* expand the duration picker into a full-width control bar of even segments */
.ie-compare-hero .ls-cases--single-group { justify-content: stretch; }
.ie-compare-hero .ls-cases { margin-bottom: 1.6rem; padding-top: 0.2rem; }
.ie-compare-hero .ls-case-group { flex: 1 1 auto; width: 100%; }
.ie-compare-hero .ls-case-group__pills { gap: 0.8rem; }
.ie-compare-hero .ls-case-tab {
  flex: 1 1 0;
  align-items: center;
  text-align: center;
  padding-top: 1.15rem;
  padding-bottom: 1.15rem;
}
/* delivery-spec descriptor that fills the widened picker header; the copy is set
   per page (content: ...) — this only carries the shared styling + divider */
.ie-compare-hero .ls-case-group__name::after {
  content: none;
  margin-left: 1.2rem;
  padding-left: 1.2rem;
  border-left: 1px solid var(--st-muted);
  font: normal 400 1.3rem/1 var(--_font-default);
  letter-spacing: 0.01em;
  color: var(--t-muted);
}

/* tightened section rhythm for the case-study pages (opt-in via <main>) */
.ie-case-compact .mxd-project__block:not(.no-margin) {
  margin-top: clamp(4.5rem, 7vw, 8rem);
  margin-bottom: clamp(4.5rem, 7vw, 8rem);
}
.ie-case-compact .mxd-project__block.pre-grid:not(.no-margin) {
  margin-bottom: clamp(4rem, 6vw, 7rem);
}

@media (max-width: 991px) {
  .ie-compare-hero__grid {
    flex-direction: column;
    align-items: stretch;
    gap: clamp(2.4rem, 5vw, 3.6rem);
  }
  .ie-compare-hero__intro { flex: none; }
  .ie-compare-hero__intro .mxd-project__subtitle { max-width: 18ch; }
  .ie-compare-hero__foot { padding-top: clamp(2rem, 5vw, 2.8rem); }
  .ie-compare-hero__stage { display: block; }
  .ie-compare-hero .ls-case-group__name::after { display: none; }
}
