/* Media presentation layer: full-bleed video bands, the stats backdrop and
   the curtain reveal shared by both. Motion here is scroll-triggered but not
   scroll-driven — JS toggles one class, CSS transitions do the rest, so the
   compositor owns every frame and the scroll thread stays free. */

/* ---------- curtain reveal (video bands + [data-media-reveal]) ---------- */

/* The settle scales past the media box, so the crop has to happen one level
   up. .showcase was position:relative only; the band is full-bleed anyway. */
.showcase { overflow: hidden; }

/* Enters slightly over-scaled and clipped inward, then eases open. The two
   durations are deliberately unequal: the wipe lands first and the scale
   keeps easing under it, so the media settles instead of stopping.
   Repeatable in both directions — js/media.js toggles .is-media-in the same
   way motion.js toggles .is-in. */
.showcase--video .showcase__media,
[data-media-reveal] {
  clip-path: inset(12%);
  transform: scale(1.08);
  transform-origin: 50% 50%;
  transition: clip-path 1.2s var(--ease), transform 1.4s var(--ease);
}

.showcase--video .showcase__media.is-media-in,
[data-media-reveal].is-media-in {
  clip-path: inset(0%);
  transform: scale(1);
}

/* The scale lives on .showcase__media, never on the <img> — motion.js owns
   the img's transform (translate3d with --parallax) and the two would
   overwrite each other on the same property. Nesting composes them instead. */

/* ---------- video bands ---------- */

/* Black under the video covers the gap before the poster decodes and the
   letterbox edges if a source's aspect ever drifts from the band's. */
.showcase--video .showcase__media { background: var(--black); }

.showcase__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* .showcase__media::before already fades the top/bottom edges into the page.
   This adds the centre falloff: video is busier than a still, and the band
   has to read as one continuous black page rather than an inserted panel. */
.showcase--video .showcase__media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    radial-gradient(ellipse 120% 90% at 50% 50%, transparent 30%, rgba(13, 13, 13, .55) 100%),
    linear-gradient(to bottom, rgba(13, 13, 13, .35), rgba(13, 13, 13, .15) 45%, rgba(13, 13, 13, .5));
  pointer-events: none;
}

.showcase__caption {
  position: absolute;
  z-index: 2;
  inset: auto 0 0 0;
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding: 0 max(var(--container-pad), 5vw) var(--sp-small);
  font-family: var(--font-secondary);
  font-size: var(--p2);
  line-height: var(--lh-l);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .12em;
}

/* The caption is optional in the markup; an empty <p> would still eat clicks
   and reserve its padding box. */
.showcase__caption:empty { display: none; }

/* ---------- stats band ---------- */

.stats {
  position: relative;
  overflow: hidden;
  padding-block: var(--sp-large);
  background: var(--black);
}

.stats__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* .35 is the ceiling that still leaves the numbers above 4.5:1 once the
   scrim below is applied — measured against a pure-white pixel of the
   globe, which is the worst case. Don't raise it without rechecking. */
.stats__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .35;
}

.stats__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 90% 70% at 50% 50%, rgba(13, 13, 13, .55), var(--black) 74%),
    linear-gradient(to bottom, var(--black), transparent 18%, transparent 82%, var(--black));
}

.stats__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-small);
}

.stat {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-top: 24px;
  border-top: 1px solid var(--white-100);
}

/* Display sizes read too loose at default tracking, hence the negative
   letter-spacing. tabular-nums keeps the counter from reflowing its
   neighbours on every rAF tick as digit widths change. */
.stat__num {
  font-family: var(--font-body);
  font-weight: var(--w-semibold);
  font-size: clamp(40px, 1.8rem + 4.4vw, 104px);
  line-height: var(--lh-s);
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  color: var(--white);
}

/* Small text takes positive tracking — the inverse of the heading above. */
.stat__label {
  font-family: var(--font-secondary);
  font-size: var(--p2);
  line-height: var(--lh-l);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .12em;
}

@media (max-width: 767px) {
  .stats__grid { grid-template-columns: 1fr; gap: 32px; }
}

/* ---------- client logo strip ---------- */

/* Fast in, slow out: the hover responds immediately, the release settles.
   grayscale() is a no-op against the current currentColor SVGs but keeps the
   strip consistent if a full-colour logo is ever dropped in. */
.logo-strip img {
  filter: invert(1) grayscale(1);
  opacity: .5;
  transition: opacity .9s var(--ease), filter .9s var(--ease);
}

.logo-strip img:hover {
  filter: invert(1) grayscale(0);
  opacity: 1;
  transition-duration: var(--dur-fast);
}

@media (prefers-reduced-motion: reduce) {
  .showcase--video .showcase__media,
  [data-media-reveal],
  .logo-strip img {
    clip-path: none !important;
    transform: none !important;
    transition: none !important;
  }
}
