/* ============================================================
   02 — PROOF · stats band + platform marquee
   Connective band directly under the hero, sits on --bg.
   Stats are a <dl>; the marquee rail bleeds past the container.
   ============================================================ */

.proof {
  position: relative;
  /* A connective band, so it sits tighter than the page rhythm — but as an
     offset of --section-y, not a fixed step, so the gap grows with the page
     and never snaps at a breakpoint. Same shape as 10-cta (+ --s-12) and
     11-footer (- --s-6). */
  padding-block: calc(var(--section-y) - var(--s-8));
}

/* ---------- Stats row ----------
   Zero gap everywhere. Separation is done with symmetric padding on the
   cells, so every hairline sits exactly in the middle of its gutter and
   the vertical/horizontal rules meet on the shared grid lines.          */

.proof__stats {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}

.proof__stat {
  min-width: 0;
  /* dt (label) is first in the DOM for the value/label pair to read
     correctly; explicit row placement puts the number on top. Rows are
     subgridded at 640px+ so every value shares one row and every label
     shares the next — a 2-line label can't push its number up. */
  display: grid;
  grid-template-rows: auto auto;
  padding-block: var(--s-6);
}

.proof__stat:first-child { padding-block-start: 0; }
.proof__stat:last-child { padding-block-end: 0; }
/* --border-strong, not --border: these hairlines carry the whole structure
   and stand alone (no card, no shadow behind them) — 0.09 alpha vanishes. */
.proof__stat + .proof__stat { border-top: 1px solid var(--border-strong); }

/* Schibsted Grotesk's tnum feature widens the separators too, not just the
   figures: at --fs-h2 the comma and the period both go to a full 31px figure
   advance, so "120,000+" and "99.9%" render as "120 , 000+" / "99 . 9%".
   Text stays proportional; tabular width is bought back only where it earns
   its keep — see .proof__figs. */
.proof__value {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  font-variant-numeric: proportional-nums;
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-display);
  white-space: nowrap;
  color: var(--text);
}

/* Digit runs of the counting stat only. Equal advances keep the trailing
   digits still while the leading ones churn ("1" is ~3px narrower than the
   other figures here); the separators sit outside the span, so they keep
   their natural width. The grid is 1fr with min-width:0 on the cell, so the
   columns are content-independent — nothing outside the number can shift. */
.proof__figs { font-variant-numeric: tabular-nums; }

.proof__label {
  margin-top: var(--s-3);
  max-width: 26ch;
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
  color: var(--text-muted);
}

@media (min-width: 640px) {
  .proof__stats { grid-template-columns: repeat(2, 1fr); }

  .proof__stat,
  .proof__stat:first-child,
  .proof__stat:last-child { padding: var(--s-6); }

  /* Outer edges flush to the container; inner edges padded symmetrically. */
  .proof__stat:nth-child(-n + 2) { padding-block-start: 0; }
  .proof__stat:nth-child(n + 3) { padding-block-end: 0; }
  .proof__stat:nth-child(odd) { padding-inline-start: 0; }
  .proof__stat:nth-child(even) { padding-inline-end: 0; }

  .proof__stat + .proof__stat { border-top: 0; }
  .proof__stat:nth-child(n + 3) { border-top: 1px solid var(--border-strong); }
  .proof__stat:nth-child(even) { border-inline-start: 1px solid var(--border-strong); }
}

/* 4-up only once a column fits the longest figure with real slack. Measured,
   not guessed: Schibsted Grotesk Bold sets every tabular glyph at 0.6348em,
   so "120,000+" is 8 advances = 5.078em, less 0.035em/char of tracking =
   4.798em → 250px at the 52px --fs-h2 cap. On --maxw-wide at 1280 the first
   cell is 276px. Below that the 2x2 keeps the numbers off the hairlines. */
@media (min-width: 1280px) {
  .proof__stats { grid-template-columns: repeat(4, 1fr); }

  .proof__stat,
  .proof__stat:nth-child(-n + 2),
  .proof__stat:nth-child(n + 3) {
    padding-block: 0;
    padding-inline: var(--s-6);
    border-top: 0;
    border-inline-start: 1px solid var(--border-strong);
  }
  .proof__stat:first-child {
    padding-inline-start: 0;
    border-inline-start: 0;
  }
  .proof__stat:last-child { padding-inline-end: 0; }
}

/* ---------- Marquee ---------- */

.proof__marquee {
  margin-top: var(--s-12);
  padding-top: var(--s-10);
  /* One step down from the stat rules: this divider separates blocks, it
     doesn't build a grid. */
  border-top: 1px solid var(--border);
}

