/* ============================================================
   JARA Voxbridge — CINEMATIC POLISH LAYER  (voxbridge.html ONLY)
   ------------------------------------------------------------
   Loaded AFTER styles.css. This file never rewrites the page's
   premium language — it adds a depth/light layer on top of it.

   Three hard rules baked into every rule below:
   1) ZERO layout impact. Every new visual is either a pseudo-
      element or an absolutely-positioned decoration, so nothing
      here can move a box → CLS stays 0.
   2) Transform / opacity only. No animated width, height, top,
      left, box-shadow or filter (one-shot filters are fine, but
      nothing filtered is animated) → compositor-friendly 60fps.
   3) prefers-reduced-motion: reduce turns EVERY new animation
      and transition off and freezes each effect on a single,
      still-legible frame (see the block at the bottom).

   Colour discipline: everything reads the live theme tokens
   (--t-accent* / --t-border / --t-bg-*), so the layer recolors
   with the product accent and with light/dark. The only literal
   is JARA gold #E7C887 / rgb(231,200,135), used exactly where
   the brand crest is intended (progress line, CTA sweep, seams).

   Driver: voxbridge-cinema.js (GSAP + ScrollTrigger from vendor/).
   Everything degrades to a static, complete page without it.
   CSP: self-contained, no external URL of any kind.
   ============================================================ */

/* ---------- 0. Shared keyframes ---------- */
@keyframes voxSpin      { to { rotate: 360deg; } }
@keyframes voxAurora {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(12%, 5%, 0) scale(1.13); }
  100% { transform: translate3d(31%, -4%, 0) scale(1.02); }
}
@keyframes voxDrift {
  0%   { opacity: 0;   transform: translate3d(0, 30px, 0) scale(.90); }
  16%  { opacity: .95; transform: translate3d(0, 6px, 0)  scale(1); }
  68%  { opacity: .85; transform: translate3d(0, -28px, 0) scale(1); }
  100% { opacity: 0;   transform: translate3d(0, -64px, 0) scale(.94); }
}
@keyframes voxSheen {
  0%   { opacity: 0; transform: translate3d(-120%, 0, 0); }
  14%  { opacity: 1; }
  100% { opacity: 0; transform: translate3d(120%, 0, 0); }
}
@keyframes voxShine {
  0%, 62%   { background-position: 165% 0; }
  93%, 100% { background-position: -70% 0; }
}
@keyframes voxWaveBreathe {
  0%   { transform: translate3d(-2%, 0, 0) scale(1.02); }
  100% { transform: translate3d(2%, -10px, 0) scale(1.07); }
}

/* ---------- 1. Gold scroll-progress hairline ----------
   Fixed, 2px, above the sticky nav. JS writes scaleX only. */
.vox-progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  height: 2px;
  z-index: 60;
  pointer-events: none;
  transform: scaleX(0);
  transform-origin: 0 50%;
  will-change: transform;
  opacity: .92;
  background: linear-gradient(90deg,
    rgba(var(--t-accent-rgb), 0) 0%,
    rgba(var(--t-accent-rgb), .60) 24%,
    rgba(231, 200, 135, .95) 66%,
    #E7C887 100%);
}
[dir="rtl"] .vox-progress { transform-origin: 100% 50%; }

/* ---------- 2. Nav gains contrast once the page starts moving ---------- */
.glass-nav {
  transition: backdrop-filter .45s ease, -webkit-backdrop-filter .45s ease,
              box-shadow .45s ease, border-color .45s ease;
}
body.vox-scrolled .nav { border-color: rgba(var(--t-accent-bright-rgb), .30); }
body.vox-scrolled .glass-nav {
  -webkit-backdrop-filter: blur(30px) saturate(1.3);
  backdrop-filter: blur(30px) saturate(1.3);
  box-shadow: 0 24px 74px var(--t-shadow-deep),
              inset 0 1px 0 rgba(var(--t-accent-bright-rgb), .16);
}

/* ---------- 3. HERO ---------- */
/* 3a. Headline word-stagger. GSAP owns opacity/transform on .vox-w
   ONLY — never on the <h1> itself, which cinematic.js §2b already
   scrubs. inline-block keeps normal line wrapping, so no CLS. */
.detail-hero h1 .vox-w { display: inline-block; will-change: transform, opacity; }

/* 3b. Very slow aurora drift behind the hero copy.
   .detail-hero already has position:relative + isolation:isolate +
   overflow:clip and only uses ::before, so ::after is free and the
   drift can never bleed into page-level horizontal scroll. */
.detail-hero::after {
  content: "";
  position: absolute;
  z-index: -1;
  pointer-events: none;
  left: -12%;
  top: -16%;
  width: 62%;
  aspect-ratio: 1.45;
  border-radius: 50%;
  background: radial-gradient(closest-side,
    rgba(var(--t-accent-rgb), .17),
    rgba(var(--t-accent-rgb), .05) 55%,
    transparent 78%);
  will-change: transform;
  animation: voxAurora 36s ease-in-out infinite alternate;
}

/* 3c. Light sweep circling the lamp. Ring is mask-carved, so it is
   only rendered where masking actually works — a UA without mask
   support gets no element at all instead of a filled disc. */
.detail-hero__visual { position: relative; isolation: isolate; }
@supports ((-webkit-mask-image: radial-gradient(#000, #000)) or (mask-image: radial-gradient(#000, #000))) {
  /* Anchored to .giant-icon, not to the column: the lamp plate is a square
     760x760 PNG, so a circle sized off the icon's own box orbits it cleanly at
     any breakpoint. Sized off the column instead, the ring came out SMALLER
     than the lamp and cut straight through it. */
  .giant-icon::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 116%;
    aspect-ratio: 1;
    translate: -50% -50%;          /* kept OFF `transform` so the sweep can own rotate */
    border-radius: 50%;
    z-index: -1;
    pointer-events: none;
    background: conic-gradient(from 0deg,
      rgba(var(--t-accent-bright-rgb), 0)   0deg,
      rgba(var(--t-accent-bright-rgb), .55) 40deg,
      rgba(231, 200, 135, .78)              66deg,
      rgba(var(--t-accent-bright-rgb), 0)  126deg,
      rgba(var(--t-accent-bright-rgb), 0)  360deg);
    -webkit-mask: radial-gradient(closest-side, transparent 70%, #000 74%, #000 79%, transparent 83%);
            mask: radial-gradient(closest-side, transparent 70%, #000 74%, #000 79%, transparent 83%);
    will-change: transform;
    animation: voxSpin 11s linear infinite;
    opacity: .85;
  }
}

/* 3d. Shimmer across the Allura "voxbridge" accent. The overlay is a
   second copy of the word, gradient-clipped to the glyphs, so the
   base colour is untouched. It inherits the handwrite clip-path, so
   it only becomes visible once the pen finishes writing. */
.detail-lockup .script-label__text { position: relative; }
.detail-lockup .script-label__text::after {
  content: "voxbridge";            /* product name — never translated (data-text is hardcoded too) */
  position: absolute;
  inset: 0;
  white-space: nowrap;
  pointer-events: none;
  background-image: linear-gradient(100deg,
    transparent 40%,
    rgba(255, 255, 255, .92) 48%,
    #E7C887 54%,
    transparent 64%);
  background-size: 250% 100%;
  background-position: 165% 0;
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  animation: voxShine 6.5s ease-in-out 2.6s infinite;
}
/* The overlay PAINTS the glyphs, it does not add light to them — so a white
   highlight on the light theme would blank the word out for the length of the
   sweep. Light gets a darker sweep instead: same gesture, still legible. */
[data-theme="light"] .detail-lockup .script-label__text::after {
  background-image: linear-gradient(100deg,
    transparent 40%,
    rgba(var(--t-accent-rgb), .95) 48%,
    #b8924c 54%,
    transparent 64%);
}

/* ---------- 4. Section seams ----------
   A hairline of light stitches each scene to the next; it draws
   itself open as the section arrives. Decorative only — nothing
   readable is ever gated behind it. */
.detail-section::before,
.detail-final::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(90deg,
    transparent,
    rgba(var(--t-accent-bright-rgb), .30) 34%,
    rgba(231, 200, 135, .26) 52%,
    transparent);
  opacity: 0;
  transform: scaleX(.35);
  transition: opacity .9s ease, transform 1.25s cubic-bezier(.2, .8, .25, 1);
}
.detail-section.vox-seam::before,
.detail-final.vox-seam::after { opacity: 1; transform: scaleX(1); }

/* ---------- 5. LIVE DEMO — the spotlight scene ---------- */
#live-demo { isolation: isolate; }
/* Named children only. `#live-demo > *` would win on specificity (1,0,0) over
   .vox-scene's own position:absolute (0,1,0) and force the decor layer back
   into flow — where, with only absolute children, it collapses to height 0 and
   its overflow:hidden clips every chip out of existence. */
#live-demo > .detail-heading,
#live-demo > .vox-demo-stage { position: relative; z-index: 1; }

.vox-scene {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

/* 5a. Slowly rotating conic aurora on the section floor.
   No filter: the conic's own soft stops plus the radial mask do the
   blurring, so rotating it costs one composited layer, not a
   full-surface blur repaint every frame. */
@supports ((-webkit-mask-image: radial-gradient(#000, #000)) or (mask-image: radial-gradient(#000, #000))) {
  .vox-scene__conic {
    position: absolute;
    left: 50%;
    top: 54%;
    width: min(150%, 1240px);
    aspect-ratio: 1;
    translate: -50% -50%;
    border-radius: 50%;
    /* Single-hue ramp on purpose. An accent→gold conic has to interpolate
       across the whole hue wheel between stops, and on this page (blue accent)
       the in-between angles land on a muddy teal. Depth here comes from alpha,
       not from a second hue; gold stays reserved for the crest moments. */
    background: conic-gradient(from 0deg,
      rgba(var(--t-accent-rgb), .18),
      rgba(var(--t-accent-bright-rgb), .09) 92deg,
      rgba(var(--t-accent-rgb), .18) 184deg,
      rgba(var(--t-accent-bright-rgb), .06) 276deg,
      rgba(var(--t-accent-rgb), .18) 360deg);
    -webkit-mask: radial-gradient(closest-side, #000 10%, rgba(0, 0, 0, .5) 46%, transparent 74%);
            mask: radial-gradient(closest-side, #000 10%, rgba(0, 0, 0, .5) 46%, transparent 74%);
    will-change: transform;
    animation: voxSpin 52s linear infinite;
  }
}

/* 5b. Language chips drifting up the gutters — the conference story,
   told in pure CSS. Gutters only exist on wide viewports, so below
   1180px they are removed entirely (never overlap the phone). */
.vox-chip {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .16em;
  white-space: nowrap;
  color: var(--t-accent-ink);
  border: 1px solid rgba(var(--t-accent-rgb), .30);
  background: linear-gradient(180deg, var(--t-bg-glass-1), var(--t-bg-glass-2));
  box-shadow: 0 10px 26px rgba(0, 0, 0, .22);
  opacity: 0;
  will-change: transform, opacity;
  animation: voxDrift 18s ease-in-out infinite;
}
.vox-chip b { font-size: 14px; letter-spacing: 0; font-weight: 400; }
.vox-chip:nth-child(1) { left: 3%;  top: 62%; animation-delay: 0s; }
.vox-chip:nth-child(2) { left: 8%;  top: 34%; animation-delay: 3.4s; }
.vox-chip:nth-child(3) { left: 1.5%;top: 16%; animation-delay: 8.6s; }
.vox-chip:nth-child(4) { right: 3%; top: 58%; animation-delay: 1.7s; }
.vox-chip:nth-child(5) { right: 7%; top: 30%; animation-delay: 6.1s; }
.vox-chip:nth-child(6) { right: 2%; top: 13%; animation-delay: 11.2s; }
@media (max-width: 1179px) { .vox-chip { display: none; } }

/* 5c. Phone frame bloom. A separate radial layer behind the frame,
   so the "glow" is an opacity/scale tween on its own compositor
   layer instead of a per-frame box-shadow repaint on a 900px card. */
.vox-demo-stage { position: relative; max-width: 900px; margin: 0 auto; will-change: transform; }
.vox-demo-bloom {
  position: absolute;
  inset: -13%;
  z-index: 0;
  border-radius: 40px;
  pointer-events: none;
  background: radial-gradient(58% 52% at 50% 50%,
    rgba(var(--t-accent-rgb), .34),
    rgba(var(--t-accent-rgb), .11) 48%,
    transparent 74%);
  opacity: 0;
  will-change: opacity, transform;
}
.vox-demo-stage .demo-frame { position: relative; z-index: 1; }

/* Placeholder shown until the 760KB demo document is mounted, so the
   frame is never an empty black rectangle. It OVERLAYS the iframe
   instead of replacing it: the <iframe> keeps its full box from the
   first paint, so (a) nothing shifts when the src lands and (b) the
   demo's own fitPhone() measures a real viewport on its load. */
.demo-frame__wait {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-items: center;
  background: #050608;
  color: var(--t-text-faded);
  font-size: 12px;
  letter-spacing: .3em;
  text-transform: uppercase;
}
.demo-frame__wait i {
  display: block;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid rgba(var(--t-accent-bright-rgb), .5);
  border-top-color: transparent;
  animation: voxSpin 1.1s linear infinite;
}
.demo-frame.is-mounted .demo-frame__wait { display: none; }

/* ---------- 6. CAPABILITIES ---------- */
/* 6a. Specular glare that tracks the pointer. Deliberately NOT a 3D
   tilt: cinematic.js §2c pins #capabilities and drives .cap-mock's
   transform (xPercent/scale) from a scrubbed timeline, so any
   transform written here would be overwritten mid-scrub. A masked
   highlight + an inner-layer parallax give the same "solid object
   catching light" read without ever touching GSAP's channel. */
.cap-mock { --vx-gx: 50%; --vx-gy: 0%; }
.cap-mock::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(34% 34% at var(--vx-gx) var(--vx-gy),
    rgba(255, 255, 255, .17),
    rgba(var(--t-accent-bright-rgb), .11) 44%,
    transparent 72%);
  opacity: 0;
  transition: opacity .45s ease;
}
.cap-mock.vox-glare::after { opacity: 1; }
/* Inner layer lags the pointer → parallax depth inside the card. */
.cap-mock__screen {
  transform: translate3d(var(--vx-px, 0px), var(--vx-py, 0px), 0);
  transition: transform .35s cubic-bezier(.2, .8, .25, 1);
}

/* 6b. Real captured footage inside the mock. The clips are portrait
   phone recordings (620x1276), so they are inset as a device rather
   than stretched across a 4:3 card. The device sits on the TRAILING
   edge and the leading side carries a live vignette (§6c) — centred,
   the phone left two dead columns of empty card, which is exactly what
   read as "an empty panel".

   The 38% reserve is derived, not guessed: film width / screen width =
   0.486·(H-59) / (1.333H-32), which stays between .32 and .34 at every
   card height, because both terms scale with the same H and the card
   ratio is locked at 4/3. 38% = the film plus a gutter. */
.cap-mock--film .cap-mock__screen { position: relative; }
.cap-mock--film .cap-vig { padding-inline-end: 38%; }
.cap-mock__film {
  position: absolute;
  inset-inline-end: 0;
  top: 50%;
  translate: 0 -50%;
  height: 100%;
  aspect-ratio: 620 / 1276;
  z-index: 1;
  border-radius: 18px;
  object-fit: cover;
  background: #05070c;
  border: 1px solid rgba(var(--t-accent-bright-rgb), .38);
  box-shadow: 0 24px 54px rgba(0, 0, 0, .48), 0 0 0 5px rgba(0, 0, 0, .34);
}

/* ---------- 6c. THE FOUR PANELS, ALIVE ----------
   Each capability panel now performs the thing it claims. All four are
   pure CSS on top of the existing .cap-mock chrome — no JS, no assets,
   no new i18n keys (the only text is language endonyms, one fixed EN→TR
   translation sample, and a timestamp).

   ONE RULE governs every vignette: the element's BASE style is the
   FINISHED frame, and the keyframes reach back to the empty state at 0%.
   So `animation: none` (reduced motion) leaves a complete, legible panel
   instead of a blank one — with no separate still-frame styling to keep
   in sync. */
.cap-vig {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
}

/* Off-screen scenes idle. Between them these panels run ~70 infinite
   animations; left running while the visitor is three screens away they
   burn frame budget for nothing (and on a constrained renderer that
   showed up as dropped frames). The polarity matters: the default is
   RUNNING and JS adds .vox-idle when a section leaves the viewport — so
   with JS off nothing is ever paused mid-keyframe, and the panels still
   play. animation-play-state only suspends the clock; it never resets a
   position, so returning to the section resumes exactly where it was. */
#capabilities.vox-idle .cap-vig *,
#capabilities.vox-idle .cap-vig *::before,
#capabilities.vox-idle .cap-vig *::after,
#live-demo.vox-idle .vox-chip,
#live-demo.vox-idle .vox-scene__conic,
.detail-final.vox-idle::before,
.detail-final.vox-idle .vox-final-wave { animation-play-state: paused; }

/* --- 6c-1 · Capability 01: the caption writing itself --- */
.cap-vig--caption {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(8px, 3%, 16px);
}
.cv-line { display: flex; align-items: flex-start; gap: 9px; min-width: 0; }
.cv-tag {
  flex: 0 0 auto;
  margin-block-start: 2px;
  padding: 3px 8px;
  border-radius: 7px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .14em;
  color: var(--t-accent-ink);
  border: 1px solid var(--t-border);
  background: rgba(var(--t-accent-rgb), .08);
}
.cv-line--tgt .cv-tag {
  color: #E7C887;
  border-color: rgba(231, 200, 135, .45);
  background: rgba(231, 200, 135, .10);
}
.cv-words { display: flex; flex-wrap: wrap; gap: 3px 6px; min-width: 0; }
.cv-words i {
  display: inline-block;
  font-style: normal;
  font-size: clamp(11px, 1.05vw, 15px);
  line-height: 1.4;
  white-space: nowrap;
  color: var(--t-text-soft);
  animation: voxCapWord 9s ease-out infinite;
}
.cv-line--tgt .cv-words i { color: var(--t-text); }
.cv-line--src .cv-words i:nth-child(1) { animation-delay: .15s; }
.cv-line--src .cv-words i:nth-child(2) { animation-delay: .50s; }
.cv-line--src .cv-words i:nth-child(3) { animation-delay: .85s; }
.cv-line--src .cv-words i:nth-child(4) { animation-delay: 1.2s; }
.cv-line--tgt .cv-words i:nth-child(1) { animation-delay: 3.1s; }
.cv-line--tgt .cv-words i:nth-child(2) { animation-delay: 3.5s; }
@keyframes voxCapWord {
  0%, 3%    { opacity: 0; transform: translateY(5px); }
  8%, 88%   { opacity: 1; transform: none; }
  95%, 100% { opacity: 0; transform: none; }
}
.cv-bridge {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 26px;
}
.cv-bridge b {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  font-size: 12px;
  font-weight: 400;
  color: var(--t-accent-bright);
  border: 1px solid rgba(var(--t-accent-bright-rgb), .5);
  background: rgba(var(--t-accent-rgb), .10);
  animation: voxBridgePulse 9s ease-in-out infinite;
}
.cv-beam {
  position: absolute;
  left: 50%;
  top: 62%;
  width: 1px;
  height: 44%;
  translate: -50% 0;
  transform: scaleY(0);
  transform-origin: 50% 0;
  opacity: 0;
  background: linear-gradient(180deg, rgba(var(--t-accent-bright-rgb), .9), rgba(231, 200, 135, 0));
  animation: voxBeam 9s ease-out infinite;
}
@keyframes voxBridgePulse {
  0%, 24%   { box-shadow: 0 0 0 0 rgba(var(--t-accent-bright-rgb), 0); }
  30%       { box-shadow: 0 0 0 7px rgba(var(--t-accent-bright-rgb), .16); }
  38%, 100% { box-shadow: 0 0 0 0 rgba(var(--t-accent-bright-rgb), 0); }
}
@keyframes voxBeam {
  0%, 26%   { opacity: 0; transform: scaleY(0); }
  30%       { opacity: 1; transform: scaleY(1); }
  40%       { opacity: 0; transform: scaleY(1); }
  41%, 100% { opacity: 0; transform: scaleY(0); }
}

/* --- 6c-2 · Capability 02: the living language constellation --- */
.cap-vig--constel {
  /* Radius tracks BOTH axes: in the pinned stage the card is sized off
     viewport height, in the stacked fallback off width. min() of the two
     keeps the orbit inside the card in either regime. */
  --cv-ro: clamp(70px, min(12.5vw, 16.5vh), 148px);
  --cv-ri: calc(var(--cv-ro) * .58);
}
.cv-core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--cv-ro) * .42);
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(var(--t-accent-bright-rgb), .85),
    rgba(var(--t-accent-rgb), .30) 54%,
    transparent 74%);
}
.cv-core i {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid rgba(var(--t-accent-bright-rgb), .55);
  opacity: 0;
  animation: voxCorePing 3.4s ease-out infinite;
}
.cv-core i:nth-child(2) { animation-delay: 1.7s; }
@keyframes voxCorePing {
  0%   { opacity: .65; transform: scale(1); }
  100% { opacity: 0;   transform: scale(2.7); }
}
.cv-ring { position: absolute; inset: 0; pointer-events: none; will-change: transform; }
.cv-ring--out { animation: voxSpin 46s linear infinite; }
.cv-ring--in  { animation: voxSpinRev 36s linear infinite; }
@keyframes voxSpinRev { to { rotate: -360deg; } }
/* Placement: rotate to the chip's angle, then push out along the local
   -Y axis. That leaves local +Y pointing straight back at the core,
   which is the axis the ::before beam rides on. */
.cv-chip {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%) rotate(var(--a, 0deg)) translateY(calc(-1 * var(--r)));
}
.cv-ring--out .cv-chip { --r: var(--cv-ro); }
.cv-ring--in  .cv-chip { --r: var(--cv-ri); }
/* The label cancels BOTH rotations: `transform` undoes the chip's own
   angle, the independent `rotate` property undoes the ring's spin (equal
   duration + linear timing, so it cancels exactly, frame for frame). */
.cv-chip i {
  display: inline-block;
  padding: 4px 9px;
  border-radius: 999px;
  font-style: normal;
  font-size: clamp(8px, .72vw, 11px);
  font-weight: 600;
  letter-spacing: .02em;
  white-space: nowrap;
  color: var(--t-accent-ink);
  border: 1px solid rgba(var(--t-accent-rgb), .30);
  background: linear-gradient(180deg, var(--t-bg-glass-1), var(--t-bg-glass-2));
  box-shadow: 0 6px 16px rgba(0, 0, 0, .20);
  transform: rotate(calc(-1 * var(--a, 0deg)));
  /* Allura and the display face are Latin-only — CJK / Arabic / Devanagari
     / Vietnamese fall back to the system stack, same as the hero rotator. */
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.cv-ring--out .cv-chip i { animation: voxSpinRev 46s linear infinite; }
.cv-ring--in  .cv-chip i { animation: voxSpin 36s linear infinite; }
.cv-chip::before {                      /* beam back to the core */
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1px;
  height: calc(var(--r) - 16px);
  translate: -50% 0;
  opacity: 0;
  background: linear-gradient(180deg, rgba(var(--t-accent-bright-rgb), .8), rgba(var(--t-accent-bright-rgb), 0));
  animation: voxChipBeam 11s ease-out infinite;
}
.cv-chip::after {                       /* the chip lighting up */
  content: "";
  position: absolute;
  inset: -7px;
  border-radius: 999px;
  opacity: 0;
  background: radial-gradient(circle, rgba(var(--t-accent-bright-rgb), .40), transparent 70%);
  animation: voxChipLit 11s ease-in-out infinite;
}
.cv-chip::before, .cv-chip::after { animation-delay: var(--d, 0s); }
@keyframes voxChipLit  { 0%, 88%, 100% { opacity: 0; } 94% { opacity: 1; } }
@keyframes voxChipBeam { 0%, 90%, 100% { opacity: 0; } 95% { opacity: .9; } }
/* angle + light-up phase, one rule per chip */
.cv-ring--out .cv-chip:nth-child(1) { --a:   0deg; --d: 0.0s; }
.cv-ring--out .cv-chip:nth-child(2) { --a:  45deg; --d: 1.3s; }
.cv-ring--out .cv-chip:nth-child(3) { --a:  90deg; --d: 2.6s; }
.cv-ring--out .cv-chip:nth-child(4) { --a: 135deg; --d: 3.9s; }
.cv-ring--out .cv-chip:nth-child(5) { --a: 180deg; --d: 5.2s; }
.cv-ring--out .cv-chip:nth-child(6) { --a: 225deg; --d: 6.5s; }
.cv-ring--out .cv-chip:nth-child(7) { --a: 270deg; --d: 7.8s; }
.cv-ring--out .cv-chip:nth-child(8) { --a: 315deg; --d: 9.1s; }
.cv-ring--in  .cv-chip:nth-child(1) { --a:  30deg; --d: 0.7s; }
.cv-ring--in  .cv-chip:nth-child(2) { --a:  90deg; --d: 2.0s; }
.cv-ring--in  .cv-chip:nth-child(3) { --a: 150deg; --d: 3.3s; }
.cv-ring--in  .cv-chip:nth-child(4) { --a: 210deg; --d: 4.6s; }
.cv-ring--in  .cv-chip:nth-child(5) { --a: 270deg; --d: 5.9s; }
.cv-ring--in  .cv-chip:nth-child(6) { --a: 330deg; --d: 7.2s; }

/* --- 6c-3 · Capability 03: the turn passing between speakers --- */
.cap-vig--speakers {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(10px, 4%, 20px);
}
.cv-track {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  animation: voxTurn 7s ease-in-out infinite;
}
.cv-track--b { animation-delay: -3.5s; }
@keyframes voxTurn { 0%, 42% { opacity: 1; } 52%, 92% { opacity: .32; } 100% { opacity: 1; } }
.cv-who {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  font-size: 11px;
  font-weight: 600;
  color: var(--t-text);
  border: 1px solid rgba(var(--t-accent-bright-rgb), .65);
  background: rgba(var(--t-accent-rgb), .26);
  animation: voxWho 7s ease-in-out infinite;
}
.cv-track--b .cv-who { animation-delay: -3.5s; }
@keyframes voxWho {
  0%, 42%  { border-color: rgba(var(--t-accent-bright-rgb), .65); background: rgba(var(--t-accent-rgb), .26); }
  52%, 92% { border-color: var(--t-border);                       background: rgba(var(--t-accent-rgb), .05); }
  100%     { border-color: rgba(var(--t-accent-bright-rgb), .65); background: rgba(var(--t-accent-rgb), .26); }
}
.cv-bars { display: flex; align-items: center; gap: 3px; flex: 1; min-width: 0; height: clamp(26px, 9%, 40px); }
.cv-bars i {
  flex: 1 1 0;
  min-width: 2px;
  max-width: 5px;
  height: 100%;
  border-radius: 2px;
  transform-origin: 50% 50%;
  background: rgba(var(--t-accent-bright-rgb), .55);
  animation: voxBar 1.05s ease-in-out infinite alternate;
}
.cv-track--b .cv-bars i { background: rgba(var(--t-accent-rgb), .42); animation-duration: 1.27s; }
@keyframes voxBar { from { transform: scaleY(.22); } to { transform: scaleY(1); } }
.cv-bars i:nth-child(1)  { transform: scaleY(.34); animation-delay: -.90s; }
.cv-bars i:nth-child(2)  { transform: scaleY(.82); animation-delay: -.20s; }
.cv-bars i:nth-child(3)  { transform: scaleY(.55); animation-delay: -.65s; }
.cv-bars i:nth-child(4)  { transform: scaleY(1);   animation-delay: -.05s; }
.cv-bars i:nth-child(5)  { transform: scaleY(.62); animation-delay: -.45s; }
.cv-bars i:nth-child(6)  { transform: scaleY(.88); animation-delay: -.80s; }
.cv-bars i:nth-child(7)  { transform: scaleY(.41); animation-delay: -.30s; }
.cv-bars i:nth-child(8)  { transform: scaleY(.74); animation-delay: -.95s; }
.cv-bars i:nth-child(9)  { transform: scaleY(.50); animation-delay: -.55s; }
.cv-bars i:nth-child(10) { transform: scaleY(.93); animation-delay: -.15s; }
.cv-bars i:nth-child(11) { transform: scaleY(.38); animation-delay: -.72s; }
.cv-bars i:nth-child(12) { transform: scaleY(.66); animation-delay: -.38s; }

/* --- 6c-4 · Capability 04: the summary writing itself --- */
.cap-vig--summary { display: grid; place-items: center; --cv-dx: -14px; }
[dir="rtl"] .cap-vig--summary { --cv-dx: 14px; }
.cv-doc {
  display: flex;
  flex-direction: column;
  gap: clamp(7px, 2.6%, 13px);
  width: min(100%, 320px);
  padding: clamp(12px, 4%, 20px);
  border-radius: 16px;
  border: 1px solid var(--t-border);
  background: linear-gradient(180deg, var(--t-bg-card-1), var(--t-bg-card-2));
  box-shadow: 0 18px 40px rgba(0, 0, 0, .28), inset 0 1px 0 rgba(255, 255, 255, .04);
  animation: voxDocIn 11s ease-out infinite;
}
@keyframes voxDocIn {
  0%, 2%    { opacity: 0; transform: translateY(8px); }
  8%, 90%   { opacity: 1; transform: none; }
  97%, 100% { opacity: 0; transform: none; }
}
.cv-title { display: flex; align-items: center; gap: 4px; height: 11px; }
.cv-title i {
  display: block;
  width: 64%;
  height: 11px;
  border-radius: 6px;
  background: linear-gradient(90deg, rgba(231, 200, 135, .9), rgba(var(--t-accent-bright-rgb), .55));
  animation: voxType 11s steps(14, end) infinite;
}
@keyframes voxType { 0%, 4% { width: 0; } 22%, 88% { width: 64%; } 95%, 100% { width: 0; } }
.cv-caret {
  display: block;
  width: 2px;
  height: 11px;
  background: #E7C887;
  opacity: 0;
  animation: voxCaret 11s steps(1, end) infinite;
}
@keyframes voxCaret {
  0%, 3% { opacity: 0; } 5% { opacity: 1; } 8% { opacity: 0; }
  11% { opacity: 1; } 14% { opacity: 0; } 17% { opacity: 1; }
  22%, 100% { opacity: 0; }
}
.cv-item { display: flex; align-items: center; gap: 8px; animation: voxItemIn 11s ease-out infinite; }
.cv-doc > .cv-item:nth-child(3) { animation-delay: .5s; }
.cv-doc > .cv-item:nth-child(4) { animation-delay: 1s; }
@keyframes voxItemIn {
  0%, 24%   { opacity: 0; transform: translateX(var(--cv-dx)); }
  31%, 88%  { opacity: 1; transform: none; }
  95%, 100% { opacity: 0; transform: none; }
}
.cv-item i {
  display: block;
  flex: 1;
  height: 8px;
  border-radius: 5px;
  background: rgba(var(--t-accent-rgb), .18);
}
.cv-doc > .cv-item:nth-child(3) i { max-width: 84%; }
.cv-doc > .cv-item:nth-child(4) i { max-width: 62%; }
.cv-check { display: grid; place-items: center; flex: 0 0 auto; width: 14px; height: 14px; }
.cv-check svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: #E7C887;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 15;
  stroke-dashoffset: 0;
  animation: voxDraw 11s ease-out infinite;
}
.cv-doc > .cv-item:nth-child(3) .cv-check svg { animation-delay: .5s; }
@keyframes voxDraw { 0%, 28% { stroke-dashoffset: 15; } 36%, 88% { stroke-dashoffset: 0; } 95%, 100% { stroke-dashoffset: 15; } }
.cv-dot {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  margin: 0 2px;
  border-radius: 50%;
  border: 1px solid rgba(var(--t-accent-bright-rgb), .55);
}
.cv-stamp {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-block-start: 2px;
  animation: voxItemIn 11s ease-out infinite;
  animation-delay: 1.4s;
}
.cv-stamp em {
  font-style: normal;
  padding: 3px 7px;
  border-radius: 6px;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .08em;
  color: #E7C887;
  border: 1px solid rgba(231, 200, 135, .42);
  background: rgba(231, 200, 135, .10);
  animation: voxStampLit 11s ease-in-out infinite;
}
.cv-stamp i { display: block; flex: 0 0 42%; height: 8px; border-radius: 5px; background: rgba(var(--t-accent-rgb), .18); }
@keyframes voxStampLit {
  0%, 46%   { box-shadow: 0 0 0 0 rgba(231, 200, 135, 0); }
  54%       { box-shadow: 0 0 15px 2px rgba(231, 200, 135, .45); }
  64%, 100% { box-shadow: 0 0 0 0 rgba(231, 200, 135, 0); }
}

/* A narrow card cannot hold a vignette AND a phone side by side. Below
   this width the film returns to centre — exactly how it shipped before
   §6c — and the vignette steps aside rather than being squeezed. */
@media (max-width: 720px) {
  .cap-mock--film .cap-vig { display: none; }
  .cap-mock--film .cap-mock__film { inset-inline-end: auto; left: 50%; translate: -50% -50%; }
}

/* ---------- 7. PROOF BAND — one-shot sheen as the stats arrive ---------- */
.proof-stat { overflow: hidden; }
.proof-stat::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(105deg,
    transparent 32%,
    rgba(var(--t-accent-bright-rgb), .22) 46%,
    rgba(231, 200, 135, .28) 52%,
    transparent 68%);
  opacity: 0;
  transform: translate3d(-120%, 0, 0);
}
.proof-stat.vox-sheen::after { animation: voxSheen 1.3s cubic-bezier(.2, .7, .2, 1) forwards; }