@media (min-width: 768px) {
  .proof__marquee { margin-top: var(--s-16); padding-top: var(--s-12); }
}

.proof__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
}

/* Shared .eyebrow carries size/weight/tracking/colour — the accent here is
   the band's single colour anchor; everything else stays typographic. */
.proof__kicker { line-height: var(--lh-normal); }

/* The marquee's stop control (WCAG 2.2.2). Quiet enough not to compete with
   the kicker, 44px tall so it is a real touch target; the negative block
   margin keeps the head row the kicker's own height. */
.proof__pause {
  display: inline-flex;
  align-items: center;
  min-height: calc(var(--s-10) + var(--s-1));
  margin-block: calc(var(--s-3) * -1);
  padding-inline: var(--s-4);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  line-height: 1;
  color: var(--text-muted);
  transition: color var(--dur) var(--ease-out), background-color var(--dur) var(--ease-out);
}

.proof__pause:hover { color: var(--text); background: var(--surface-2); }

/* Pressed = the rail is held. Label names the function, colour carries state. */
.proof__pause[aria-pressed="true"] { color: var(--accent); background: var(--accent-soft); }

.proof__sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* Full-bleed: only the scrolling rail escapes the container, so the row
   reads as the page continuing past the text column. body has
   overflow-x: hidden, which absorbs the classic-scrollbar 100vw overhang. */
.proof__viewport {
  margin-block-start: var(--s-6);
  margin-inline: calc(50% - 50vw);
  overflow: hidden;
  /* Proportional fade: 20px at 320 (row stays readable on a phone),
     ~86px at 1440 (reads as depth, not a cut). A fixed value is wrong at
     one end or the other. Mask uses alpha only — var(--text) is an opaque
     stop. */
  --proof-fade: clamp(var(--s-5), 6vw, var(--s-24));
  -webkit-mask-image: linear-gradient(
    to right,
    transparent 0,
    var(--text) var(--proof-fade),
    var(--text) calc(100% - var(--proof-fade)),
    transparent 100%
  );
  mask-image: linear-gradient(
    to right,
    transparent 0,
    var(--text) var(--proof-fade),
    var(--text) calc(100% - var(--proof-fade)),
    transparent 100%
  );
}

.proof__rail {
  display: flex;
  width: max-content;
  /* Three identical sets, so one set only has to exceed half the viewport.
     ~20s per set ≈ 75px/s: readable movement, not a treadmill. */
  animation: proof-marquee calc(var(--dur-slower) * 24) linear infinite;
  will-change: transform;
}

/* Pause when off-screen (main.js toggles .is-paused), when the user presses
   the button (.is-held), or when the pointer is on the moving strip.
   No :focus-within rule: nothing inside the viewport is focusable, so it
   could never fire — the button is the keyboard path. */
.proof__marquee.is-paused .proof__rail,
.proof__marquee.is-held .proof__rail,
.proof__viewport:hover .proof__rail {
  animation-play-state: paused;
}

@keyframes proof-marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-33.3333%, 0, 0); }
}

.proof__set {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--s-10);
  /* Leading pad on every set: keeps inter-set spacing equal to the intra-set
     gap (so the loop stays exact) and starts the first item clear of the
     left fade at rest. */
  padding-inline-start: var(--s-10);
}

.proof__item {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  flex: 0 0 auto;
  white-space: nowrap;
  /* --ink-400 (--text-subtle) is 3.92:1 on --bg — under the 4.5:1 floor for
     17px semibold, which is not "large" text. --ink-500 (--text-muted) is
     6.81:1; the row stays recessive through size and weight instead. */
  color: var(--text-muted);
  transition: color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}

/* The rail is already paused under :hover — the per-item lift is what makes
   that pause read as "you're in control" rather than "it broke". */
.proof__viewport:hover .proof__item:hover {
  color: var(--text);
  transform: translateY(-2px);
}

.proof__glyph {
  width: var(--s-6);
  height: var(--s-6);
  flex: 0 0 auto;
}

.proof__name {
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-normal);
  line-height: 1;
}

/* ---------- Reduced motion: static, wrapped, inside the container ---------- */

@media (prefers-reduced-motion: reduce) {
  /* Nothing moves here, so a stop control would be a dead button. */
  .proof__pause { display: none; }

  .proof__viewport {
    margin-inline: 0;
    overflow: visible;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .proof__rail {
    width: auto;
    animation: none;
    will-change: auto;
  }
  .proof__set {
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: wrap;
    row-gap: var(--s-5);
    padding-inline-start: 0;
  }
  .proof__set--clone { display: none; }
}