/* ---------- 8. FINAL CTA — the closing shot ---------- */
.detail-final { position: relative; isolation: isolate; }

/* 8a. Slow conic halo behind the card (z-index:-1 sits above the
   section background but below .detail-final-inner). */
@supports ((-webkit-mask-image: radial-gradient(#000, #000)) or (mask-image: radial-gradient(#000, #000))) {
  .detail-final::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: min(112%, 1080px);
    aspect-ratio: 1.55;
    translate: -50% -50%;
    z-index: -1;
    border-radius: 50%;
    pointer-events: none;
    /* Gold IS coherent here — it echoes the gold CTA at the centre of the card —
       so the ramp keeps it, but only against --t-accent-bright, whose hue sits
       close enough that the interpolation never crosses into teal. */
    background: conic-gradient(from 0deg,
      rgba(var(--t-accent-bright-rgb), .20),
      rgba(231, 200, 135, .16) 100deg,
      rgba(var(--t-accent-bright-rgb), .20) 200deg,
      rgba(231, 200, 135, .11) 300deg,
      rgba(var(--t-accent-bright-rgb), .20) 360deg);
    -webkit-mask: radial-gradient(closest-side, #000 16%, rgba(0, 0, 0, .45) 54%, transparent 76%);
            mask: radial-gradient(closest-side, #000 16%, rgba(0, 0, 0, .45) 54%, transparent 76%);
    will-change: transform;
    animation: voxSpin 44s linear infinite;
  }
}

/* 8b. The captured waveform, mounted lazily by JS (see the .js file
   for the gating). It is a blue-on-black plate, so `screen` drops
   the black; on light themes it would only wash out, so it is not
   rendered there at all. */
.vox-final-wave {
  position: absolute;
  left: 50%;
  bottom: -6%;
  width: min(148%, 1500px);
  translate: -50% 0;
  z-index: -1;
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: screen;
  transition: opacity 1.4s ease;
  will-change: transform;
  animation: voxWaveBreathe 28s ease-in-out infinite alternate;
  /* Feathered on all four edges so the plate reads as ambient depth rather than
     a pasted rectangle — without it the section boundary sliced the wave crests
     off with a hard horizontal edge. Unsupported UAs just get the plain plate. */
  -webkit-mask: linear-gradient(180deg, transparent 0%, #000 34%, #000 76%, transparent 100%),
                linear-gradient(90deg, transparent 0%, #000 16%, #000 84%, transparent 100%);
          mask: linear-gradient(180deg, transparent 0%, #000 34%, #000 76%, transparent 100%),
                linear-gradient(90deg, transparent 0%, #000 16%, #000 84%, transparent 100%);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}
.vox-final-wave.vox-in { opacity: .20; }
[data-theme="light"] .vox-final-wave { display: none; }

/* 8c. Gold light sweep across the closing CTA. z-index:-1 under
   isolation lands it above the button's own gradient and below its
   label, so the text never dims. */
.detail-final .primary-cta { position: relative; overflow: hidden; isolation: isolate; }
.detail-final .primary-cta::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(105deg,
    transparent 34%,
    rgba(255, 255, 255, .55) 47%,
    rgba(231, 200, 135, .95) 54%,
    transparent 70%);
  opacity: 0;
  transform: translate3d(-130%, 0, 0);
}
.detail-final .primary-cta:hover::after,
.detail-final .primary-cta:focus-visible::after { animation: voxSheen .9s cubic-bezier(.25, .7, .2, 1); }

/* ---------- 9. Mobile trims ---------- */
@media (max-width: 900px) {
  .detail-hero::after { width: 92%; }
  .vox-demo-bloom { inset: -8%; }
  .giant-icon::after { width: 118%; }
}

/* ---------- 10. prefers-reduced-motion: everything above freezes ----------
   Each effect keeps a single, deliberately chosen still frame; the
   progress line and the drifting chips (which only exist as motion)
   are removed outright. Nothing that carries meaning is hidden. */
@media (prefers-reduced-motion: reduce) {
  .vox-progress,
  .vox-chip { display: none !important; }

  .detail-hero::after,
  .giant-icon::after,
  .detail-lockup .script-label__text::after,
  .vox-scene__conic,
  .detail-final::before,
  .vox-final-wave,
  .demo-frame__wait i,
  .proof-stat.vox-sheen::after,
  .detail-final .primary-cta:hover::after,
  .detail-final .primary-cta:focus-visible::after { animation: none !important; }

  .detail-lockup .script-label__text::after,
  .proof-stat::after,
  .detail-final .primary-cta::after { display: none !important; }

  .glass-nav,
  .detail-section::before,
  .detail-final::after,
  .cap-mock::after,
  .cap-mock__screen,
  .vox-final-wave { transition: none !important; }

  .detail-section::before,
  .detail-final::after { opacity: 1; transform: none; }
  /* A frozen spinner would read as a broken ring — close the circle instead. */
  .demo-frame__wait i { border-top-color: rgba(var(--t-accent-bright-rgb), .5); }

  /* §6c panels. Because every vignette's BASE style is already the
     finished frame, switching the animations off is all that is needed:
     the caption stays written, the constellation stays lit and readable,
     both speaker tracks stay visible, and the summary card keeps its
     typed title, its drawn ticks and its timestamp. */
  .cv-words i,
  .cv-bridge b,
  .cv-beam,
  .cv-core i,
  .cv-ring--out,
  .cv-ring--in,
  .cv-ring--out .cv-chip i,
  .cv-ring--in .cv-chip i,
  .cv-chip::before,
  .cv-chip::after,
  .cv-track,
  .cv-who,
  .cv-bars i,
  .cv-doc,
  .cv-title i,
  .cv-caret,
  .cv-item,
  .cv-check svg,
  .cv-stamp,
  .cv-stamp em { animation: none !important; }
  /* The beam and the caret exist only as motion — nothing to freeze. */
  .cv-beam,
  .cv-caret { display: none !important; }
  .cap-mock__screen { transform: none !important; }
  .vox-demo-bloom { opacity: .5; transform: none !important; }
  .vox-scene__conic { opacity: .55; }
}
