/* =============================================================
   UNREAL SITE — shared foundations
   ─────────────────────────────────────────────────────────────
   THE SYSTEM CONTRACT (documented here because this file ships
   with the bundle; the DS tokens it consumes live in _ds/tokens).

   TYPE ROLES        display-1/2/3 · h2/h3 (u-h*) · body-lg/body/
                     body-sm (u-body*) · caption 13 · eyebrow 12 ·
                     micro 11 · note 14 — every size is a token
                     below; no literal font-size may be added.
   SPACING           the 14-step --space-* scale; section rhythm
                     --section-y / --section-y-lg; component gaps
                     in steps, never invented values.
   CONTAINERS        shell 1440 (heroes, full-bleed media) ·
                     content 1200 (everything argued) ·
                     narrative 832 (prose) — settled in Phase 3.
   GRID              declared spans on the documented ladder:
                     479 / 767 / 1023 / 1279 (+ lg–xl band).
   LINES             the 4-step --line-* scale only; no ad-hoc
                     border alphas.
   RADIUS            xs 2 · sm 4 · md 6 · lg 10 · pill · circle —
                     from tokens, and sparingly: this brand is
                     hairlines and skews, not rounded cards.
   ELEVATION         exactly three: --elev-card (raised card),
                     --elev-doc (the physical-document artifacts),
                     --elev-float (badges/overlays). Nothing else
                     casts a shadow.
   ICONS             stroke icons: 24 viewBox, 1.6 stroke, in a
                     19px box (see .social-btn). Glyph icons (↗ +)
                     come from the type system at label size.
                     Never mix a third style.
   MOTION            durations/easings from --dur-* / --ease-*;
                     choreography delays are literal by design.
                     Feedback (progress, form swap) runs under
                     reduced-motion; decoration never does.
   STATES            every interactive surface defines default /
                     hover / focus-visible / active / disabled;
                     buttons add is-loading; fields add
                     aria-invalid + .field-error.
   ACCENT            --data-accent marks DATA AND STATE ONLY —
                     never chrome. One accent, everywhere.
   ============================================================= */

/* ---- Token bridge: UMGFINAL's deliberate divergences from the DS defaults are
   expressed AS the tokens, so there is one source of truth. (site.css previously
   re-declared the display classes with literal clamps, which silently made
   token-level responsive overrides inert — the Phase-1 320px fix hit exactly that.) */
:root {
  --fs-display-1: clamp(2.75rem, 6.4vw, 6rem);
  /* Section headings keep the type they had before the 2 Sep refinement
     pass (Dan, 2 Sep 2026): the pre-pass display-2/3 scale. */
  --fs-display-2: clamp(2rem, 4.2vw, 3.5rem);
  --fs-display-3: clamp(1.75rem, 3.2vw, 2.5rem);
  /* two sizes the DS scale lacks, named so they stop being "random numbers" */
  --fs-note: 0.875rem; /* 14px — footer blurb, dense annotations, u-body-sm */
  --fs-h3: 1.5rem; /* site fixes the DS's fluid h3 at its midpoint */
  --fs-metric-md: 1.75rem; /* the metric scale is its own family, not headings */
  --fs-metric-sm: 1.25rem;
  --fs-lf-heading: clamp(1.375rem, 1.8vw, 1.75rem); /* lead-form heading */
  /* the three elevations — the only shadows on the site */
  --elev-card: inset 0 1px 0 rgba(255, 255, 255, 0.09), 0 12px 30px -18px rgba(0, 0, 0, 0.8);
  --elev-doc: 0 32px 64px -44px rgba(0, 0, 0, 0.55), 0 2px 0 var(--line-1);
  --elev-float: 0 20px 42px -20px rgba(0, 0, 0, 0.9);
}

/* ---- Data accent: the ONE non-monochrome token.
   Licensed for data + state only: chart strokes/markers, live-test
   progress fills, range-slider thumb, prediction-outcome rail.
   Forbidden on chrome (nav, buttons, links, borders, focus, selection). */
:root {
  /* layout tokens (spec B.1.4) */
  --container-shell: 90rem;
  --container-content: 75rem;
  --container-narrative: 52rem;
  --measure-body: 65ch;
  --measure-aside: 45ch;
  /* breakpoints (reference — media queries repeat the raw px):
     sm 480 · md 768 · lg 1024 · xl 1280 · 2xl 1440 */
}

/* ---- Base ---- */
html {
  scroll-behavior: smooth;
}
body {
  margin: 0;
  background: var(--surface-canvas);
  color: var(--text-primary);
  font-family: var(--font-body);
}
a {
  color: var(--text-primary);
  text-decoration: none;
  transition: color var(--dur-base, var(--dur-base)) var(--ease-out, ease);
}
a:hover {
  color: var(--ink-999);
}
[data-theme="light"] a:hover {
  color: var(--ink-000);
}
::selection {
  background: var(--ink-999);
  color: var(--ink-000);
}
[data-theme="light"] ::selection {
  background: var(--ink-000);
  color: var(--ink-999);
}
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-xs);
}

/* ---- Containers ---- */
.u-container {
  max-width: var(--container-shell, 90rem);
  margin-inline: auto;
  padding-inline: clamp(20px, 4vw, 56px);
}
.u-container--content {
  max-width: var(--container-content, 75rem);
  margin-inline: auto;
  padding-inline: clamp(20px, 4vw, 56px);
}
.u-container--md {
  max-width: var(--container-narrative, 52rem);
  margin-inline: auto;
  padding-inline: clamp(20px, 4vw, 56px);
}
.u-measure {
  max-width: var(--measure-body, 65ch);
}
.u-measure-sm {
  max-width: var(--measure-aside, 45ch);
}

/* ---- Numerals ---- */
.u-tabular,
.u-mono {
  font-variant-numeric: tabular-nums;
}

/* =============================================================
   TYPE SCALE — §B.2. 17 roles. No px font sizes outside this block.
   Casing law: display = uppercase; headings/card titles = sentence
   case; eyebrows/buttons/mono labels = uppercase.
   ============================================================= */
/* Display — Saira, uppercase */
.u-display-1 {
  font-family: var(--font-display);
  font-size: var(--fs-display-1);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 0.94;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0;
}
.u-display-2 {
  font-family: var(--font-display);
  font-size: var(--fs-display-2);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 0.98;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0;
}
.u-display-3 {
  /* Section headings keep the type they had before the 2 Sep refinement
     pass (Dan, 2 Sep 2026): uppercase Saira 700 at the tight track. The
     rest of that pass (labels, accent, frames, textures, rhythm) stands. */
  font-family: var(--font-display);
  font-size: var(--fs-display-3);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.02;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0;
}
/* Headings — Saira, sentence case */
.u-h3 {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
  margin: 0;
}
.u-title {
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.3;
  margin: 0;
}
/* Body — Hanken Grotesk */
.u-body-lg {
  font-family: var(--font-body);
  font-size: var(--fs-body-lg);
  font-weight: 400;
  line-height: 1.6;
}
.u-body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.6;
}
.u-body-sm {
  font-family: var(--font-body);
  font-size: var(--fs-note);
  font-weight: 400;
  line-height: 1.6;
}
/* Labels — two systems, never crossed */
.u-eyebrow {
  font-family: var(--font-eyebrow);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.u-mono-label {
  /* Refinement pass (2 Sep 2026): the label voice moves off the monospace.
     Space Mono at 0.14em on every label read as dev-tool chrome; labels are
     now the body face at 13px with a light track, and monospace is reserved
     for data (.u-data): durations, ratios, file names, counters. */
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}
.u-data {
  font-family: var(--font-mono);
  font-weight: 400;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}
.u-mono-micro {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}
/* Metrics — tabular always */
.u-metric-md {
  font-family: var(--font-display);
  font-size: var(--fs-metric-md);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
/* Hero outline word — solid fallback, outline only when strokes paint (§B.2.7) */

/* =============================================================
   BUTTONS — one primitive, three variants, three sizes
   ============================================================= */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  position: relative;
  transition:
    transform var(--dur-base) var(--ease-out, ease),
    background var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease),
    color var(--dur-base) var(--ease-out, ease);
}
.btn:active {
  transform: scale(0.98);
}
.btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.btn--lg {
  height: 56px;
  padding: 0 32px;
  font-size: var(--fs-caption);
}
.btn--md {
  height: 48px;
  padding: 0 26px;
  font-size: var(--fs-eyebrow);
}
.btn--sm {
  height: 40px;
  padding: 0 20px;
  font-size: var(--fs-eyebrow);
}
.btn--sm::after {
  content: "";
  position: absolute;
  inset: -4px 0;
} /* 44px hit area */
.btn--primary {
  background: var(--action-fill);
  color: var(--action-fill-text);
}
.btn--primary:hover {
  background: var(--action-fill-hover);
  color: var(--action-fill-text);
}
.btn--secondary {
  background: transparent;
  color: var(--text-primary);
  border-color: var(--border-strong);
}
.btn--secondary:hover {
  border-color: var(--border-focus);
  background: var(--fill-ghost);
  color: var(--text-primary);
}
.btn--quiet {
  background: none;
  color: var(--text-secondary);
  padding-inline: 4px;
}
.btn--quiet:hover {
  color: var(--text-primary);
}
/* .btn is nowrap because a filled button that wraps loses its shape. A quiet button has
   no fill — it is a text link with a blade — so on narrow screens it wraps instead of
   pushing the page into a horizontal scroll. `height` becomes a floor for the same
   reason: two lines need the box to grow. */
@media (max-width: 767px) {
  .btn--quiet {
    white-space: normal;
    height: auto;
    min-height: 48px;
    padding-block: 12px;
    text-align: left;
    line-height: 1.5;
  }
}
.btn[disabled],
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}
/* The blade grows on hover by scaling, not by width: a width change made the
   button 16px wider and shoved its neighbour sideways on every hover. */
.btn .fx-blade {
  display: inline-block;
  width: 34px;
  height: 2px;
  background: currentColor;
  transform: skewX(-24deg) scaleX(0.53);
  transform-origin: left center;
  transition: transform var(--dur-base) var(--ease-out, ease);
}
.btn:hover .fx-blade {
  transform: skewX(-24deg) scaleX(1);
}

/* =============================================================
   FX — grain, image treatment, marquee, reveals
   ============================================================= */
.fx-grain {
  position: relative;
}
.fx-grain::after,
.cta-close::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNjAiIGhlaWdodD0iMTYwIj48ZmlsdGVyIGlkPSJuIj48ZmVUdXJidWxlbmNlIHR5cGU9ImZyYWN0YWxOb2lzZSIgYmFzZUZyZXF1ZW5jeT0iMC45IiBudW1PY3RhdmVzPSIyIi8+PC9maWx0ZXI+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsdGVyPSJ1cmwoI24pIi8+PC9zdmc+");
  background-size: 160px 160px;
}
.fx-img {
  transition: transform var(--dur-slower) var(--ease-out, ease);
}
.fx-img:hover {
  transform: scale(1.02);
}
.fx-cta {
  transition:
    transform var(--dur-base) var(--ease-out, ease),
    background var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease),
    color var(--dur-base) var(--ease-out, ease);
}
.fx-cta:active {
  transform: scale(0.98);
}
.fx-cta .fx-blade {
  display: inline-block;
  width: 18px;
  height: 2px;
  background: currentColor;
  transform: skewX(-24deg);
  transition: width var(--dur-base) var(--ease-out, ease);
}
.fx-cta:hover .fx-blade {
  width: 34px;
}
@keyframes heroIn {
  from {
    opacity: 0;
    transform: translateY(46px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
/* -50% lands one gap short of a clean seam: .fx-track's gap applies between the
   duplicate copies too, so the loop must travel half the width PLUS half a gap. */
@keyframes marquee {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(calc(-50% - 7px));
  }
}
.fx-marquee {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
/* The track carried these four declarations inline, and an inline `animation`
   shorthand sets animation-play-state to `running` at a specificity no
   stylesheet rule can reach. Both pause selectors below were therefore dead:
   the WCAG 2.2.2 button toggled .is-paused and the strip kept scrolling, and
   hover-pause never worked either. The reduced-motion rule further down only
   works because it reaches for !important. Held in the class instead, so the
   cascade decides and no rule needs to shout. */
.fx-track {
  display: flex;
  gap: 14px;
  width: max-content;
  animation: marquee 96s linear infinite;
}
.fx-marquee:hover .fx-track {
  animation-play-state: paused;
}
.fx-marquee.is-paused .fx-track {
  animation-play-state: paused;
}
/* WCAG 2.2.2 pause control, injected by site-fx.js. Hover-pause alone leaves touch and
   keyboard users with no way to stop the motion. The brand film shares the control's
   look but sits top-right, clear of the headline block and the film meta line. */
.marquee-toggle,
.film-toggle {
  position: absolute;
  right: clamp(16px, 3vw, 40px);
  bottom: 10px;
  z-index: 3;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.62);
  color: rgba(255, 255, 255, 0.86);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-circle);
  cursor: pointer;
  font-size: var(--fs-micro);
  letter-spacing: 0.06em;
  padding: 0;
  -webkit-backdrop-filter: blur(var(--blur-sm));
  backdrop-filter: blur(var(--blur-sm));
  transition:
    color var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease);
}
.marquee-toggle:hover,
.film-toggle:hover {
  color: var(--ink-999);
  border-color: var(--border-strong);
}
.marquee-toggle:focus-visible,
.film-toggle:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
footer .marquee-toggle {
  display: none;
} /* the footer ticker is decorative and tiny */
/* Declared after the shared block so these win — the film control anchors to the top. */
.film-toggle {
  top: clamp(70px, 10vh, 104px);
  bottom: auto;
}

/* Reveals: gated — invisible ONLY when JS has confirmed it will run */
html.js-enabled [data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition:
    opacity var(--dur-reveal) var(--ease-out, ease),
    transform var(--dur-reveal) var(--ease-out, ease);
}
html.js-enabled [data-reveal].is-in {
  opacity: 1;
  transform: none;
}
html.js-enabled [data-reveal].is-in > * {
}
@media (prefers-reduced-motion: reduce) {
  html.js-enabled [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .fx-track {
    animation: none !important;
  }
  html {
    scroll-behavior: auto;
  }
}

/* =============================================================
   CARDS — three kinds only (§C.2)
   ============================================================= */
.card {
  border-radius: var(--radius-md);
  box-sizing: border-box;
}
.card--surface,
.card--data {
  background: var(--surface-card);
  border: 1px solid var(--border-default);
}
.card--hover {
  transition:
    transform var(--dur-base, var(--dur-base)) var(--ease-out, ease),
    border-color var(--dur-base, var(--dur-base)) var(--ease-out, ease);
}
.card--hover:hover {
  transform: translateY(-2px);
  border-color: var(--border-strong);
}
.card--hover:hover .fx-img {
  transform: scale(1.04);
}

/* =============================================================
   FORMS
   ============================================================= */
input[type="text"],
input[type="email"],
input[type="url"],
input[type="number"],
textarea,
select {
  width: 100%;
  box-sizing: border-box;
  height: 48px;
  padding: 0 16px;
  background: var(--surface-inset);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  outline: none;
  transition: border-color var(--dur-base) var(--ease-out, ease);
}
textarea {
  height: auto;
  padding: 12px 16px;
}
input:focus,
textarea:focus,
select:focus {
  border-color: var(--border-focus);
}
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  box-shadow: var(--focus-ring);
}
input[aria-invalid="true"] {
  border-color: var(--border-focus);
}
.field-error {
  font-size: var(--fs-caption);
  color: var(--text-primary);
  font-weight: 600;
  margin-top: 6px;
}
/* The lead form's alert region is always mounted (an aria-describedby target that
   only exists after a failure resolves to nothing while the form is being filled
   in), so it needs a weightless resting state and a visible one. This was a
   130-character style string rebuilt in JS on every render; the two states are
   what CSS is for. Not .field-error above: that styles a message under a single
   field, and this is one form-level alert — reusing it would change the design
   rather than consolidate it. */
.form-alert {
  margin: 0;
}
.form-alert.is-shown {
  margin: 18px 0 0;
  padding: 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
}

/* Range slider — 24px thumb, thick hit area, real focus */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  height: 24px;
  background: transparent;
  outline: none;
  padding: 0;
  border: none;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 2px;
  background: var(--border-default);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 24px;
  height: 24px;
  margin-top: -11px;
  background: var(--data-accent);
  border-radius: 0;
  transform: skewX(-12deg);
  cursor: pointer;
}
input[type="range"]::-moz-range-track {
  height: 2px;
  background: var(--border-default);
}
input[type="range"]::-moz-range-thumb {
  width: 24px;
  height: 24px;
  background: var(--data-accent);
  border: none;
  border-radius: 0;
  cursor: pointer;
}
input[type="range"]:focus-visible {
  box-shadow: var(--focus-ring);
}

/* Choice chips as real inputs */
.chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 18px;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  font-family: var(--font-eyebrow);
  font-size: var(--fs-caption);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  cursor: pointer;
  transition:
    border-color var(--dur-base) var(--ease-out, ease),
    background var(--dur-base) var(--ease-out, ease),
    color var(--dur-base) var(--ease-out, ease);
  min-height: 44px;
  box-sizing: border-box;
  white-space: nowrap;
}
.chip:hover {
  border-color: var(--border-strong);
  background: var(--wash-up-1);
  color: var(--text-primary);
}
[data-theme="light"] .chip:hover {
  background: var(--wash-dn-1);
}
.chip:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.chip[data-on="true"],
.chip[data-on="true"]:hover {
  background: var(--action-fill);
  border-color: var(--action-fill);
  color: var(--action-fill-text);
}
.field {
  width: 100%;
  box-sizing: border-box;
  padding: 13px 15px;
  min-height: 46px;
  -webkit-appearance: none;
  appearance: none;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--text-primary);
  background: var(--wash-up-1);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  transition:
    border-color var(--dur-base) var(--ease-out, ease),
    background var(--dur-base) var(--ease-out, ease);
}
.field::placeholder {
  color: var(--text-tertiary);
}
.field:hover {
  border-color: var(--border-strong);
}
.field:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--wash-up-2);
}
/* Light-surface texture — fine hairline stripes, brand-monochrome, very subtle */
.tex-stripes {
  position: relative;
}
.tex-stripes::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: repeating-linear-gradient(
    90deg,
    rgba(0, 0, 0, 0.028) 0 1px,
    transparent 1px 8px
  );
  mask-image: linear-gradient(180deg, transparent, #000 14%, #000 86%, transparent);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 14%, #000 86%, transparent);
}
.tex-stripes > * {
  position: relative;
}
.tex-stripes--diag::before {
  background-image: repeating-linear-gradient(
    -24deg,
    rgba(0, 0, 0, 0.024) 0 1px,
    transparent 1px 11px
  );
}
[data-theme="light"] .tex-stripes::before {
  background-image: repeating-linear-gradient(
    90deg,
    rgba(0, 0, 0, 0.028) 0 1px,
    transparent 1px 8px
  );
}

/* Dark-surface texture — the mirror of .tex-stripes for black bands, so an
   all-black section reads as a material rather than a void. Grain alone was too
   fine to register at section scale; the hairline rule gives it structure. */
.tex-dark {
  position: relative;
}
.tex-dark::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: repeating-linear-gradient(
    -24deg,
    rgba(255, 255, 255, 0.016) 0 1px,
    transparent 1px 13px
  );
  mask-image: linear-gradient(180deg, transparent, #000 12%, #000 88%, transparent);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 12%, #000 88%, transparent);
}
.tex-dark > * {
  position: relative;
}

/* U-mark field — the closing section only. The mark is the one brand glyph, so it
   tiles at 7.5% as a watermark and fades from the centre out, keeping the headline
   on clean black. Scoped tight on purpose: everywhere else it would be noise. */
.tex-mark {
  position: relative;
}
.tex-mark::before,
.cta-close::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url("assets/u-mark-white-176.png");
  background-repeat: repeat;
  background-size: 88px auto;
  opacity: 0.075;
  mask-image: radial-gradient(115% 88% at 50% 50%, transparent 16%, #000 68%);
  -webkit-mask-image: radial-gradient(115% 88% at 50% 50%, transparent 16%, #000 68%);
}
.tex-mark > * {
  position: relative;
}

/* The closing call to action — the section every page ends on, and the site's
   most repeated moment. It shipped three ways: branded on the homepage, a plain
   dark band on four pages, and Contact on a padding value of its own. One class
   now carries the grain, the U-mark field the note above already scoped to "the
   closing section", the section rhythm and the centring. Page-level borders stay
   inline: they separate whatever happens to sit above. */
.cta-close {
  position: relative;
  padding: var(--section-y) 0 var(--section-y-lg);
  text-align: center;
}
.cta-close > * {
  position: relative;
}

/* The U-mark is the one brand glyph and it was landing at seven hand-set heights
   (44 / 35 / 30 / 30 / 28 / 17 / 16 / 14px), so the same object read as a slightly
   different size on almost every page. Three steps, chosen as the value already
   most used in each cluster. Opacity and spacing stay per-instance — those are
   context, not scale. */
.u-mark {
  width: auto;
}
.u-mark--lg {
  height: 44px;
}
.u-mark--md {
  height: 30px;
}
.u-mark--sm {
  height: 16px;
}

/* Four identical inline font sizes drove the drawer's destinations. */
.nav-drawer-link {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2rem, 9vw, 3.2rem);
  text-transform: uppercase;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

/* The one number style that sat outside the type roles. Mono on purpose — these
   values are not all numeric ("SET"), which is why they are not a metric role. */
.fact-value {
  font-size: clamp(1.4rem, 2.4vw, 2rem);
  font-weight: 700;
  color: var(--text-primary);
}
@media (prefers-reduced-motion: no-preference) {
}

/* Footer nav links: the 46px rule lives in the touch query, so mouse users were left
   with bare line-height (18.6px) — under WCAG 2.5.8 AA's 24px pointer minimum, on
   every page, since the footer is shared. This is the desktop floor; touch still gets 46. */
footer nav a {
  min-height: 26px;
  display: inline-flex;
  align-items: center;
}
/* Same cause: mono-label links (BOOK A 15-MIN CALL, the contact address) measured
   22.4px with a mouse because their 44px rule is touch-gated too. */
a.u-mono-label,
main a[href^="mailto"]:not(p a) {
  min-height: 26px;
  display: inline-flex;
  align-items: center;
}

/* The DS Eyebrow renders an inline-flex box (rule + label). inline-flex sizes to
   max-content and does NOT shrink to its parent, so any eyebrow whose label is long
   enough overflows the container at narrow widths — Work's "Against a traditional
   shoot" measured 312px inside 280px, pushing the document 12px wide at 320. Every
   eyebrow is wrapped in `.eb`, so constraining its inner box fixes the whole class
   at once rather than per-page. */
.eb div {
  max-width: 100%;
  flex-wrap: wrap;
}

/* <=374px: .u-display-1's 2.75rem floor outgrows the viewport. The headline is
   uppercase 800-weight, so its longest word ("EVERYWHERE.") runs ~7.7x the font-size
   — 339px at the floor, wider than the 280px content column. A single word cannot
   wrap, so it forced its grid track 39px past the viewport and the hero's
   overflow:hidden severed the column mid-letter. 11vw keeps that word inside the
   column at every width down to 320. (The class, not the token: site.css's own
   .u-display-1 clamp overrides --fs-display-1, so a token step here is inert.) */
@media (max-width: 479px) {
  :root {
    /* 9.4vw, not 11: at 393 the second line "SEEN EVERYWHERE." measured 405px
       in a 353px column and broke into a third line, splitting the solid and
       outline pair the headline is built on. 346px now; 277px at 320. */
    --fs-display-1: clamp(1.85rem, 9.4vw, 2.75rem);
  }
}

/* Mono type floor — the DS scale bottoms out at 10–11px, which is under the readable
   floor on every device, not just under a thumb. Set globally so no viewport can
   render brand-critical labels at 11px. */
.u-mono-label,
.fmt-spec,
.step-when {
  font-size: 0.8125rem;
}
.u-mono-micro {
  font-size: 0.75rem;
}

/* Focus-only, so not strictly a touch target — but it landed 1.4px short, and that is
   true at every width, so it belongs here rather than in a device query. */
.skip-link {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

/* Press citations — set in Unreal's own type as honest credits, NOT imitation logo
   lockups. The previous version typeset "BUSINESS INSIDER" and a red "AP" in Saira,
   which is a hand-drawn approximation of a third-party trademark. If the outlets'
   official logo files are supplied, swap these for real <img> assets. */
.press-cite {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.005em;
  font-size: clamp(0.9375rem, 1.5vw, 1.0625rem);
  color: var(--ink-900);
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 2px;
  transition:
    color var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease);
}
.press-cite:hover {
  color: var(--ink-999);
  border-bottom-color: var(--ink-999);
}
.press-cite:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.press-arrow {
  font-family: var(--font-mono);
  font-size: 0.75em;
  opacity: 0.6;
  transition:
    transform var(--dur-base) var(--ease-out, ease),
    opacity var(--dur-base) var(--ease-out, ease);
}
.press-cite:hover .press-arrow {
  transform: translate(1px, -1px);
  opacity: 1;
}

/* Stills gallery — masonry columns: native ratios, no cropping, no orphan cells */
/* A rectangular grid: three 4:5 frames, then the landscape portrait across
   two columns beside the fifth. The masonry it replaces ended ragged at every
   width (column bottoms 318px apart at 1440) with the centred link floating
   in the void. The wide frame has no intrinsic height of its own, so it takes
   the row height its 4:5 neighbour sets, exactly. */
/* Four 4:5 frames across (2 x 2 on a phone); one shape, so the row always
   closes flush. The wide-cell variant below is kept for any page that still
   spans a landscape frame across two columns. */
.stills-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  margin-top: 14px;
}
.stills-strip > figure {
  position: relative;
  margin: 0;
  overflow: hidden;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  aspect-ratio: 4 / 5;
}
/* The picture is pinned to the cell, so a landscape source fills the 4:5
   frame the same way a portrait one does: an inline <picture> let the image
   size itself to its own ratio and left the cell half empty. */
.stills-strip > figure picture {
  position: absolute;
  inset: 0;
  display: block;
}
.stills-strip img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.stills-strip > .stills-strip__wide {
  grid-column: span 2;
  aspect-ratio: auto;
  position: relative;
}
.stills-strip > .stills-strip__wide picture {
  position: absolute;
  inset: 0;
}
@media (max-width: 767px) {
  .stills-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }
  /* Alone on its row on a phone, the wide frame keeps its own 3:2. */
  .stills-strip > .stills-strip__wide {
    aspect-ratio: 3 / 2;
  }
}

/* HERO split — editorial left, form right */
.hero-split {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: clamp(32px, 4vw, 72px);
  align-items: start;
}
/* minmax(0,1fr), not 1fr: a bare 1fr track's min size is min-content, so one long
   headline word can push the track past the viewport and the hero clips it. */
@media (max-width: 1023px) {
  .hero-split {
    grid-template-columns: minmax(0, 1fr);
    gap: 36px;
  }
}

/* The wizard split: copy carries slightly more track than the card, and the
   card never grows past a readable form width when the column is generous. */
.hero-split--wizard {
  align-items: center;
}
.hero-split--wizard > div:last-child {
  max-width: 560px;
  width: 100%;
  justify-self: end;
}
@media (max-width: 1023px) {
  .hero-split--wizard > div:last-child {
    justify-self: stretch;
    max-width: 640px;
  }
}

/* Stats + the partnership door, as one baseline band under both hero columns. */
.hero-under {
  margin-top: clamp(32px, 5vh, 48px);
  padding-top: clamp(20px, 3vh, 28px);
  border-top: 1px solid var(--border-strong);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px 32px;
}
/* The band draws the rule once; the stats block inside it loses its own. */
.hero-under .hero-stats {
  border-top: 0;
  flex: 0 1 auto;
}
.hero-under .hero-stat {
  padding-top: 0;
  flex: 0 0 auto;
}
.hero-under .hero-alt {
  display: inline-block;
}
@media (max-width: 479px) {
  .hero-under .hero-stat {
    flex: 1 1 100%;
  }
  .hero-under .hero-stat:first-child {
    padding-top: 0;
  }
  .hero-under .hero-stat + .hero-stat {
    padding-top: 14px;
  }
}

/* The split hero's headline is measured by its column, not by the viewport.
   --fs-display-1 is 6.4vw, calibrated for the full-width heroes every other
   page uses; dropped into a 1.1fr track it outgrows its own authored line
   breaks, so "Shot nowhere. / Seen everywhere." set as four ragged lines at
   every width from 1024 up — 308px of the first screen at 1280 — and the
   solid-line/outline-line pairing the type is built around never resolved.
   Container units size it against the column it actually occupies; min()
   keeps the token as the ceiling so nothing here can enlarge a headline. */
@media (min-width: 1024px) {
  .hero-split > div:first-child {
    container-type: inline-size;
  }
  /* The vw fallback is not redundant, it is the fix for a visible flash.
     This page mounts client-side, and on the first paint after the mount the
     container's inline-size is not registered yet. A cqw length with no
     container resolves against the viewport, so `min(8.8cqw, …)` computed
     81.92px at 1280 — measured — and the headline painted 50% too large for a
     frame before snapping to 54.56px. The column runs about 48% of the shell,
     so 4.2vw lands within a pixel of the container answer and the swap is
     invisible. The @container block below takes over the moment the container
     is live, and stays the authority at every width. */
  .hero-split > div:first-child .u-display-1 {
    font-size: min(4.2vw, var(--fs-display-1));
  }
  @container (min-width: 1px) {
    .hero-split > div:first-child .u-display-1 {
      font-size: min(8.8cqw, var(--fs-display-1));
    }
  }
}

@keyframes recpulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}
@media (prefers-reduced-motion: reduce) {
  [style*="recpulse"] {
    animation: none !important;
  }
}

/* The hero stagger is declared inline per element, so the keyframe-level
   reduced-motion blocks never reached it — a visitor who asked the OS for less
   motion still got the full ten-element sequence. Same attribute-selector guard
   recpulse uses. `animation: none` also cancels the "both" fill, so content that
   would have faded in simply renders in place. */
@media (prefers-reduced-motion: reduce) {
  [style*="heroIn"] {
    animation: none !important;
  }
}

fieldset.chips {
  border: none;
  margin: 0;
  padding: 0;
}
fieldset.chips legend {
  font-size: var(--fs-caption);
  color: var(--text-secondary);
  padding: 0;
  margin-bottom: 10px;
  font-family: var(--font-body);
}

/* Switch — real checkbox with visible knob */
input[type="checkbox"].switch {
  width: 40px;
  height: 22px;
  appearance: none;
  -webkit-appearance: none;
  background: var(--surface-inset);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xs);
  position: relative;
  cursor: pointer;
  margin: 0;
  transition: background var(--dur-base) var(--ease-out, ease);
}
input[type="checkbox"].switch::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  background: var(--text-tertiary);
  transform: skewX(-8deg);
  transition:
    left var(--dur-base) var(--ease-out, ease),
    background var(--dur-base) var(--ease-out, ease);
}
input[type="checkbox"].switch:checked {
  background: var(--data-accent-quiet);
}
input[type="checkbox"].switch:checked::before {
  left: 20px;
  background: var(--data-accent);
}
input[type="checkbox"].switch:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
input[type="checkbox"].switch:focus-visible {
  box-shadow: var(--focus-ring);
}

/* =============================================================
   TABLES — semantic, mobile-stacked below 768px
   ============================================================= */

/* =============================================================
   RESPONSIVE GRIDS — §D.3. Declared spans, no nested auto-fit.
   ============================================================= */
.grid {
  display: grid;
  gap: var(--grid-gap, 24px);
}
.grid--2 {
  grid-template-columns: repeat(2, 1fr);
}
.grid--3 {
  grid-template-columns: repeat(3, 1fr);
}
.grid--4 {
  grid-template-columns: repeat(4, 1fr);
}
.grid--5 {
  grid-template-columns: repeat(5, 1fr);
}
.grid--split {
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 4vw, 56px);
}
@media (max-width: 1023px) {
  .grid--4,
  .grid--5 {
    grid-template-columns: repeat(2, 1fr);
  }
  .grid--3 {
    grid-template-columns: repeat(2, 1fr);
  }
  /* Odd stragglers span the full row — no empty cells */
  .grid--3 > *:nth-child(odd):last-child,
  .grid--5 > *:nth-child(odd):last-child {
    grid-column: 1 / -1;
  }
}
@media (max-width: 767px) {
  .grid--2,
  .grid--3,
  .grid--4,
  .grid--5,
  .grid--split {
    grid-template-columns: 1fr;
  }
  /* Paid-traffic landing heroes (/start, /contact): when the split stacks, the
     form comes first — the h1 plus the form's own header is the pitch, and the
     supporting bullets answer objections below it. Measured before this: the
     first input sat ~1200px down at 390×844, 1.4 viewports from the promise. */
  .hero-lp > :first-child {
    order: 2;
  }
}
/* Grid-child stagger stayed deliberately unimplemented: the reveal system tags
   only section openers and the duel (site-fx.js), and the duel's own row cascade
   below is the one place a cascade tells a story. Blanket card stagger is
   motion without information. */
.grid > * {
  min-width: 0;
}

/* =============================================================
   NAV / drawer
   ============================================================= */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--ink-999);
  color: var(--ink-000);
  padding: 12px 20px;
  font-family: var(--font-eyebrow);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.skip-link:focus {
  left: 12px;
  top: 12px;
}
/* The desktop nav switches on at the documented lg boundary (1024) but at 2.2vw
   its last item ran to 1040px — iPad landscape clipped the START A PROJECT
   button. 1.7vw fits 1024 with 20px to spare and is within a pixel of the old
   gap at 1920, so the wide-desktop rhythm is unchanged. Measured, not guessed. */
.nav-desktop {
  display: flex;
  align-items: center;
  gap: clamp(16px, 1.7vw, 34px);
}
.nav-burger {
  display: none;
}
/* The drawer mounts only while open, so a mount animation is its entrance:
   a short fade-drop for the surface, then the destinations land top to bottom.
   Close unmounts instantly — dismissal never waits. Compositor properties only. */
@media (prefers-reduced-motion: no-preference) {
  #nav-drawer {
    animation: drawer-in var(--dur-base) var(--ease-out, ease);
  }
  #nav-drawer nav > a {
    animation: drawer-link-in var(--dur-slow) var(--ease-out, ease) both;
  }
  #nav-drawer nav > a:nth-child(1) {
    animation-delay: 40ms;
  }
  #nav-drawer nav > a:nth-child(2) {
    animation-delay: 80ms;
  }
  #nav-drawer nav > a:nth-child(3) {
    animation-delay: 120ms;
  }
  #nav-drawer nav > a:nth-child(4) {
    animation-delay: 160ms;
  }
  #nav-drawer .drawer-sub {
    animation: drawer-link-in var(--dur-slow) var(--ease-out, ease) 200ms both;
  }
}
@keyframes drawer-in {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }
}
@keyframes drawer-link-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}
@media (max-width: 1023px) {
  .nav-desktop {
    display: none;
  }
  .nav-burger {
    display: inline-flex;
  }
}
.nav-link {
  font-family: var(--font-eyebrow);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  white-space: nowrap;
  padding: 4px 0;
  border-bottom: 1px solid transparent;
  transition:
    color var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease);
}
.nav-link:hover {
  color: var(--text-primary);
  border-color: var(--ink-999);
}
.nav-link[aria-current="page"] {
  color: var(--text-primary);
  border-color: var(--ink-999);
}

/* Legal section nav. Was four anchors carrying identical inline styles and no class,
   which put them outside every touch-target rule in the mobile block — they computed
   exactly 40px (10px padding on a 12px label), 4px short, on the page's only navigation.
   Styling lives here now so the same sweep reaches them next time. */
.legal-nav {
  margin-top: 36px;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.legal-nav a {
  display: inline-flex;
  align-items: center;
  padding: 10px 18px;
  font-family: var(--font-eyebrow);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--text-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  transition:
    border-color var(--dur-base) var(--ease-out, ease),
    color var(--dur-base) var(--ease-out, ease);
}
.legal-nav a:hover {
  border-color: var(--ink-999);
  color: var(--text-primary);
}

/* Sticky qualify bar. Measured at 390x844: /work runs 5.4 screens, /about 5.0 and
   /how-it-works 4.4 with no actionable element anywhere on screen — the homepage
   solved that with this bar and the other long pages never got one. The shell now
   lives here once; site-fx.js injects the same markup into any page carrying a
   [data-cta-bar] marker, and the homepage's own React copy uses the same class. */
.qbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  background: var(--glass-dark, rgba(0, 0, 0, 0.7));
  -webkit-backdrop-filter: blur(var(--blur-md));
  backdrop-filter: blur(var(--blur-md));
  border-top: 1px solid var(--border-strong);
  animation: heroIn var(--dur-slow) var(--ease-out, ease) both;
}
.qbar-row {
  padding-top: 12px;
  padding-bottom: max(12px, env(safe-area-inset-bottom));
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.qbar-lede {
  display: flex;
  align-items: baseline;
  gap: 16px;
  min-width: 0;
}
.qbar-title {
  font-size: var(--fs-body-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.qbar-acts {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
}
/* Two bars pinned to the same edge means the consent notice (z-index 2147483646)
   sits on top of the action bar (60) and buries its controls — measured on a
   phone with the notice up. Consent is a one-time, front-loaded decision, so the
   action bar waits for it. site-fx.js sets the flag, which also covers the
   homepage's own React-rendered bar. */
html.has-consent-notice .qbar {
  display: none !important;
}
/* The persistent cookie-preferences control is pinned bottom-left at a maximal
   z-index, so it sat squarely on top of the action bar's primary button —
   measured at 390px, and true on the homepage before this pass too. Privacy
   controls do not get hidden, so it steps up above the bar for as long as the
   bar is showing. site-fx.js publishes the bar's measured height. */
html.has-cta-bar #umg-cookie-preferences {
  bottom: calc(max(12px, env(safe-area-inset-bottom)) + var(--qbar-h, 69px) + 10px) !important;
}
@media (max-width: 767px) {
  /* At 390px the three controls take the whole row, leaving the lede squeezed to a
     truncated sliver that reads as a rendering fault. On a phone the two actions
     say it themselves, so the sentence goes and they get the width. */
  .qbar-meta,
  .qbar-title {
    display: none !important;
  }
  .qbar-lede {
    display: none;
  }
  .qbar-row {
    gap: 10px;
  }
  .qbar-acts {
    flex: 1 1 auto;
  }
  .qbar-acts .btn {
    padding-inline: 12px;
  }
  .qbar-acts .btn:not(.qbar-x) {
    flex: 1 1 0;
    justify-content: center;
  }
}

/* Eyebrow labels wrap between words when the width runs out. A nowrap rule sat here
   ("never wrap mid-word") — but normal white-space already never breaks mid-word, and
   nowrap made the label's min-content the full line, so inside the hero's
   overflow:hidden the 320px viewport SEVERED the eyebrow mid-letter instead of
   wrapping it. Sitewide, since every section opens with this component. */
span[style*="0.24em"] {
  white-space: normal;
}

/* Details / FAQ */
details > summary {
  list-style: none;
}
details > summary::-webkit-details-marker {
  display: none;
}
details[open] .faq-x {
  transform: rotate(45deg);
}
/* The + already rotates; the answer itself snapped into place. A 4px settle in
   the direction the panel expands gives the open action a body. Close stays
   instant — dismissal should never wait on choreography. */
@media (prefers-reduced-motion: no-preference) {
  details[open] > :not(summary) {
    animation: faq-in var(--dur-base) var(--ease-out, ease) both;
  }
}
@keyframes faq-in {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
}

/* Footer wordmark: clips horizontally only. `overflow:hidden` also clips vertically,
   and the display face renders ~1.28x its font-size, so the line box must allow for
   that or the glyph bottoms shear off. */
/* Social row — kept ready for the client's real profile URLs. Brand glyphs are inline
   SVG because Lucide dropped its brand set and no icon asset was supplied. */
.social-row {
  list-style: none;
  margin: 22px 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.social-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  background: transparent;
  transition:
    color var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease),
    background 0.2s var(--ease-out, ease),
    transform 0.2s var(--ease-out, ease);
}
.social-btn:hover {
  color: var(--ink-999);
  border-color: var(--ink-999);
  background: var(--wash-up-1, rgba(255, 255, 255, 0.05));
  transform: translateY(-2px);
}
.social-btn:active {
  transform: translateY(0) scale(0.96);
}
.social-btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.footer-wordmark {
  white-space: nowrap;
  overflow-x: hidden;
  max-width: 100%;
  line-height: 1.35;
  padding-bottom: 0.14em;
  font-size: clamp(3.4rem, 12.5vw, 11.5rem);
}
@media (max-width: 1279px) {
  .footer-wordmark-tail {
    display: none;
  }
}
/* Wide viewports show the full name — sized to end at the shell edge, not to be
   guillotined mid-letter. "UNREAL MEDI|" read as a mistake, not a bleed. */
@media (min-width: 1280px) {
  .footer-wordmark {
    font-size: clamp(5.8rem, 7.35vw, 6.55rem);
  }
}

/* Hero monitor — the form's old column shows the work now, one form remains at
   #start. Hidden below the split breakpoint: the frames marquee directly under
   the hero already puts media above the fold on a phone, and a stacked 9:16
   panel would add ~700px to a page already fighting its height. The clip is
   preload="none" with a data-src the reel observer assigns on intersection, so
   a hidden monitor never intersects and never downloads a byte. */

/* =============================================================
   HOMEPAGE HERO (2 Sep 2026) — the work full-bleed, one line, one action
   ============================================================= */

/* The hero is one screen: a reel of published pieces behind a headline at
   the full display scale, one action, a meta line naming the piece playing,
   and the frames ticker as the section's own floor. Three grid rows: the
   copy (which centres in whatever the ticker leaves), the meta line, the
   ticker. 100svh where the browser has it, so the phone's URL bar never
   pushes the ticker under the fold. */
.hero {
  position: relative;
  overflow: hidden;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  /* One explicit column at the section's own width. Left implicit, the
     column sized itself to the ticker's max-content track (about 3900px of
     cells) and every .u-container in the hero centred inside that, 1200px
     off the right edge of the screen. */
  grid-template-columns: minmax(0, 100%);
  grid-template-rows: minmax(0, 1fr) auto auto;
  background: var(--surface-canvas);
  color: var(--text-primary);
}
.hero-media,
.hero-scrim {
  position: absolute;
  inset: 0;
}
.hero-media {
  z-index: 0;
  background: #000;
  transform-origin: 50% 40%;
}
.hero-poster,
.hero-poster img,
.hero-film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* The two reel elements crossfade on opacity alone. Nothing else about them
   moves, so the cut is one compositor fade and the poster under both never
   shows through mid-transition (the outgoing clip keeps painting until the
   fade completes; the script pauses it a beat later). */
.hero-film {
  opacity: 0;
  transition: opacity 900ms var(--ease-out, ease);
}
.hero-film.is-live {
  opacity: 1;
}
/* One scrim, shaped rather than blanket: the reading column on the left and
   the ticker's floor take the ink, the centre and right of the frame keep
   the clip's own light. A phone holds the copy lower in a taller frame, so
   the weight moves to the bottom third. */
.hero-scrim {
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
      90deg,
      rgba(10, 10, 11, 0.82) 0%,
      rgba(10, 10, 11, 0.5) 34%,
      rgba(10, 10, 11, 0.06) 66%,
      rgba(10, 10, 11, 0.18) 100%
    ),
    linear-gradient(
      180deg,
      rgba(10, 10, 11, 0.55) 0%,
      rgba(10, 10, 11, 0) 28%,
      rgba(10, 10, 11, 0) 52%,
      rgba(10, 10, 11, 0.9) 100%
    );
}
@media (orientation: portrait) {
  .hero-scrim {
    background: linear-gradient(
      180deg,
      rgba(10, 10, 11, 0.62) 0%,
      rgba(10, 10, 11, 0.18) 24%,
      rgba(10, 10, 11, 0.42) 56%,
      rgba(10, 10, 11, 0.94) 100%
    );
  }
}
.hero-copy {
  position: relative;
  z-index: 2;
  align-self: center;
  width: 100%;
  padding-top: calc(68px + clamp(32px, 7vh, 88px));
  padding-bottom: clamp(20px, 4vh, 44px);
}
/* The full display scale, sized against the viewport rather than a column.
   min() keeps the token as the ceiling; the vw term keeps the longest line
   ("SEEN EVERYWHERE.", 16 characters of uppercase Saira at 800) inside the
   shell at every width from 480 up. Under 480 the token itself is the 9.4vw
   phone step declared above, which was measured for exactly that line. */
.hero-title {
  margin: clamp(18px, 3vh, 28px) 0 0;
  font-size: min(var(--fs-display-1), 8.6vw);
  line-height: 0.92;
}
@media (max-width: 479px) {
  .hero-title {
    font-size: var(--fs-display-1);
  }
}
/* Masked line reveal: each line is a clipped box and its text rises into it.
   Transform only, no overshoot, and the box reserves the line height, so the
   headline never reflows as it lands. The small padding/negative margin pair
   keeps descenders from clipping at the mask edge. */
.hero-line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}
.hero-line > span {
  display: block;
  transform: translateY(112%);
  animation: heroLine var(--dur-cinematic) var(--ease-out, ease) both;
}
@keyframes heroLine {
  to {
    transform: none;
  }
}
.hero-in {
  animation: heroIn var(--dur-cinematic) var(--ease-out, ease) both;
}
[data-i="1"] {
  animation-delay: 0.1s;
}
[data-i="2"] {
  animation-delay: 0.2s;
}
[data-i="3"] {
  animation-delay: 0.36s;
}
[data-i="4"] {
  animation-delay: 0.46s;
}
[data-i="5"] {
  animation-delay: 0.7s;
}
.hero-lede {
  margin: clamp(20px, 3vh, 30px) 0 0;
  max-width: 38ch;
  color: rgba(255, 255, 255, 0.84);
  text-wrap: pretty;
}
.hero-cta {
  margin-top: clamp(24px, 4vh, 36px);
}
/* The meta line: which piece is playing, its provenance, its page, and the
   one control that stops it. Right-aligned under the copy, over the clip's
   dark floor, in the film-meta ink the brand film already uses. */
.hero-meta {
  position: relative;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 10px 22px;
  padding-bottom: clamp(14px, 2.2vh, 24px);
  color: rgba(255, 255, 255, 0.64);
}
.hero-meta-now {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.hero-meta-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* A phone has no room for the prefix or for one line: the piece's name
   takes the first line whole (truncating before it can wrap), the link and
   the control share the second. */
@media (max-width: 767px) {
  .hero-meta {
    justify-content: flex-start;
    gap: 12px 16px;
  }
  .hero-meta-now {
    flex: 1 1 100%;
  }
  .hero-meta-prefix {
    display: none;
  }
  .hero-meta-link {
    margin-right: auto;
  }
}
.hero-meta-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.85);
  flex: none;
  animation: recpulse 2.4s ease-in-out infinite;
}
.hero-meta-link {
  color: rgba(255, 255, 255, 0.84);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-base) var(--ease-out, ease);
}
.hero-meta-link:hover,
.hero-meta-link:focus-visible {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 4px;
}
.hero-toggle {
  -webkit-appearance: none;
  appearance: none;
  width: 40px;
  height: 40px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  background: rgba(10, 10, 11, 0.55);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: border-color var(--dur-base) var(--ease-out, ease);
}
.hero-toggle:hover {
  border-color: rgba(255, 255, 255, 0.6);
}
.hero-toggle:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
/* The ticker as the hero's floor. A hairline above, the clip's dark floor
   behind, and cells shorter than the standalone strip ran, because here they
   share the screen with the headline. The marquee's own pause control still
   lands bottom-right (site-fx positions it against this box). */
.hero-strip {
  position: relative;
  z-index: 2;
  min-width: 0;
  overflow: hidden;
  padding: clamp(12px, 2vh, 18px) 0 clamp(16px, 3vh, 28px);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.hero-strip-label {
  margin-bottom: 12px;
  color: rgba(255, 255, 255, 0.56);
}
.hero-strip .strip-cell {
  height: clamp(112px, 12vw, 164px);
}
@media (max-width: 767px) {
  .hero-strip .strip-cell {
    height: 124px;
  }
}
/* Scroll handoff, where the browser has scroll-driven animations: the copy
   lifts and fades as the reader leaves, the reel settles back. Pure
   functions of scroll position, no listeners; browsers without the feature
   simply scroll past. Off under reduced motion. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero-copy {
      animation: heroDrift linear both;
      animation-timeline: scroll(root);
      animation-range: 0 80vh;
    }
    .hero-media {
      animation: heroSink linear both;
      animation-timeline: scroll(root);
      animation-range: 0 100vh;
    }
  }
}
@keyframes heroDrift {
  to {
    transform: translateY(-12vh);
    opacity: 0;
  }
}
@keyframes heroSink {
  to {
    transform: scale(1.08);
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero-line > span,
  .hero-in {
    animation: none !important;
    transform: none;
  }
  .hero-meta-dot {
    animation: none;
  }
  .hero-toggle {
    display: none;
  }
}

/* The header floats over the hero. The page opts in (html.nav-overlay, set
   by the homepage on mount) and site-fx flags the resting position
   (html.nav-at-top while scrollY < 24). The header's glass is authored
   inline in SiteNav, so this is the one place !important is the right tool:
   the rule must beat an inline declaration, and only while both flags hold. */
html.nav-overlay .site-header {
  transition:
    background-color var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease);
}
html.nav-overlay.nav-at-top .site-header {
  background: transparent !important;
  border-bottom-color: transparent !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* The proof band under the hero: the press citations on the left, the
   partnership door on the right, one quiet line. */
.proof-band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px 32px;
  padding-top: clamp(18px, 2.6vh, 26px);
  padding-bottom: clamp(18px, 2.6vh, 26px);
}
.proof-band .hero-alt {
  display: inline-block;
}

/* Hero stat ledger — hairline-separated, no orphan padding on the last cell */
.hero-stats {
  display: flex;
  flex-wrap: wrap;
  border-top: 1px solid var(--border-strong);
}
.hero-stat {
  flex: 1 1 140px;
  padding: 22px 24px 0 0;
}
.hero-stat + .hero-stat {
  padding-left: 24px;
  border-left: 1px solid var(--border-subtle);
}
.hero-stat-value {
  margin: 0;
  line-height: 1;
}
.hero-stat-label {
  margin-top: 8px;
  color: var(--text-tertiary);
}
/* Boxed fact bands (How It Works hero and kin) share the phone ledger treatment:
   value left, label right, one row per fact. */
.fact-label {
  margin-top: 8px;
  color: var(--text-tertiary);
}
@media (max-width: 479px) {
  .fact-cell {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
  }
  .fact-cell .fact-label {
    margin-top: 0;
    text-align: right;
  }
}
@media (max-width: 479px) {
  /* Phones get ledger rows, not a tall stack: value left, label right on one
     baseline — the callsheet language the duel section already speaks. Three
     rows read in one glance instead of six stacked lines. */
  .hero-stat {
    flex: 1 1 100%;
    padding: 14px 0 0;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
  }
  .hero-stat + .hero-stat {
    padding-left: 0;
    border-left: 0;
    border-top: 1px solid var(--border-subtle);
    margin-top: 14px;
  }
  .hero-stat-label {
    margin-top: 0;
    text-align: right;
  }
}

/* Format index — raised cards, not hairline cells. The previous version painted each
   cell in --surface-canvas on a near-black section, so the boxes were black on black
   and disappeared. Now each is a lit graphite card that can actually be seen. */
.fmt-index {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(10px, 1.2vw, 14px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.fmt-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  box-sizing: border-box;
  padding: 24px 24px 26px;
  text-decoration: none;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, var(--ink-200), var(--ink-150));
  border: 1px solid var(--line-3);
  color: var(--text-primary);
  box-shadow: var(--elev-card);
  transition:
    background var(--dur-base) var(--ease-out, ease),
    transform var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease),
    box-shadow var(--dur-base) var(--ease-out, ease);
}
/* Scoped to the anchor: /partnership's eligibility row is three <div> criteria
   beside one <a>, and a hover state on all four told the cursor that three
   dead cards were doors. An affordance that lies costs more than one that is
   quiet. */
a.fmt-cell:hover,
button.fmt-tab:hover {
  transform: translateY(-3px);
  border-color: rgba(111, 166, 228, 0.5);
  background: linear-gradient(180deg, var(--ink-300), var(--ink-200));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    var(--elev-float);
}
/* Fallback (no subgrid): a flex column. Titles that wrap will push their own body copy
   down, which is what the @supports block below actually fixes. */
.fmt-cell > .u-h3 {
  min-height: 2.1em;
}
.fmt-cell:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
/* Hover still — a dimmed frame from that format fades up behind the copy, so the index
   answers "what does this look like" without leaving the page. Absolute, so it stays out
   of the subgrid row templates below. The scrim is deliberately heavy: the copy over it
   is --text-secondary body text, and the frame must never lift the composite above the
   card's own --ink-300 hover background or the measured AA margin goes with it. */
.fmt-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  overflow: hidden;
}
.fmt-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.06);
  transition:
    opacity var(--dur-slow) var(--ease-out, ease),
    transform var(--dur-slower) var(--ease-out, ease);
}
/* 0.80 is the floor, not a taste call: at 0.55 image opacity over the --ink-300 hover
   card, a scrim this strong keeps the composite at or below #25 even where a frame goes
   pure white — so --text-tertiary at 12px, the smallest and quietest run in the cell,
   still clears 4.5:1 wherever it lands in the gradient. */
.fmt-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(7, 7, 7, 0.8), rgba(7, 7, 7, 0.92));
}
.fmt-cell > :not(.fmt-bg) {
  position: relative;
  z-index: 1;
}
a.fmt-cell:hover .fmt-bg img,
a.fmt-cell:focus-visible .fmt-bg img,
button.fmt-tab:hover .fmt-bg img,
button.fmt-tab:focus-visible .fmt-bg img,
button.fmt-tab[aria-selected="true"] .fmt-bg img {
  opacity: 0.55;
  transform: scale(1);
}
@media (prefers-reduced-motion: reduce) {
  .fmt-bg img {
    transition: opacity var(--dur-slow) var(--ease-out, ease);
    transform: none;
  }
  a.fmt-cell:hover .fmt-bg img,
  a.fmt-cell:focus-visible .fmt-bg img,
  button.fmt-tab:hover .fmt-bg img,
  button.fmt-tab:focus-visible .fmt-bg img,
  button.fmt-tab[aria-selected="true"] .fmt-bg img {
    transform: none;
  }
}
/* The index number is the one spot of colour per card — it also numbers the sequence. */
.fmt-num {
  color: var(--text-tertiary);
}
/* The eligibility row on /partnership ends 01 · 02 · 03 · →: three statements
   about where the reader already is, then the one thing to do about it. Drawn
   identically, the door reads as a fourth criterion and the page's last moment
   has no visible exit. One step brighter and a stronger edge is enough to make
   it the object in the row that is different — no colour it has not earned, no
   size change, and the grid rhythm is untouched. */
.fmt-cell--action {
  background: linear-gradient(180deg, var(--ink-300), var(--ink-200));
  border-color: var(--line-4);
}
.fmt-cell--action .fmt-num {
  color: var(--text-primary);
}
a.fmt-cell--action:hover {
  border-color: var(--border-focus, rgba(111, 166, 228, 0.7));
}
/* The format cards became the showcase's tab strip when the four per-format
   sections merged into one. They are buttons now, so they need the reset a
   button always needs to look like the card it replaced — and a selected state,
   because a tablist whose only feedback is the panel below it makes the reader
   hunt for what they just pressed. */
button.fmt-tab {
  width: 100%;
  font: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
/* Selected reads at a glance without inventing a colour: the card sits at its
   hover elevation, the border takes the accent it already uses for focus, and a
   rule down the leading edge marks it the way the eyebrow numbers do. */
button.fmt-tab[aria-selected="true"] {
  border-color: var(--border-focus, rgba(111, 166, 228, 0.7));
  background: linear-gradient(180deg, var(--ink-300), var(--ink-200));
  box-shadow:
    inset 3px 0 0 var(--data-accent),
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    var(--elev-card);
}
button.fmt-tab[aria-selected="true"] .fmt-spec {
  color: var(--text-secondary);
}
/* The selected state paints a box-shadow, and so does the focus ring: without
   this the ring on the SELECTED tab is silently overwritten by the state above
   it (0,2,1 beats `.fmt-cell:focus-visible` at 0,2,0), which is exactly the tab
   a keyboard lands on first. Ring wins, always. */
button.fmt-tab:focus-visible,
button.fmt-tab[aria-selected="true"]:focus-visible {
  box-shadow: var(--focus-ring);
}

/* One panel is visible at a time, so its own spacing carries the section's
   rhythm rather than the four section paddings it replaced. */
.fmt-panel {
  margin-top: clamp(32px, 4.5vh, 52px);
}
.fmt-panel-cta {
  margin-top: 28px;
  display: flex;
  justify-content: center;
}

@media (max-width: 1023px) {
  .fmt-index {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* Align the four cards' rows STRUCTURALLY rather than reserving a guessed title height.
   An em-based min-height can't fit an unknown number of wrapped lines — at mid widths
   "PRODUCT FILMS" wraps to two lines and overflowed the reservation, dropping that card's
   body copy ~7px below its neighbours. Subgrid makes every card share one row track set,
   so index / title / body / meta line up however any title wraps. `grid-auto-rows` cycles
   the pattern so it still holds when the grid drops to 2 or 1 column. The <li> between
   grid and card has to opt in too, hence the two levels. */
@supports (grid-template-rows: subgrid) {
  .fmt-index {
    grid-auto-rows: auto auto 1fr auto;
  }
  .fmt-index > li,
  .fmt-cell {
    display: grid;
    grid-row: span 4;
    grid-template-rows: subgrid;
  }
  .fmt-cell > .u-h3 {
    min-height: 0;
  }
  /* Stretch, not end: the shared meta row is sized by its tallest cell, and a
     bottom-aligned meta floats its top hairline wherever its own height lands
     (measured 18px high on the card whose BEST FOR line wraps). Stretching pins
     every hairline to the row's top edge — one rule, four cards. The child
     combinator outranks the flex-fallback `.fmt-meta { margin-top: auto }`
     declared below this block; an auto margin absorbs the track's free space
     before align-self can, so it must lose here. */
  .fmt-cell > .fmt-meta {
    margin-top: 0;
    align-self: stretch;
  }
}
/* Phones: the strip is a snap rail, not a stack.
   Four cards in one column measured 1276px at 390px wide — a third of the
   height the whole page is allowed, spent on the control rather than the work.
   Horizontally it costs one card's height and still shows each card whole, and
   it is the same rail the reels and the product thumbs already use here.

   This has to sit AFTER the @supports block above: subgrid's row template only
   means anything inside the grid it was declared for, and a flex rail is not
   that grid, so both levels have to opt back out. */
@media (max-width: 767px) {
  .fmt-index {
    display: flex;
    grid-template-columns: none;
    grid-auto-rows: auto;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 12px;
    padding-bottom: 4px;
  }
  .fmt-index::-webkit-scrollbar {
    display: none;
  }
  .fmt-index > li {
    flex: 0 0 78%;
    scroll-snap-align: start;
    display: block;
    grid-row: auto;
    grid-template-rows: none;
  }
  .fmt-index > li > .fmt-cell {
    display: flex;
    grid-row: auto;
    grid-template-rows: none;
  }
  /* The flex fallback is back in charge of the meta row once subgrid is off. */
  .fmt-index > li > .fmt-cell > .fmt-meta {
    margin-top: auto;
    align-self: auto;
  }
}

/* Two mono lines in identical tertiary read as one mushy block — divide them,
   and let the audience line outrank the technical spec. */
.fmt-meta {
  display: block;
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--border-subtle);
  color: var(--text-tertiary);
}
/* Differentiate the technical spec from the audience line with tracking, NOT alpha —
   opacity on top of --text-tertiary drops below the 4.5:1 floor. */
/* Split section header: heading left, meta right. The meta holds its own column
   down to 760px instead of wrapping under the display heading at odd widths. */
.sec-head--split {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px clamp(24px, 4vw, 56px);
  margin-bottom: 28px;
}
.sec-head--split > :first-child {
  flex: 1 1 380px;
  min-width: 0;
}
.sec-head--split > .sec-meta {
  flex: 0 1 280px;
  margin: 0;
}
@media (max-width: 767px) {
  .sec-head--split > .sec-meta {
    flex: 1 1 100%;
    padding-top: 16px;
    border-top: 1px solid var(--border-subtle);
  }
}
/* Team cards — portrait over a name/role/bio block with a mailto footer */
.team-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
@media (max-width: 1023px) {
  .team-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .team-grid > :nth-child(odd):last-child {
    grid-column: 1 / -1;
  }
}
/* In the 2-up band the odd last card spans the row; left to itself it renders a
   ~770px-tall portrait that out-weighs the pair above it. Turn that one card
   horizontal — portrait beside the text at the same visual weight as its
   neighbours, object-position holding the head in frame. */
@media (min-width: 768px) and (max-width: 1023px) {
  .team-grid > :nth-child(odd):last-child {
    flex-direction: row;
    align-items: stretch;
  }
  .team-grid > :nth-child(odd):last-child > div:first-child {
    flex: 0 0 42%;
    aspect-ratio: auto !important;
  }
  .team-grid > :nth-child(odd):last-child img {
    object-position: 50% 18%;
  }
}
@media (max-width: 767px) {
  .team-grid {
    grid-template-columns: 1fr;
  }
}
.team-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  transition:
    border-color var(--dur-base) var(--ease-out, ease),
    transform var(--dur-base) var(--ease-out, ease);
}
.team-card:hover {
  border-color: var(--border-strong);
}
/* Specialties, link and email travel as one block pinned to the card foot,
   so the three cards align on every row however long a bio runs. */
.team-foot {
  margin-top: auto;
  display: flex;
  flex-direction: column;
}
.team-mail {
  margin-top: 0;
  padding-top: 18px;
  color: var(--text-tertiary);
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.02em;
  text-transform: none;
  overflow-wrap: anywhere;
  text-decoration: none;
  transition: color var(--dur-base) var(--ease-out, ease);
}
.team-mail:hover {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Comparison table v3 — a labelled row per dimension. The old two-column layout
   had no row anchor and set the "traditional" side in tertiary grey on white,
   which is what made it hard to read. */
/* Sector chips — dark-grey stamps on the light band: present but not shouting,
   and a tonal match for the comparison slab beside them. */
.sector-chip {
  padding: 7px 13px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  background: var(--ink-300);
  color: var(--ink-999);
  border: 1px solid var(--ink-400);
}
.sector-chip:hover {
  background: var(--ink-400);
  border-color: var(--ink-500);
}

/* ---- Colour, used deliberately ----
   The system is monochrome by mandate, with one functional accent. These are the places
   that accent is spent: the label that opens every section, the figure that settles the
   comparison, the index number on each format card, and interactive text. Everything
   else stays ink — which is what keeps these reads as signal rather than decoration. */
/* The DS Eyebrow renders as an unclassed div whose colour AND rule both read
   `var(--text-secondary)` from inline styles — no class rule can outrank that. So each
   eyebrow gets a wrapper of ours and the token is rescoped there: the component keeps
   its own styling contract, and the mark + label pick up the accent together. */
.eb {
  /* Refinement pass: the accent is data-and-state only, as the token file
     says. Eyebrows are the page's own ink at a step down; the work carries
     the colour. --text-primary is theme-scoped, so this holds on the light
     sections too. */
  --text-secondary: var(--text-primary);
  opacity: 0.86;
  display: block;
}
/* The DS scopes --data-accent and --text-primary per theme, but declares the DARK set on
   :root with no [data-theme="dark"] block — so a dark island inside a light section has no
   way to re-enter dark scope. Aliasing them here does it: var() in a custom property is
   substituted at the DECLARING element, so these capture the :root (dark) values and keep
   them when inherited into a [data-theme="light"] subtree. Beats hardcoding the hexes,
   which would silently stop tracking if the DS accent ever changes. */
:root {
  --accent-on-dark: var(--data-accent);
  --text-primary-on-dark: var(--text-primary);
}

/* `--data-accent` is already theme-scoped by the DS — it resolves to the light-band
   counterpart automatically, so no per-theme override belongs here. */
/* Sitewide fallback for eyebrows written as a plain class rather than the component. */
.u-eyebrow {
  --text-secondary: var(--text-primary);
  opacity: 0.86;
}
.sector-chip {
  transition:
    background var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease);
}
.sector-chip:hover {
  border-color: var(--data-accent);
}

/* Case-study fact grid — pinned to counts that divide the 4 cells exactly.
   auto-fit produced a 3+1 row at mid widths, and because the 1px gaps are the
   parent's background showing through, the empty track rendered as a grey box
   that looked like a missing image. */
/* Case study. The breakdowns used to be four equal cells in a row with the films
   somewhere else on the page — a spec table pointing at a reel. Each one now runs
   beside the film it is about, and the four beats are numbered so brief → idea →
   craft → shipped reads as the order it happened in rather than four facts of
   equal weight. Each film keeps its real aspect ratio: the widescreen master and
   the vertical hero are different products and the copy says so. */
.case {
  display: grid;
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  gap: clamp(20px, 3vw, 40px);
  align-items: start;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
  padding: clamp(18px, 2.2vw, 26px);
}
@media (max-width: 899px) {
  .case {
    grid-template-columns: 1fr;
  }
}
/* Sticky so the film stays with the beat being read about — and so the
   widescreen master, which is short, does not leave a column of dead space
   beside a tall breakdown. Released once the layout stacks. */
.case-film {
  position: sticky;
  top: 88px;
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius-md);
  background: var(--ink-100);
  max-height: 520px;
}
@media (max-width: 899px) {
  .case-film {
    position: relative;
    top: auto;
  }
}
.case-film video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.case-film-cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  color: var(--ink-999);
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.82));
}
.case-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-h4);
  letter-spacing: -0.01em;
}
.case-steps {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
}
.case-step {
  display: flex;
  gap: 16px;
  padding: 14px 0;
  border-top: 1px solid var(--border-subtle);
}
.case-step:first-child {
  border-top: 0;
  padding-top: 4px;
}
/* --text-quiet is tuned for --surface-canvas, where it clears 4.5:1. These
   numerals sit on the raised card (#161618), where the same ink measures
   4.13:1 at 12px — the last WCAG 1.4.3 failure on the site after the ink ramp
   was corrected. --text-tertiary reaches 5.57:1 on that surface and is the
   token immediately above it on the same ramp, so the numerals take it rather
   than introducing a one-off hex. */
.case-step-n {
  flex: none;
  width: 2ch;
  font-size: var(--fs-eyebrow);
  color: var(--text-tertiary);
  margin-top: 2px;
}
.case-step-k {
  font-size: var(--fs-eyebrow);
  color: var(--text-tertiary);
}
.case-step-p {
  margin: 8px 0 0;
  font-size: var(--fs-note);
  line-height: 1.6;
  color: var(--text-secondary);
}
.case-hard {
  margin-top: 16px;
  padding: 14px 16px;
  border-left: 2px solid var(--data-accent);
  background: var(--surface-inset-dark, rgba(255, 255, 255, 0.03));
  border-radius: var(--radius-sm);
}

/* LEAD FORM — the conversion surface, so it is the one card allowed real elevation.
   A lit top edge + deep drop separates it from the hero photograph behind it. */
.leadform {
  position: relative;
  overflow: hidden;
  padding: clamp(22px, 2.6vw, 34px);
  background:
    radial-gradient(130% 100% at 8% 0%, rgba(255, 255, 255, 0.055), transparent 62%), var(--ink-150);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow:
    0 44px 90px -36px rgba(0, 0, 0, 0.72),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
.leadform-rule {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(
    90deg,
    var(--ink-999) 0%,
    var(--ink-999) 22%,
    rgba(255, 255, 255, 0.14) 22%,
    rgba(255, 255, 255, 0.06)
  );
}
/* The hero mounts the SAME full form as the page foot, so the compaction is scoped
   to the hero section rather than a variant — tighter there, roomy at the close. */
#top .leadform,
#brief .leadform {
  padding: clamp(18px, 1.9vw, 26px);
}
#top .leadform .field,
#brief .leadform .field {
  min-height: 42px;
  padding: 10px 13px;
}
#top .leadform .chip,
#brief .leadform .chip {
  min-height: 38px;
  padding: 8px 12px;
  font-size: var(--fs-eyebrow);
}
#top .leadform .btn--lg,
#brief .leadform .btn--lg {
  height: 50px;
  padding-inline: 24px;
}
@media (max-width: 1023px) {
  #top .leadform .chip,
  #brief .leadform .chip {
    min-height: 44px;
  }
}
/* Width was standing in for input type, and an iPad in landscape is 1180px of
   touch screen: the device sweep measured these chips at 38px there. Ask the
   pointer instead, so anything a finger drives gets the full target whatever
   its width, and a mouse keeps the compact hero form. */
@media (pointer: coarse) {
  #top .leadform .chip,
  #brief .leadform .chip {
    min-height: 44px;
  }
}
/* Light bands invert the card so it still reads as a raised object, not a hole. */
[data-theme="light"] .leadform {
  background: var(--ink-999);
  border-color: var(--border-default);
  box-shadow:
    0 34px 70px -34px rgba(0, 0, 0, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
}
[data-theme="light"] .leadform-rule {
  background: linear-gradient(
    90deg,
    var(--ink-000) 0%,
    var(--ink-000) 22%,
    rgba(0, 0, 0, 0.14) 22%,
    rgba(0, 0, 0, 0.05)
  );
}
[data-theme="light"] .leadform img[alt=""] {
  filter: invert(1);
}

.lf-heading {
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: -0.018em;
  line-height: 1.02;
  font-size: clamp(1.5rem, 2vw, 1.875rem);
}
.leadform .grid--2 {
  margin-top: 22px;
}
#top .leadform .grid--2 {
  margin-top: 18px;
  gap: 12px;
}
#top .leadform .lf-heading {
  font-size: clamp(1.375rem, 1.7vw, 1.625rem);
}
#top .leadform fieldset {
  margin-top: 18px;
}

/* The hero's three-step wizard (LeadForm variant="hero").
   One form, three CSS states: data-step shows a single question at a time, so
   the native POST fallback still serialises every answered field and nothing
   forks between a "wizard" and the form the rest of the site uses. */
.lf-wiz-track {
  display: flex;
  gap: 7px;
  margin-top: 16px;
}
.lf-wiz-seg {
  height: 3px;
  flex: 1 1 auto;
  background: var(--border-default);
  transform: skewX(-24deg);
  transition: background var(--dur-base) var(--ease-out, ease);
}
.lf-wiz-seg[data-on="true"] {
  background: var(--data-accent);
}
.lf-wiz-acts {
  margin-top: 24px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 18px;
}
/* The submit row's layout lives here, not inline, because the hero wizard has
   to be able to hide it on steps one and two — an inline display would win. */
.lf-send {
  margin-top: 28px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}
.lf-wiz-alt {
  color: var(--text-tertiary);
  text-decoration: none;
  transition: color var(--dur-base) var(--ease-out, ease);
}
.lf-wiz-alt:hover,
.lf-wiz-alt:focus-visible {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.leadform[data-variant="hero"] .lf-sec--who,
.leadform[data-variant="hero"] .lf-sec--what,
.leadform[data-variant="hero"] .lf-sec--when,
.leadform[data-variant="hero"] .lf-send {
  display: none;
}
.leadform[data-variant="hero"][data-step="1"] .lf-sec--what,
.leadform[data-variant="hero"][data-step="2"] .lf-sec--when {
  display: block;
}
.leadform[data-variant="hero"][data-step="3"] .lf-sec--who {
  display: grid;
}
.leadform[data-variant="hero"][data-step="3"] .lf-send {
  display: flex;
}
/* The wizard keeps its own quiet scheduler link; the full-width Calendly
   button and the deep partnership qualifier belong to the long forms. */
.leadform[data-variant="hero"] .lf-cal,
.leadform[data-variant="hero"] .lf-perf-extra {
  display: none;
}
/* One height across the three steps, so Next never makes the card breathe. */
.leadform[data-variant="hero"] .lf-sec--what,
.leadform[data-variant="hero"] .lf-sec--when,
.leadform[data-variant="hero"] .lf-sec--who {
  min-height: 152px;
}
/* Step three opens with its question, like the other two; the long forms
   don't need it — their fields follow a heading that already asks. */
.lf-who-q {
  display: none;
  grid-column: 1 / -1;
  color: var(--text-secondary);
}
.leadform[data-variant="hero"] .lf-who-q {
  display: block;
}

/* Signature — closes the studio's point of view like a signed letter */
.sig {
  margin-top: clamp(36px, 5vh, 56px);
  display: flex;
  align-items: center;
  gap: 16px;
}
.sig-rule {
  flex: 1 1 auto;
  height: 1px;
  background: var(--border-default);
}
.sig-mark {
  flex: none;
  opacity: 0.9;
}
[data-theme="light"] .sig-mark {
  filter: invert(1);
}
.sig-name {
  flex: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.0625rem, 1.5vw, 1.375rem);
  letter-spacing: -0.01em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Operating rules — a numbered editorial list. The previous auto-fit card grid
   produced ragged trailing columns and read as six unrelated tiles. */
.rules {
  list-style: none;
  margin: clamp(32px, 5vh, 52px) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0 clamp(28px, 4vw, 64px);
  border-top: 1px solid var(--border-default);
}
@media (max-width: 1023px) {
  .rules {
    grid-template-columns: 1fr;
  }
}
.rule {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(16px, 2vw, 26px);
  padding: clamp(22px, 2.6vw, 30px) 0;
  border-bottom: 1px solid var(--border-subtle);
  transition: background var(--dur-base) var(--ease-out, ease);
}
.rule-num {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 0.86;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  color: transparent;
  -webkit-text-stroke: 1.5px var(--border-strong);
}
@supports not (-webkit-text-stroke: 1px black) {
  .rule-num {
    color: var(--text-tertiary);
  }
}
.rule:hover .rule-num {
  -webkit-text-stroke-color: var(--text-primary);
}
.rule-name {
  margin: 2px 0 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-title);
  letter-spacing: -0.01em;
  text-transform: uppercase;
}
.rule-body {
  margin: 10px 0 0;
  font-size: var(--fs-note);
  line-height: 1.65;
  color: var(--text-secondary);
}

/* UGC feed — a filmstrip of six vertical clips. The hook name rides ON the frame
   (it is what the ad does, so it earns its place); the old second caption line
   was editorialising and is gone, along with the block under each video. */
.ugc-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: clamp(8px, 1vw, 12px);
}
@media (max-width: 1023px) {
  .ugc-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}
@media (max-width: 767px) {
  .ugc-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
.ugc-card {
  margin: 0;
  display: flex;
  flex-direction: column;
}
.ugc-media {
  position: relative;
  aspect-ratio: 9/16;
  overflow: hidden;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-inset);
  transition:
    transform var(--dur-slow) var(--ease-out, ease),
    border-color var(--dur-slow) var(--ease-out, ease);
}
.ugc-card:hover .ugc-media {
  transform: translateY(-3px);
  border-color: var(--border-strong);
}
.ugc-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  padding: 4px 8px;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.14em;
  color: var(--ink-999);
  background: rgba(0, 0, 0, 0.62);
  -webkit-backdrop-filter: blur(var(--blur-sm));
  backdrop-filter: blur(var(--blur-sm));
  border-radius: var(--radius-xs);
}

/* Section rhythm, tightened. The DS default (144px top AND bottom) is tuned for
   sparse editorial pages; this page runs 13 sections, most of them media-dense,
   so the default adds ~1,000px of pure padding. 104px still reads as generous
   whitespace between two full-bleed media blocks. */
:root {
  /* Refinement pass: two steps, not one. 96px between related sections,
     128px before a shift in the argument, so the gap across a shift lands
     near 224px against 192px between kin. */
  --section-y: clamp(3.5rem, 2rem + 4.5vw, 6rem);
  --section-y-lg: clamp(4.5rem, 2.5rem + 6vw, 8rem);
}

/* Product films — one row of six clips over a compact spec bar. Six divides every
   breakpoint's column count (6 / 3 / 2), so no row ever orphans a cell. */
.pf-reel {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: clamp(10px, 1.2vw, 14px);
}
@media (max-width: 1023px) {
  .pf-reel {
    grid-template-columns: repeat(3, 1fr);
  }
}
@media (max-width: 767px) {
  .pf-reel {
    grid-template-columns: repeat(2, 1fr);
  }
}
.pf-specbar {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0 clamp(20px, 2.6vw, 36px);
  margin-top: clamp(22px, 3vh, 32px);
  padding-top: 20px;
  border-top: 1px solid var(--border-default);
}
@media (max-width: 1023px) {
  .pf-specbar {
    grid-template-columns: repeat(2, 1fr);
    gap: 22px clamp(20px, 2.6vw, 36px);
  }
}
@media (max-width: 479px) {
  .pf-specbar {
    grid-template-columns: 1fr;
  }
}
/* Column count divides the clip count exactly — no orphan cell. */
.pf-thumb {
  margin: 0;
  overflow: hidden;
  aspect-ratio: 9/16;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-inset);
  transition:
    transform var(--dur-slow) var(--ease-out, ease),
    border-color var(--dur-slow) var(--ease-out, ease);
}
.pf-thumb:hover {
  transform: translateY(-3px);
  border-color: var(--border-strong);
}

/* Process — horizontal: four steps read left-to-right as a sequence, in a quarter
   of the vertical space the stacked timeline took. The rail runs along the top. */
.steps-h {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(18px, 2.4vw, 32px);
}
.step-h {
  position: relative;
  padding-top: 26px;
}
.step-h-rail {
  position: absolute;
  top: 5px;
  left: 0;
  right: calc(-1 * clamp(18px, 2.4vw, 32px));
  height: 1px;
  background: var(--border-default);
}
.step-h:last-child .step-h-rail {
  right: 0;
}
.step-h-rail .step-dot {
  position: absolute;
  left: 0;
  top: -5px;
  margin: 0;
}
.step-h-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.step-h .step-out {
  display: block;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border-subtle);
  color: var(--text-tertiary);
}
@media (max-width: 1023px) {
  .steps-h {
    grid-template-columns: repeat(2, 1fr);
    row-gap: clamp(26px, 4vh, 38px);
  }
  .step-h:nth-child(2) .step-h-rail {
    right: 0;
  }
}
@media (max-width: 767px) {
  .steps-h {
    grid-template-columns: 1fr;
  }
  .step-h .step-h-rail {
    right: 0;
  }
}
/* Body copy of different lengths floats each column's OUT row to its own height
   (measured 45px apart on /partnership). Subgrid shares one row set across the
   band — meta, title, body, out — so the OUT hairline is a single line however
   the bodies wrap. The auto-rows pattern keeps it true in the 2- and 1-column
   bands. The rail is absolute, so it takes no track. */
@supports (grid-template-rows: subgrid) {
  .steps-h {
    grid-auto-rows: auto auto 1fr auto;
  }
  .step-h {
    display: grid;
    grid-row: span 4;
    grid-template-rows: subgrid;
  }
}

/* ============================================================
   TOUCH LAYOUT (≤1023px) — matches where .hero-split stacks and the
   burger appears. Tap targets, input zoom and the mono floor belong
   at the SAME breakpoint as the layout they serve; scoping them to
   640 left the 641–1023 band (iPad portrait) with the stacked layout
   and none of the fixes.
   ============================================================ */
@media (max-width: 1023px) {
  /* The three-step wizard is small enough to keep on touch: one question per
     screen, stacked directly under the press citations. (The old full form
     was hidden here and replaced by a scroll-to-#start button; the wizard
     retires that detour.) */

  /* iOS/iPadOS auto-zooms any focused input under 16px — on the one conversion
     surface that costs the user their place. Needs the element qualifier: the base
     `input[type="text"]` rule outranks a bare `.field`. */
  input.field,
  textarea.field,
  input[type="text"],
  input[type="email"],
  input[type="url"],
  textarea,
  select {
    font-size: var(--fs-body);
  }
}

/* ---- Touch ergonomics: gated on INPUT CAPABILITY, not width.
   These were previously inside `max-width: 1023px`, which meant an iPad Pro in
   landscape (1024px, touch-primary) got the desktop nav and none of the 44px
   targets — nav links computed 27.3px. Layout stays width-gated above; only the
   ergonomics follow the pointer. ---- */
@media (max-width: 1023px), (hover: none) and (pointer: coarse) {
  /* 44px minimum on everything tappable */
  .nav-burger {
    min-height: 44px;
    min-width: 44px;
  }
  .btn--sm {
    min-height: 44px;
  }
  .nav-logo {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 9px 0;
  }
  footer nav a {
    padding: 13px 0;
    min-height: 46px;
    display: flex;
    align-items: center;
  }
  .press-cite {
    padding: 14px 0 15px;
  }
  details > summary {
    min-height: 52px;
  }
  /* `:not(p a)` derives the WCAG 2.5.8 exemption structurally: a mailto inside a
     paragraph IS "in a sentence" and is exempt, one that isn't is a discrete control
     and needs the target. Without the qualifier the 44px box inflated the line box of
     any paragraph containing an address (25.5px line-height → 36.5px line spacing). */
  a.u-mono-label,
  main a[href^="mailto"]:not(p a) {
    padding: 11px 0;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  /* Legal's section pills are 40px by design on desktop; only the touch target grows. */
  .legal-nav a {
    min-height: 44px;
  }
  /* The drawer's secondary row (Contact / Client Login) computed 20px tall — under half
     the minimum, on the primary mobile navigation. The drawer only exists below this
     breakpoint, so there is no desktop counterpart to protect. */
  .drawer-sub a {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  /* Focus-only, so not strictly a touch target — but it landed 1.4px short. */
  .skip-link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  /* The desktop nav is visible at ≥1024px, which INCLUDES touch tablets in landscape
     (iPad Pro). Those links compute 27.3px from line-height alone — below 1024 the
     drawer replaces them, so this rule never had a reason to exist until the query
     stopped being width-only. Mouse users keep the tighter header. */
  .nav-desktop .nav-link,
  .nav-desktop .btn {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  .ugc-badge {
    font-size: var(--fs-eyebrow);
    letter-spacing: 0.1em;
    padding: 5px 8px;
  }
  /* The brand-film meta line is nowrap by design (it sits in a one-line overlay row).
     Below ~400px the full string exceeds the viewport, so the qualifier drops rather
     than the label wrapping into the headline beneath it. */
  .film-meta-tail {
    display: none;
  }
}

/* Phone-only density (≤640px) */
@media (max-width: 767px) {
  /* Six 9:16 clips at full width = 4,000px of scroll. Two-up shows the range instead. */
  .ugc-grid {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 10px;
  }

  /* Page-level CTAs go full-width. At 320–430px an auto-width button lands wherever
     its label ends (measured 225px / 206px), so a row of two reads as two ragged
     fragments rather than a decision. Full-width is the native phone pattern, puts the
     primary action under the thumb, and makes the hierarchy unambiguous. Only .btn--lg
     is affected — that class is used exclusively for page CTAs, so .btn--sm/--md inline
     actions keep their intrinsic width. */
  .btn--lg {
    width: 100%;
  }

  /* The decorative still band was 240px tall — a fifth of a phone screen spent on
     texture before any argument. 150px still reads as a moving wall of work. */
  .strip-cell {
    height: 150px;
  }
}

@media (max-width: 1023px) {
  /* Inline width:40px on the dismiss control loses to nothing but !important. */
  .qbar-x {
    width: 44px !important;
    min-height: 44px;
  }
}

/* .step-dot and .step-when are shared by the horizontal steps; the rest of the
   vertical-timeline rules were removed with that markup. */
.step-dot {
  position: relative;
  margin-top: 8px;
  width: 11px;
  height: 11px;
  border-radius: var(--radius-circle);
  background: var(--surface-canvas);
  border: 1px solid var(--border-strong);
  transition:
    border-color var(--dur-base) var(--ease-out, ease),
    box-shadow var(--dur-base) var(--ease-out, ease);
}
.step-h:hover .step-dot {
  border-color: var(--data-accent);
  box-shadow: 0 0 0 4px var(--data-accent-quiet);
}
.step-when {
  padding: 4px 9px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  color: var(--text-tertiary);
  white-space: nowrap;
}

.fmt-spec {
  color: var(--text-tertiary);
  letter-spacing: 0.16em;
}

/* Horizontal clip rail — for long 9:16 reels where row math would always orphan a cell */
.reel-rail {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 10px;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.reel-rail > * {
  flex: 0 0 clamp(190px, 21vw, 250px);
  scroll-snap-align: start;
}
.reel-rail:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
/* Fixed-height rail: each card's width follows its own native ratio, so mixed
   aspect ratios sit side by side without a single cropped frame. */
.reel-rail--tall > * {
  flex: 0 0 auto;
  height: clamp(340px, 38vw, 460px);
  aspect-ratio: 9 / 16;
}
.reel-rail--native > * {
  flex: 0 0 auto;
  height: clamp(300px, 34vw, 420px);
  width: auto;
}
.reel-rail--native > * > video {
  height: 100%;
  width: auto;
}

/* =============================================================
   Partnership page components — the versus ledger and the access
   ledger. Both are authored in the design project's stylesheet;
   only the two families this page needs are ported here, against
   tokens the deployed _ds already defines.
   ============================================================= */

/* ---- Versus rows: how an agency is paid vs how we are ---- */
.vsr {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  overflow: hidden;
  --vsr-them-label: "THEM";
  --vsr-us-label: "UNREAL";
}
.vsr-head,
.vsr-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  padding: 18px clamp(16px, 2.4vw, 26px);
}
.vsr-head {
  background: var(--surface-card);
  border-bottom: 1px solid var(--border-default);
  padding-block: 14px;
}
.vsr-row {
  border-top: 1px solid var(--border-subtle);
}
.vsr-row:first-of-type {
  border-top: 0;
}
.vsr-them {
  color: var(--text-tertiary);
}
.vsr-us {
  color: var(--text-primary);
}

@media (max-width: 767px) {
  /* The header is clipped rather than display:none — the grid is read as a
     comparison, and removing the row strips each cell's column association
     from the accessibility tree. Each usage supplies its own labels. */
  .vsr-head {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .vsr-row {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .vsr-them::before {
    content: var(--vsr-them-label);
    display: block;
    margin-bottom: 4px;
    font-family: var(--font-mono);
    font-size: var(--fs-eyebrow);
    letter-spacing: 0.14em;
    color: var(--text-tertiary);
  }
  .vsr-us::before {
    content: var(--vsr-us-label);
    display: block;
    margin: 10px 0 4px;
    font-family: var(--font-mono);
    font-size: var(--fs-eyebrow);
    letter-spacing: 0.14em;
    color: var(--text-tertiary);
  }
}

/* ---- Access ledger: what we never touch ---- */
.vs-doc {
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-md);
  overflow: hidden;
}
.vs-doc--sheet {
  background: #fdfdfc;
  color: #111;
  border: 1px solid rgba(0, 0, 0, 0.22);
  box-shadow: var(--elev-doc);
}
.vs-doc--sheet .vs-doc-head {
  border-bottom: 1px dashed rgba(0, 0, 0, 0.32);
}
.vs-doc--sheet .vs-line {
  border-bottom: 1px solid rgba(0, 0, 0, 0.09);
}
.vs-doc--sheet .vs-note {
  color: rgba(0, 0, 0, 0.62);
}
.vs-doc--sheet .vs-total {
  border-top: 1px dashed rgba(0, 0, 0, 0.32);
}
.vs-doc-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 8px 16px;
  padding: 16px clamp(16px, 2vw, 24px);
  min-height: 51px;
  box-sizing: border-box;
}
.vs-doc-head .u-mono-label {
  white-space: nowrap;
}
.vs-lines {
  flex: 1 1 auto;
}
.vs-line {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: baseline;
  padding: 13px clamp(16px, 2vw, 24px);
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  line-height: 1.5;
}
.vs-time {
  letter-spacing: 0.04em;
  opacity: 0.62;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.vs-item {
  font-weight: 700;
  letter-spacing: 0.03em;
  overflow-wrap: anywhere;
}
.vs-note {
  text-align: right;
  white-space: nowrap;
}
.vs-total {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 12px 16px;
  padding: 18px clamp(16px, 2vw, 24px);
}
.vs-total-fig {
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(22px, 2.4vw, 32px);
  letter-spacing: 0.02em;
  line-height: 1;
}

@media (max-width: 479px) {
  .vs-line {
    grid-template-columns: 58px minmax(0, 1fr);
  }
  .vs-note {
    grid-column: 2;
    text-align: left;
    white-space: normal;
  }
}

/* ---- Manifest lines: filename · kind · status ----
   The base .vs-line grid leads with a narrow 72px index column, which is
   right for the access ledger but squeezes a filename. Lines carrying a
   .vs-file take a three-column layout instead. */
.vs-line--file {
  grid-template-columns: minmax(0, 1.4fr) auto;
}
.vs-file {
  font-weight: 700;
  letter-spacing: 0.03em;
  overflow-wrap: anywhere;
}
.vs-kind,
.vs-status {
  white-space: nowrap;
}
.vs-doc--sheet .vs-kind {
  color: rgba(0, 0, 0, 0.55);
}
.vs-doc--sheet .vs-status {
  color: #111;
  font-weight: 700;
  letter-spacing: 0.1em;
}

@media (max-width: 767px) {
  .vs-line--file {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .vs-line--file .vs-kind {
    grid-column: 1;
    text-align: left;
    white-space: normal;
  }
}

/* =============================================================
   WHY UNREAL — the duel. Two artifacts instead of a comparison
   table: a paper production call sheet (what one shoot day buys)
   against a dark delivery manifest (what the same brief ships).
   The documents carry the argument; no strikethrough word-pairs.
   ============================================================= */
.vs-duel {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 2.4vw, 32px);
  align-items: stretch;
}
/* In the narrow side-by-side band the folder head needs two rows; the sheet head
   reserves the same height there so the first data rows stay aligned. */
@media (min-width: 1024px) and (max-width: 1279px) {
  .vs-duel .vs-doc-head {
    min-height: 78px;
    align-content: center;
  }
}
.vs-badge {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  width: 58px;
  height: 58px;
  border-radius: var(--radius-circle);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ink-000);
  color: var(--ink-999);
  border: 1px solid var(--line-4);
  font-family: var(--font-eyebrow);
  font-size: var(--fs-caption);
  letter-spacing: 0.14em;
  box-shadow: var(--elev-float);
}
/* Rubber stamp on the call sheet. rgba(17,17,17,0.72) over the #fdfdfc stock
   composites to ~#535353 — 7.6:1, so the 12px bold reads at AA. */
.vs-stamp {
  transform: rotate(-6deg);
  margin: 0 auto;
  flex: none;
  padding: 6px 12px;
  border: 2px solid rgba(17, 17, 17, 0.72);
  border-radius: var(--radius-sm);
  font-family: var(--font-eyebrow);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.18em;
  color: rgba(17, 17, 17, 0.72);
  pointer-events: none;
}

/* Folder — the delivery manifest is from the new world: dark, luminous, file-system
   chrome. The duel sits in a light-themed section, so --data-accent and --text-primary
   would resolve to their light-band counterparts inside this card: the accent drops to
   3.5:1 on --ink-100 (an AA fail at 13px) and the text goes near-black on near-black.
   Both are re-entered from the :root snapshot taken before the light theme overrides
   them, so the card tracks the DS instead of hardcoding hexes. */
.vs-doc--folder {
  background: var(--ink-100);
  color: var(--ink-999);
  border: 1px solid var(--line-3);
  --data-accent: var(--accent-on-dark);
  --text-primary: var(--text-primary-on-dark);
  --border-subtle: rgba(255, 255, 255, 0.09);
  --border-default: rgba(255, 255, 255, 0.16);
  box-shadow:
    var(--elev-doc),
    inset 0 1px 0 var(--line-1);
}
.vs-doc--folder .vs-doc-head {
  border-bottom: 1px solid var(--line-2);
}
.vs-doc--folder .vs-doc-head .u-mono-label {
  color: rgba(255, 255, 255, 0.72);
}
.vs-doc--folder .vs-line {
  border-bottom: 1px solid var(--line-1);
}
.vs-doc--folder .vs-kind {
  color: rgba(255, 255, 255, 0.66);
}
.vs-doc--folder .vs-status {
  color: var(--data-accent);
  font-weight: 700;
  letter-spacing: 0.1em;
}
.vs-doc--folder .vs-total {
  border-top: 1px solid var(--line-2);
}
.vs-doc--folder .vs-total .u-mono-label {
  color: rgba(255, 255, 255, 0.72);
}
.vs-total-fig--accent {
  color: var(--data-accent);
}

/* Rows cascade in when the section reveals; the hidden state is scoped to [data-reveal]
   so a duel already in view on load renders instantly rather than staying blank. */
html.js-enabled [data-reveal] .vs-line {
  opacity: 0;
  transform: translateY(10px);
}
html.js-enabled [data-reveal].is-in .vs-line {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-slower) var(--ease-out, ease),
    transform var(--dur-slower) var(--ease-out, ease);
}
html.js-enabled [data-reveal].is-in .vs-line:nth-child(1) {
  transition-delay: 0.05s;
}
html.js-enabled [data-reveal].is-in .vs-line:nth-child(2) {
  transition-delay: 0.13s;
}
html.js-enabled [data-reveal].is-in .vs-line:nth-child(3) {
  transition-delay: 0.21s;
}
html.js-enabled [data-reveal].is-in .vs-line:nth-child(4) {
  transition-delay: 0.29s;
}
html.js-enabled [data-reveal].is-in .vs-line:nth-child(5) {
  transition-delay: 0.37s;
}
html.js-enabled [data-reveal].is-in .vs-line:nth-child(6) {
  transition-delay: 0.45s;
}
@media (prefers-reduced-motion: reduce) {
  html.js-enabled [data-reveal] .vs-line {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Stack before the folder head would wrap to a second row (~1024px), so the two cards'
   first rows never misalign while they are still side by side. */
@media (max-width: 1023px) {
  .vs-duel {
    grid-template-columns: 1fr;
  }
  .vs-badge {
    position: static;
    transform: none;
    margin: -6px auto;
  }
}

/* Visually-hidden text that stays in the accessibility tree. clip-path rather than
   display:none — a hidden live region is never announced. */
.u-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  white-space: nowrap;
  border: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
}

/* LeadForm track swap — the two question sets exchange places on a height transition
   instead of the page jumping. grid-template-rows 0fr→1fr animates an auto height;
   the inner div carries the overflow so the collapsed track has no scroll box, and
   visibility keeps its controls out of the tab order while it is closed. */
.lf-reveal {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-out, ease);
}
.lf-reveal[data-open="true"] {
  grid-template-rows: 1fr;
}
.lf-reveal > div {
  overflow: hidden;
  min-height: 0;
  visibility: hidden;
  transition: visibility var(--dur-slow);
}
.lf-reveal[data-open="true"] > div {
  visibility: visible;
}
@media (prefers-reduced-motion: reduce) {
  .lf-reveal,
  .lf-reveal > div {
    transition: none;
  }
}

/* Hero's second door — a quiet mono line under the CTAs. Underlined on hover so it reads
   as a link rather than a caption, which is what the unstyled version looked like. */
.hero-alt {
  color: var(--text-tertiary);
  text-decoration: none;
  transition: color var(--dur-base) var(--ease-out, ease);
}
.hero-alt:hover,
.hero-alt:focus-visible {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* Whose risk — claim on the left, mechanism on the right. The rail is deliberately not
   a card: it is three ledger lines, so it reads as the terms of the trade rather than a
   feature list. */
.risk-split {
  margin-top: 30px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
.risk-rail {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
}
.risk-rail li {
  display: grid;
  grid-template-columns: 108px minmax(0, 1fr);
  gap: 8px 18px;
  padding: 16px 0;
  border-top: 1px solid var(--border-default);
}
.risk-rail li:last-child {
  border-bottom: 1px solid var(--border-default);
}
.risk-side {
  color: var(--text-tertiary);
  white-space: nowrap;
}
.risk-side--paid {
  color: var(--data-accent);
}
.risk-item {
  color: var(--text-secondary);
}
@media (max-width: 1023px) {
  .risk-split {
    grid-template-columns: 1fr;
  }
  .risk-rail li {
    grid-template-columns: 1fr;
    padding: 14px 0;
  }
}

/* Footer columns — extracted from 15 identical inline declarations (the footer file
   was 44% style attributes). The hover moves from the runtime's style-hover attribute
   to real CSS. The tap-target rules below still compose on top. */
.foot-col {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.foot-label {
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.foot-link {
  font-family: var(--font-eyebrow);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-secondary);
  white-space: nowrap;
  transition: color var(--dur-base) var(--ease-out, ease);
}
.foot-link:hover,
.foot-link:focus-visible {
  color: var(--text-primary);
}
.foot-link--strong {
  color: var(--text-primary);
}
.foot-link--accent {
  color: var(--data-accent);
}

/* Footer column links are 12px eyebrow text, so each hit box is 14px tall and they clear
   WCAG 2.5.8 only through the spacing exception — a technicality on a phone. Folding the
   column's 12px gap into the links as padding makes every target 26px and leaves the
   footer pixel-identical: same 26px pitch, same rhythm, a target you can actually hit.
   The gap is an inline style on the <nav>, which loses to nothing but !important. */
footer nav[aria-label] {
  gap: 0 !important;
}
footer nav[aria-label] > span:first-child {
  display: block;
  margin-bottom: 12px;
}
footer nav[aria-label] a {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
}
@media (max-width: 1023px) {
  footer nav[aria-label] a {
    min-height: 34px;
  }
  footer nav[aria-label] > span:first-child {
    margin-bottom: 8px;
  }
}

/* =============================================================
   COMPONENT STATES — the matrix the contract promises
   ============================================================= */
/* Buttons: disabled and loading. Disabled keeps pointer events so a tooltip or
   aria-describedby can still explain WHY; the press transform is cancelled. */
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}
.btn:disabled:active,
.btn[aria-disabled="true"]:active {
  transform: none;
}
/* Loading keeps the label legible — a full-button spinner hides what the click
   was — and pulses the blade instead. Feedback, so it survives reduced-motion
   as a static dimmed blade rather than vanishing. */
.btn.is-loading {
  cursor: progress;
  pointer-events: none;
}
.btn.is-loading .fx-blade {
  animation: bladepulse 1s var(--ease-in-out, ease-in-out) infinite;
}
@keyframes bladepulse {
  50% {
    opacity: 0.3;
  }
}
@media (prefers-reduced-motion: reduce) {
  .btn.is-loading .fx-blade {
    animation: none;
    opacity: 0.5;
  }
}

/* Fields: invalid, disabled. Pair aria-invalid with a .field-error text node
   linked by aria-describedby — the runtime's role="alert" flow already does the
   announcing; this styles the field itself so the eye finds it too. */
.field[aria-invalid="true"] {
  border-color: var(--line-4);
}
.field[aria-invalid="true"]:focus-visible {
  box-shadow: var(--focus-ring);
}
.field:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Chips: disabled (pressed/hover/focus already defined with the component). */
.chip:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* =============================================================
   PROOF LAYER — Phase 4
   ============================================================= */

/* Press quote — the citation moves from footnote weight to proof weight. The quote
   is a third party's published headline; the site's own voice stays out of it. */
.press-quote {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.press-quote-text p::before {
  content: "";
  display: block;
  width: 34px;
  height: 2px;
  background: var(--data-accent);
  transform: skewX(-24deg);
  margin-bottom: 22px;
}
.press-quote-cite {
  display: flex;
  align-items: center;
  gap: 18px;
}
.press-quote-sep {
  width: 1px;
  height: 18px;
  background: var(--border-strong);
  flex: none;
}
.press-sep-hero {
  height: 20px;
}
/* The consent notice pins itself at a maximal z-index so page chrome can never
   bury a compliance control — but that also painted it over the open menu's
   bottom CTAs (the drawer dialog sits at z-index 90). The drawer only exists in
   the DOM while open, so :has() scopes the yield exactly to that state. */
body:has(#nav-drawer) #umg-cookie-consent,
body:has(#nav-drawer) #umg-cookie-preferences {
  visibility: hidden;
}
/* Same yield, same reason, for /work's browse sheet: it is a modal pinned to
   the bottom edge, and the notice was painting over its Reset and Show-N-clips
   row — measured on a 390x800 phone, where the notice covered the apply
   control outright. The flag only exists while the sheet is open. */
body[data-wg-sheet="1"] #umg-cookie-consent,
body[data-wg-sheet="1"] #umg-cookie-preferences {
  visibility: hidden;
}
/* When the hero press strip wraps to two lines the divider dangles at a line end —
   drop it and let the gap separate the citations. */
@media (max-width: 479px) {
  .press-sep-hero {
    display: none;
  }
}

/* Batch anatomy — the manifest, counted. Unit tiles at the files' own aspect
   ratios: identity comes from shape and printed counts, never from hue. The
   accent is reserved for the one figure that is data (the total). */
.batch-fig {
  margin: clamp(28px, 4vh, 44px) 0 0;
}
.batch-groups {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: clamp(20px, 3vw, 40px);
}
.batch-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.batch-count {
  color: var(--text-secondary);
  letter-spacing: 0.14em;
}
.batch-tiles {
  display: flex;
  gap: 4px;
  align-items: flex-end;
}
.batch-tiles--grid {
  display: grid;
  grid-template-columns: repeat(8, 16px);
  gap: 4px;
}
.batch-tile {
  display: block;
  width: 16px;
  height: 16px;
  border-radius: var(--radius-xs);
  background: var(--ink-300);
  border: 1px solid var(--line-3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
.batch-tile--wide {
  width: 57px;
  height: 32px;
}
.batch-tile--tall {
  width: 18px;
  height: 32px;
}
.batch-total {
  display: flex;
  align-items: flex-end;
  gap: 14px;
  margin-left: auto;
  padding-left: clamp(20px, 3vw, 40px);
  border-left: 1px solid var(--border-default);
}
.batch-total-fig {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.2rem, 3.4vw, 3.2rem);
  line-height: 0.9;
  color: var(--data-accent);
  font-variant-numeric: tabular-nums;
}
@media (max-width: 767px) {
  .batch-groups {
    gap: 18px 24px;
  }
  .batch-total {
    margin-left: 0;
    padding-left: 0;
    border-left: 0;
    width: 100%;
    padding-top: 16px;
    border-top: 1px solid var(--border-default);
  }
}

/* Case result grid — ships unused; the ready slot for authorised client figures.
   See the comment block above Work's WHY IT WORKS section. */
.case-result-grid {
  margin-top: 12px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px 28px;
}
.case-result-grid > div {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.case-result-k {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  color: var(--text-tertiary);
}
.case-result-v {
  font-size: var(--fs-note);
  line-height: 1.6;
  color: var(--text-secondary);
}

/* =============================================================
   RUNTIME FALLBACK — what a visitor sees when the page cannot render
   -------------------------------------------------------------
   These pages are rendered client-side: support.js hides the raw template
   immediately (hideRawTemplate) and swaps <x-dc> for the rendered tree when
   React lands. If React never lands — a blocked CDN, a content blocker, a
   dropped connection — its catch logs and rethrows, and nothing un-hides the
   page. Measured in that state: document body height 0, and the only thing on
   screen is the cookie banner. This is the state that replaces the void.
   Token values carry literal fallbacks because a failure surface must not
   depend on the thing that may have failed.
   ============================================================= */
/* Centred by flex with margin:auto on the child rather than by grid centring:
   once the panel is taller than the viewport — a 320px phone stacks the
   headline, five lines of body and three full-width buttons — grid centring
   pushes the top out of reach and cannot be scrolled back to. */
.rt-shell {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  padding: clamp(20px, 5vw, 48px);
  overflow-y: auto;
  background: var(--surface-canvas, #0a0a0b);
  color: var(--text-primary, #fafafb);
  font-family: var(--font-body, system-ui, -apple-system, sans-serif);
}
.rt-inner {
  width: min(600px, 100%);
  margin: auto;
}
/* The consent notice pins itself at a maximal z-index, so on a small screen it
   lands on top of the recovery actions. Suppressing a consent control to make
   room is not ours to do — the panel yields and scrolls instead, the same way
   the CTA bar yields to it. */
html.has-consent-notice .rt-shell {
  padding-bottom: 118px;
}
.rt-eyebrow {
  display: block;
  font-family: var(--font-mono, ui-monospace, "Space Mono", monospace);
  font-size: var(--fs-eyebrow, 11px);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-tertiary, rgba(250, 250, 251, 0.55));
}
.rt-title {
  font-family: var(--font-display, "Saira", system-ui, sans-serif);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  line-height: 1.04;
  font-size: var(--fs-display-3, clamp(26px, 4.6vw, 42px));
  margin: 16px 0 0;
  text-wrap: balance;
}
/* Focus is moved here programmatically so the message is announced and the
   keyboard lands on it; it is a heading, not a control, so the ring it would
   otherwise draw is noise. Same treatment as the app-layer error shell. */
.rt-title:focus,
.rt-title:focus-visible {
  outline: none;
  box-shadow: none;
} /* the site draws focus with box-shadow, not outline */
.rt-body {
  margin: 16px 0 0;
  max-width: 48ch;
  font-size: var(--fs-body-sm, 15px);
  line-height: 1.6;
  color: var(--text-secondary, rgba(250, 250, 251, 0.72));
}
.rt-acts {
  margin-top: 28px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.rt-note {
  margin: 22px 0 0;
  font-family: var(--font-mono, ui-monospace, "Space Mono", monospace);
  font-size: var(--fs-eyebrow, 11px);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-tertiary, rgba(250, 250, 251, 0.55));
}
/* The waiting state is deliberately quieter than the failure state: most of the
   time the runtime is 220ms away and this never appears at all. */
.rt-wait {
  display: flex;
  align-items: center;
  gap: 14px;
}
.rt-spin {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: var(--radius-circle, 50%);
  border: 2px solid var(--border-default, rgba(255, 255, 255, 0.1));
  border-top-color: var(--text-primary, #fafafb);
  animation: rtspin 0.9s linear infinite;
}
@keyframes rtspin {
  to {
    transform: rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .rt-spin {
    animation: none;
  }
}

/* ---------------------------------------------------------------------------
   Calendly embed (public/calendly.js)

   The height is reserved here, before any script runs. That is the whole
   trick: the widget's iframe, the loading skeleton and the offline fallback
   all occupy the same reserved box, so whichever one ends up rendering, the
   page below it never moves. Reserving nothing and letting a 700px iframe
   arrive later is the standard way an embed earns a 0.3 CLS.

   The two heights differ because Calendly's own layout does: it stacks the
   calendar under the event details on narrow viewports and puts them side by
   side from ~680px, so a single height is either short on mobile or a band of
   dead space on desktop.
--------------------------------------------------------------------------- */
.cal-embed {
  position: relative;
  min-height: 1060px;
  border: 1px solid var(--border-subtle);
  border-radius: 16px;
  overflow: hidden;
  background: var(--surface-raised, #141416);
}
@media (min-width: 680px) {
  .cal-embed {
    min-height: 720px;
  }
}
.cal-embed__stage {
  position: absolute;
  inset: 0;
}
.cal-embed__stage > div {
  width: 100%;
  height: 100%;
}

/* Skeleton. Deliberately calm: it sits inside the reserved box and is replaced
   in place, so it must not imply the layout is still settling. */
.cal-skeleton {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 28px;
  justify-content: center;
}
.cal-skeleton__row {
  display: block;
  height: 14px;
  border-radius: 999px;
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.05),
    rgba(255, 255, 255, 0.1),
    rgba(255, 255, 255, 0.05)
  );
  background-size: 200% 100%;
  animation: calShimmer 1.6s linear infinite;
}
.cal-skeleton__row:nth-child(1) {
  width: 42%;
}
.cal-skeleton__row:nth-child(2) {
  width: 68%;
}
.cal-skeleton__row:nth-child(3) {
  width: 55%;
}
@keyframes calShimmer {
  from {
    background-position: 200% 0;
  }
  to {
    background-position: -200% 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .cal-skeleton__row {
    animation: none;
  }
}

/* The card that appears when the widget is blocked or does not arrive in time.
   It carries the real booking link and the email address, because a blank
   rectangle where a calendar should be reads as a broken site. */
.cal-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 14px;
  padding: clamp(24px, 5vw, 44px);
  text-align: left;
}
.cal-fallback__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-h3);
  text-transform: uppercase;
  color: var(--text-primary);
}
.cal-fallback__body {
  margin: 0;
  max-width: 46ch;
  color: var(--text-secondary);
  font-size: var(--fs-body-sm);
  line-height: 1.65;
}
.cal-fallback__mail {
  color: var(--text-tertiary);
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  text-decoration: underline;
}
.cal-fallback .btn,
.cal-fallback__mail {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

/* Calendly draws its own focus ring inside the iframe, but the container has
   to be reachable and visibly focused to get there by keyboard. */
.cal-embed:focus-visible {
  outline: 2px solid var(--data-accent, #6fa6e4);
  outline-offset: 3px;
}

/* Format-card clips (public/site-fx.js). The poster sits underneath at the same
   size, so the card looks identical before the clip arrives, under
   prefers-reduced-motion, and if the fetch fails. */
.fmt-bg-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.32;
  transition: opacity var(--dur-base, 200ms) var(--ease-out, ease);
  pointer-events: none;
}
a.fmt-cell:hover .fmt-bg-video,
a.fmt-cell:focus-visible .fmt-bg-video,
button.fmt-tab:hover .fmt-bg-video,
button.fmt-tab:focus-visible .fmt-bg-video,
button.fmt-tab[aria-selected="true"] .fmt-bg-video {
  opacity: 0.55;
}
@media (prefers-reduced-motion: reduce) {
  .fmt-bg-video {
    display: none;
  }
}

/* =============================================================
   UX ENHANCEMENT SYSTEM (2026-08-28)
   Additive only. Everything below either ranks something that was
   previously unranked, gives an existing device a real target/
   affordance, or is a new module built from the families already
   in this file (vs-doc, sec-head, chip, foot-col).
   ============================================================= */

/* -------------------------------------------------- 1 · NAV HIERARCHY */
/* One filled primary per viewport. "Book a call" and "Client Login" keep
   their destinations and their 44px targets; what changes is that they no
   longer read at the same weight as the ask the page is built around. */
.nav-rule {
  display: block;
  width: 1px;
  height: 20px;
  background: var(--border-strong);
}
.nav-link--quiet {
  color: var(--text-tertiary);
}
.nav-link--quiet:hover {
  color: var(--text-secondary);
  border-color: var(--border-strong);
}
.nav-util {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-quiet, var(--text-tertiary));
  white-space: nowrap;
  padding: 4px 0;
  border-bottom: 1px solid transparent;
  transition:
    color var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease);
}
.nav-util:hover {
  color: var(--text-secondary);
  border-color: var(--border-strong);
}
.nav-util[aria-current="page"] {
  color: var(--text-primary);
  border-color: var(--ink-999);
}
.nav-util:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.drawer-sub-link {
  font-family: var(--font-eyebrow);
  font-size: var(--fs-caption);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.drawer-sub-link--quiet {
  color: var(--text-tertiary);
}

/* -------------------------------------------- 2 · TABLET FORM LAYOUT */
/* Paired inputs collapsed at 768 instead of 1024.
   /contact and /start put the lead form in one half of a `.grid--split`
   hero, and the form's own `.grid--2` put NAME and WORK EMAIL side by side
   inside it. Between 768 and 1023 that made each field a ~210px box holding
   a 15px value and a placeholder that could not finish its own sentence
   ("you@brand.com" clipped at 768). The split now stacks with the same rule
   the pairs do, so the form owns the measure at every intermediate width.
   Kept as its own block, and last, so it wins over the 1023 grid rules
   above without !important. */
@media (max-width: 1023px) {
  .grid--split {
    grid-template-columns: minmax(0, 1fr);
  }
  .leadform .grid--2,
  form .grid--2 {
    grid-template-columns: minmax(0, 1fr);
  }
  .hero-lp > :first-child {
    order: 2;
  }
}
/* Below 1024 a stacked form has the full container: hold it to a readable
   measure rather than letting a 900px-wide single input read as a banner. */
@media (min-width: 768px) and (max-width: 1023px) {
  .hero-lp > * {
    max-width: 720px;
    width: 100%;
  }
}

/* ------------------------------------- 3 · HORIZONTAL SCROLL AFFORDANCE */
/* The rails scroll sideways and said so nowhere: no scrollbar (hidden), no
   edge treatment, no hint. A reader who could not see a cut-off card had no
   way to know one existed. `.scroll-rail` adds the two signals that cost
   nothing: content bleeding under a soft edge, and a mono hint that removes
   itself once the rail has been scrolled (JS sets data-scrolled). */
.scroll-rail {
  position: relative;
}
.scroll-rail__hint {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-quiet, var(--text-tertiary));
  transition: opacity var(--dur-base) var(--ease-out, ease);
}
.scroll-rail[data-scrolled="1"] .scroll-rail__hint {
  opacity: 0;
}
/* A rail that fits its container is not a rail: no hint, no fade. The flag is
   set by site-fx.js from the measured scrollWidth, so this reacts to the real
   layout rather than to a breakpoint guess. */
.scroll-rail:not([data-overflow="1"]) .scroll-rail__hint {
  display: none;
}
/* The format tablist only scrolls below 768 (see .fmt-index above). */
.scroll-rail__hint--tabs {
  display: none;
}
@media (max-width: 767px) {
  .scroll-rail[data-overflow="1"] .scroll-rail__hint--tabs {
    display: inline-flex;
  }
}
/* Only masked while there is actually something past the right edge, so a
   rail that fits does not fade its own last card. */
.scroll-rail[data-overflow="1"] > .reel-rail,
.scroll-rail[data-overflow="1"] > .fmt-index,
.scroll-rail[data-overflow="1"] > .fmt-tiles {
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 92%, transparent 100%);
  mask-image: linear-gradient(90deg, #000 0, #000 92%, transparent 100%);
}
.scroll-rail[data-overflow="1"][data-at-end="1"] > .reel-rail,
.scroll-rail[data-overflow="1"][data-at-end="1"] > .fmt-index,
.scroll-rail[data-overflow="1"][data-at-end="1"] > .fmt-tiles {
  -webkit-mask-image: none;
  mask-image: none;
}
/* A pointer that cannot hover has no scrollbar to reveal, so the rail keeps
   a visible one on the desktop it does have. */
@media (hover: hover) {
  .reel-rail {
    scrollbar-color: var(--border-strong) transparent;
  }
}

/* ----------------------------------------------- 4 · DELIVERY MANIFEST */
/* "What you receive", as the folder a delivery actually arrives in. Same
   document language as the vs-doc duel — mono header row, hairline rows,
   a status column — so it reads as another sheet from the same studio and
   not as a feature grid. Every line is a deliverable this site already
   states elsewhere; nothing here is a metric or a claim. */
.mf {
  border: 1px solid var(--border-default);
  background: var(--surface-card);
}
.mf__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px 20px;
  padding: 16px clamp(16px, 2.4vw, 24px);
  border-bottom: 1px solid var(--border-default);
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.mf__head b {
  color: var(--text-primary);
  font-weight: 600;
  letter-spacing: 0.16em;
}
.mf__rows {
  display: block;
  margin: 0;
  padding: 0;
}
.mf__row {
  display: grid;
  grid-template-columns: 2.2rem minmax(0, 1fr) minmax(0, 1.35fr) auto;
  align-items: baseline;
  gap: 6px clamp(12px, 2vw, 26px);
  padding: 16px clamp(16px, 2.4vw, 24px);
  border-bottom: 1px solid var(--border-subtle);
}
.mf__row:last-child {
  border-bottom: 0;
}
.mf__n {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  color: var(--text-quiet, var(--text-tertiary));
}
.mf__file {
  font-family: var(--font-mono);
  font-size: var(--fs-note);
  color: var(--text-primary);
  word-break: break-word;
}
.mf__what {
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: var(--text-secondary);
}
.mf__tag {
  justify-self: start;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  border: 1px solid var(--border-default);
  border-radius: 999px;
  padding: 4px 10px;
  white-space: nowrap;
}
.mf__tag--yours {
  color: var(--data-accent);
  border-color: color-mix(in srgb, var(--data-accent) 45%, transparent);
}
.mf__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  padding: 16px clamp(16px, 2.4vw, 24px);
  border-top: 1px solid var(--border-default);
}
/* Three columns is a table; below 900 it becomes a stacked record, which is
   what it is. The number keeps its own column so the rows stay countable. */
@media (max-width: 899px) {
  .mf__row {
    grid-template-columns: 2.2rem minmax(0, 1fr);
  }
  .mf__tag {
    grid-column: 2;
    margin-top: 4px;
  }
  .mf__what {
    grid-column: 2;
  }
}

/* ---------------------------------------------- 5 · ENGAGEMENT SLATES */
/* Two ways to work, as two slates. The device is the clapperboard's field
   block: a label column and a value column, ruled. Deliberately NOT a
   pricing table — there are no numbers to put in one. */
.slates {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2.4vw, 28px);
}
@media (max-width: 899px) {
  .slates {
    grid-template-columns: minmax(0, 1fr);
  }
}
.slate {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-default);
  background: var(--surface-card);
  padding: clamp(20px, 2.6vw, 30px);
}
.slate--lead {
  border-color: var(--border-strong);
  box-shadow: inset 3px 0 0 var(--data-accent);
}
.slate__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding-bottom: 14px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--border-default);
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.slate__fields {
  margin: 0 0 auto;
  padding: 0;
}
.slate__field {
  display: grid;
  grid-template-columns: minmax(96px, 8.5rem) minmax(0, 1fr);
  gap: 4px 18px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border-subtle);
}
.slate__field:last-child {
  border-bottom: 0;
}
.slate__field dt {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-quiet, var(--text-tertiary));
}
.slate__field dd {
  margin: 0;
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: var(--text-secondary);
}
@media (max-width: 479px) {
  .slate__field {
    grid-template-columns: minmax(0, 1fr);
  }
}
.slate__act {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--border-default);
}
/* .btn is nowrap by default, and "How the Performance Partnership works" is
   38 characters — at 360 it ran 97px past the viewport and was the one thing
   on the page making it scroll sideways. Inside a slate the action wraps and
   is allowed to shrink; nothing else that uses .btn changes. */
.slate__act .btn {
  max-width: 100%;
  white-space: normal;
  text-align: left;
  min-height: 48px;
  height: auto;
  padding-block: 12px;
}

/* ------------------------------------------------------ 6 · FAQ POLISH */
/* The summary row was a 22px-padded flex with the marker as decoration. It
   keeps its look and gains a real 48px target, a hover surface, and a
   marker that reads as open/closed rather than only rotating. */
details > summary {
  list-style: none;
}
details > summary::-webkit-details-marker {
  display: none;
}
details[open] > summary .faq-x {
  transform: rotate(45deg);
}
details > summary:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* --------------------------------------------------- 7 · REDUCED MOTION */
/* One authoritative block, last in the file, covering every decorative
   animation this site ships — the marquees, the footer ticker, the hero
   slow-zoom, the reveals, the blade sweep, the count-up and smooth
   scrolling. Individual rules above cover some of these; the point of this
   block is that a new decorative animation cannot be added without being
   covered by it. Content is never hidden here: everything lands in its
   final state. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .fx-marquee,
  .fxf-track,
  .fx-blade {
    animation: none !important;
    transform: none !important;
  }
  .fx-reveal,
  [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
  }
  /* Snapping is motion the reader did not ask for on a rail they are
     dragging; without it the rail is an ordinary scroller. */
  .reel-rail,
  .fmt-index,
  .wg-rail__group {
    scroll-snap-type: none;
  }
}

/* ------------------------------------------------- 8 · TOUCH TARGETS */
/* The remaining sub-44px controls found in the sweep. Each grows its box,
   not its type, so nothing about the composition changes. */
.qbar-x {
  min-width: 44px !important;
  min-height: 44px !important;
}
@media (max-width: 1023px), (hover: none) and (pointer: coarse) {
  .foot-link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .foot-col {
    gap: 0;
  }
  .nav-util {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .drawer-sub-link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .scroll-rail__hint {
    min-height: 44px;
  }
}

/* --------------------------------------------------- 9 · OVERFLOW GUARD */
/* Nothing on this site is meant to scroll the page sideways; every rail
   owns its own overflow. This makes that a property of the document rather
   than of whichever section last got it right. */
/* On <html> only, deliberately. The same declaration on <body> makes body a
   scroll container, and position: sticky resolves against the nearest one —
   /work's filter rail would stop sticking with no other symptom. Set on the
   root element the overflow propagates to the viewport, so the guard holds
   and every sticky in the site keeps working. */
html {
  overflow-x: hidden;
}

/* ------------------------------- 10 · HOMEPAGE SEQUENCE (2026-08-28) */

/* What you receive — manifest beside the terms. */
.receive-split {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: clamp(16px, 2.4vw, 28px);
  align-items: start;
  margin-top: clamp(32px, 4.5vh, 52px);
}
@media (max-width: 1023px) {
  .receive-split {
    grid-template-columns: minmax(0, 1fr);
  }
}
.receive-terms {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.receive-terms > li {
  display: flex;
  gap: 14px;
  color: var(--text-secondary);
}
.receive-tick {
  flex: none;
  width: 16px;
  height: 2px;
  margin-top: 10px;
  background: var(--data-accent);
  transform: skewX(-24deg);
}

/* Final CTA — what happens after you send it, as three ruled steps. */
.start-next {
  margin: 32px 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--border-subtle);
}
.start-next > li {
  display: flex;
  gap: 16px;
  align-items: baseline;
  padding: 15px 0;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-secondary);
}
.start-next__n {
  flex: none;
  color: var(--text-quiet, var(--text-tertiary));
}

/* ------------------------------- 11 · WORK COLLECTIONS NAV (2026-08-29) */
/* /work is five collections behind one label. The nav says so on desktop
   through a panel and on mobile through a group in the drawer — in both
   cases as an addition to the plain /work link, never as a replacement for
   it, so the hub stays reachable in one action from anywhere. */
.nav-mega {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.nav-mega__trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.nav-mega__caret {
  width: 0;
  height: 0;
  border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent;
  border-top: 4px solid currentColor;
  opacity: 0.55;
  transition:
    transform var(--dur-base) var(--ease-out, ease),
    opacity var(--dur-base) var(--ease-out, ease);
}
.nav-mega__trigger[aria-expanded="true"] .nav-mega__caret {
  transform: rotate(180deg);
  opacity: 1;
}
.nav-mega__panel {
  position: absolute;
  top: calc(100% + 14px);
  left: 50%;
  transform: translateX(-50%) translateY(-6px);
  min-width: 320px;
  padding: 8px;
  background: var(--surface-card, #141416);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: 0 28px 60px -24px rgba(0, 0, 0, 0.8);
  display: grid;
  gap: 2px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity var(--dur-base) var(--ease-out, ease),
    transform var(--dur-base) var(--ease-out, ease),
    visibility 0s linear var(--dur-base);
  z-index: 60;
}
.nav-mega__panel[data-open="true"] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
  transition:
    opacity var(--dur-base) var(--ease-out, ease),
    transform var(--dur-base) var(--ease-out, ease),
    visibility 0s;
}
/* The gap between the trigger and the panel would drop a hover halfway
   across it; this bridges it without being visible or clickable in itself. */
.nav-mega__panel::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -14px;
  height: 14px;
}
.nav-mega__item {
  display: grid;
  gap: 2px;
  padding: 10px 12px;
  min-height: 44px;
  align-content: center;
  border-radius: 4px;
  text-decoration: none;
  transition: background var(--dur-base) var(--ease-out, ease);
}
.nav-mega__item:hover {
  background: var(--wash-up-1);
}
.nav-mega__item:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.nav-mega__name {
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--text-primary);
}
.nav-mega__note {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.nav-mega__item--all {
  margin-top: 4px;
  padding-top: 12px;
  border-top: 1px solid var(--border-subtle);
  border-radius: 0 0 4px 4px;
}
@media (prefers-reduced-motion: reduce) {
  .nav-mega__panel {
    transition:
      opacity 1ms,
      visibility 0s;
    transform: translateX(-50%);
  }
  .nav-mega__panel[data-open="true"] {
    transform: translateX(-50%);
  }
}

/* Drawer: the same five, one tap from the menu rather than two. */
.drawer-cats {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 14px 0 6px;
  border-bottom: 1px solid var(--border-subtle);
}
.drawer-cat {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 14px;
  border: 1px solid var(--border-default);
  border-radius: 999px;
  font-family: var(--font-eyebrow);
  font-size: var(--fs-caption);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.drawer-cat:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.drawer-cat--all {
  border-color: var(--border-strong);
  color: var(--text-primary);
}

/* The plain-language production explainer on the homepage's process band.
   Set apart from the step rail above it by a rule rather than a panel: it is
   an aside to the sequence, not a fifth step. */
.proc-plain {
  margin-top: clamp(22px, 3vh, 32px);
  padding-top: clamp(20px, 2.6vh, 26px);
  border-top: 1px solid var(--border-subtle);
}

/* ------------------- 13 · HOW IT WORKS · SETTLED BEFORE YOU SIGN */
/* Five answers, as a definition list. Not cards: they are answers to
   questions, and a grid would rank them against each other when the reader
   needs whichever one they arrived worrying about. */
.hiw-settled {
  margin: clamp(32px, 4.5vh, 52px) 0 0;
  padding: 0;
  border-top: 1px solid var(--border-default);
}
.hiw-settled__row {
  display: grid;
  grid-template-columns: minmax(150px, 13rem) minmax(0, 1fr);
  gap: 6px clamp(20px, 3vw, 48px);
  padding: clamp(16px, 2.2vh, 22px) 0;
  border-bottom: 1px solid var(--border-subtle);
}
@media (max-width: 639px) {
  .hiw-settled__row {
    grid-template-columns: minmax(0, 1fr);
  }
}
.hiw-settled__row dt {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-quiet, var(--text-tertiary));
}
.hiw-settled__row dd {
  margin: 0;
  color: var(--text-secondary);
  line-height: 1.65;
  max-width: var(--measure-body);
}

/* ------------------------------- 14 · PARTNERSHIP · THE TERMS */
.pt-terms {
  margin: clamp(32px, 4.5vh, 52px) 0 0;
  padding: 0;
  border-top: 1px solid var(--border-default);
}
.pt-terms__row {
  display: grid;
  grid-template-columns: minmax(150px, 13rem) minmax(0, 1fr);
  gap: 6px clamp(20px, 3vw, 48px);
  padding: clamp(16px, 2.2vh, 22px) 0;
  border-bottom: 1px solid var(--border-subtle);
}
@media (max-width: 639px) {
  .pt-terms__row {
    grid-template-columns: minmax(0, 1fr);
  }
}
.pt-terms__row dt {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-quiet, var(--text-tertiary));
}
.pt-terms__row dd {
  margin: 0;
  color: var(--text-secondary);
  line-height: 1.65;
  max-width: var(--measure-body);
}
.pt-terms__link {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ------------------------------------------- 15 · ABOUT · TEAM SPECIALTIES */
/* Three short tags per person, each restating something the bio above already
   says. Set as quiet mono chips so they read as an index of the paragraph
   rather than as credentials the paragraph did not earn. */
.team-spec {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 16px 0 0;
  padding: 0;
  list-style: none;
}
.team-spec__item {
  border: 1px solid var(--border-default);
  border-radius: 999px;
  padding: 5px 10px;
  color: var(--text-tertiary);
  line-height: 1;
}
.team-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 14px;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border-strong);
  align-self: flex-start;
}
.team-link:hover {
  color: var(--text-primary);
  border-color: var(--ink-999);
}
.team-link:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* =============================================================
   HOMEPAGE SIMPLIFICATION (2026-08-31)
   The format tiles that replaced the tabbed showcase, the slim
   manifest view, and the one-row production standards. Additive:
   the fmt-cell/fmt-index family above stays for /partnership,
   and the full .mf grid stays for How It Works.
   ============================================================= */

/* ------------------------------------------------ 1 · FORMAT TILES */
/* Each tile IS the format's lead sample: a 9:16 frame playing full-bleed,
   the copy reduced to number, name and audience line. 9:16 because that is
   the native ratio of all three clips and the stills poster — the work
   fills the tile edge to edge instead of being a dimmed backdrop. */
.fmt-tiles {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(10px, 1.2vw, 14px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.fmt-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  aspect-ratio: 9 / 16;
  overflow: hidden;
  border-radius: var(--radius-md);
  border: 1px solid var(--line-3);
  background: var(--surface-card);
  text-decoration: none;
  color: var(--text-primary);
  box-shadow: var(--elev-card);
  transition:
    transform var(--dur-base) var(--ease-out, ease),
    border-color var(--dur-base) var(--ease-out, ease),
    box-shadow var(--dur-base) var(--ease-out, ease);
}
.fmt-tile:hover {
  transform: translateY(-3px);
  border-color: rgba(111, 166, 228, 0.5);
  box-shadow: var(--elev-float);
}
.fmt-tile:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
@media (prefers-reduced-motion: reduce) {
  .fmt-tile,
  .fmt-tile:hover {
    transform: none;
  }
}
.fmt-tile-media {
  position: absolute;
  inset: 0;
}
.fmt-tile-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.fmt-tile-clip {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .fmt-tile-clip {
    display: none;
  }
}
/* The copy sits in the last ~22% of the tile, where the scrim has reached
   0.82 — the floor at which a 0.78-alpha white mono line still clears 4.5:1
   over a pure-white frame. The top eighth takes just enough to seat the
   number chip on a bright sky. */
.fmt-tile-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(7, 7, 7, 0.16) 0%,
    rgba(7, 7, 7, 0) 24%,
    rgba(7, 7, 7, 0) 50%,
    rgba(7, 7, 7, 0.82) 78%,
    rgba(7, 7, 7, 0.94) 100%
  );
}
.fmt-tile-copy {
  position: relative;
  display: block;
  padding: clamp(16px, 2vw, 22px);
}
/* The number keeps its accent, on its own pill so it reads on any frame. */
.fmt-tile .fmt-num {
  position: absolute;
  top: 14px;
  left: 16px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(10, 10, 11, 0.68);
}
.fmt-tile-name {
  display: block;
  color: var(--ink-999);
}
.fmt-tile-for {
  display: block;
  margin-top: 8px;
  color: rgba(255, 255, 255, 0.78);
}
/* Pointer affordance only — the tile's name is the accessible label and the
   whole tile is the link, so this can afford to arrive on hover. */
.fmt-tile-go {
  position: absolute;
  top: 14px;
  right: 16px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(10, 10, 11, 0.68);
  color: var(--ink-999);
  opacity: 0;
  transform: translateX(-6px);
  transition:
    opacity var(--dur-base) var(--ease-out, ease),
    transform var(--dur-base) var(--ease-out, ease);
}
.fmt-tile:hover .fmt-tile-go,
.fmt-tile:focus-visible .fmt-tile-go {
  opacity: 1;
  transform: translateX(0);
}
@media (prefers-reduced-motion: reduce) {
  .fmt-tile-go {
    transform: none;
    transition: opacity var(--dur-base) var(--ease-out, ease);
  }
}
@media (max-width: 1023px) {
  .fmt-tiles {
    grid-template-columns: repeat(2, 1fr);
  }
}
/* Phones: the same snap rail the old card strip used — one tile's height,
   each tile shown whole, and the scroll-rail hint/mask wired by site-fx. */
@media (max-width: 767px) {
  .fmt-tiles {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 12px;
    padding-bottom: 4px;
  }
  .fmt-tiles::-webkit-scrollbar {
    display: none;
  }
  .fmt-tiles > li {
    flex: 0 0 72%;
    scroll-snap-align: start;
  }
}

/* --------------------------------------------- 2 · SLIM MANIFEST VIEW */
/* The homepage manifest names the file and the format only; the per-row
   sentences live on How It Works. Three columns, not four — the ≤899px
   collapse above already handles the stacked record for both views. */
.mf--slim .mf__row {
  grid-template-columns: 2.2rem minmax(0, 1fr) auto;
}

/* ------------------------------------------ 3 · PRODUCTION STANDARDS */
/* The six standards as one wrapping hairline row where a titled section
   stood. The dot is drawn, not typed, so a screen reader hears six
   standards and no stray punctuation. */
.cleared-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px 18px;
  margin-top: clamp(28px, 4vh, 44px);
  padding-top: 24px;
  border-top: 1px solid var(--border-default);
}
.cleared-line > .u-mono-micro {
  color: var(--text-secondary);
}
.cleared-line > .u-mono-micro:not(:last-child)::after {
  content: "·";
  margin-left: 18px;
  color: var(--text-quiet, var(--text-tertiary));
}

/* ------------------------------------- 4 · RESTORED-HERO TOUCH RULES */
/* The restored homepage hero (31 Aug: homepage back to its Thursday 27 Aug
   form, everything else current) mounts the full lead form and a
   mobile-only CTA. These are the two rules that hero carried before the
   wizard hero replaced it, and the wizard pass dropped them with the old
   markup. Scoped so the wizard variant, if it returns, is untouched. */

/* =============================================================
   HOMEPAGE PASS (1 Sep 2026) — hero balance, monitor reel, format tiles
   ============================================================= */

/* Format tiles read as an index, not a second gallery: 4:5 rather than the
   9:16 the family was drawn for, so four tiles sit about 360px tall in the
   content column and the work sections below keep the taller frames. The
   .fmt-tile-clip slot stays unused here — four autoplaying clips above four
   sections of autoplaying clips would fight the page's own media budget. */
.fmt-tile {
  aspect-ratio: 4 / 5;
}
.fmt-tile-copy .fmt-tile-name {
  font-size: var(--fs-h4, var(--fs-h3));
  letter-spacing: 0.02em;
}

/* =============================================================
   DETAILED AUDIT PASS (1 Sep 2026) — story, conversion and chrome findings
   ============================================================= */

/* A subgrid step inherits the band's gap between its own four rows, which
   spread meta, title, body and OUT by 32px and stopped each step reading
   as one unit. Its own row gap is zero; the gap between steps is untouched. */
@supports (grid-template-rows: subgrid) {
  .step-h {
    row-gap: 0;
  }
}

/* Three eligibility cards: three columns, so the closing "Request an audit"
   card is not a hole on desktop, and a stacked column on phones, so it is
   never off-canvas behind a rail with no hint. */
.fmt-index--three {
  grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 1023px) and (min-width: 768px) {
  .fmt-index--three {
    grid-template-columns: repeat(3, 1fr);
  }
}
@media (max-width: 767px) {
  .fmt-index--three {
    flex-direction: column;
    overflow: visible;
  }
  .fmt-index--three > li {
    flex: 0 0 auto;
  }
}

/* Index numerals on the light sections were stroked at 16% black and read as
   blank until hover. */
[data-theme="light"] .rule-num {
  -webkit-text-stroke-color: rgba(0, 0, 0, 0.34);
}

/* The definition-list labels are the scanning anchors of the terms and the
   settled-before-you-sign lists; they were the faintest text on either page. */
.hiw-settled__row dt,
.pt-terms__row dt {
  color: var(--text-tertiary);
}

/* Legal: the in-page pills meet the site's 44px floor, and on phones the
   LAST UPDATED stamp drops under every section title, not just the one whose
   title is long enough to force it. */
.legal-nav a {
  min-height: 44px;
}
@media (max-width: 479px) {
  [data-screen-label="Legal"] section > div:first-child {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }
}

/* 404: three recovery buttons at three widths read as ragged on a phone. */
@media (max-width: 479px) {
  [data-screen-label="404"] main .btn {
    width: 100%;
    max-width: 320px;
  }
}

/* Footer columns below 1024 wrapped 4+1 (tablet) and 2+2+1 (phone), each
   leaving LEGAL alone under a void. A three- then two-column grid keeps the
   rows even; Legal spans the phone row as one line of links. */
@media (max-width: 1023px) {
  footer .foot-cols {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
@media (max-width: 479px) {
  footer .foot-cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  footer nav[aria-label="Legal"] {
    grid-column: 1 / -1;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0 20px;
  }
  /* The bottom bar repeated the brand block's DISTRIBUTED STUDIO line 500px
     under it on a phone. */
  footer > div:last-child > div > span:last-child {
    display: none;
  }
}
/* The one accent-coloured link in the chrome outranked the two actions beside
   it; the accent is a data colour, not a link colour. */
.foot-link--accent {
  color: var(--text-secondary);
}
/* Once a consent choice is made the fixed preferences pill sits over the
   copyright line; the bar makes room for it. */
html:has(#umg-cookie-preferences) footer > div:last-child > div {
  padding-bottom: 72px;
}

/* The drawer on a short phone (375x667) ran 692px in a 667px viewport with
   its last button clipped; it scrolls instead. */
#nav-drawer {
  overflow-y: auto;
  overscroll-behavior: contain;
}
@media (max-height: 700px) {
  #nav-drawer nav {
    justify-content: flex-start;
    padding-top: 12px;
  }
}

/* The reassurance line under the form wrapped with a single word orphaned. */
.leadform > p.u-mono-label {
  text-wrap: balance;
}

/* =============================================================
   DETAILED AUDIT PASS (1 Sep 2026) — homepage findings
   ============================================================= */

/* The frame strip's height lives here so the phone rule below can win; an
   inline clamp on the figure used to beat it, so the decorative strip was
   230px tall on a phone (27% of the screen) under a two-line label. */
.strip-cell {
  height: clamp(230px, 26vw, 320px);
}
@media (max-width: 767px) {
  .strip-cell {
    height: 150px;
  }
}

/* In-page destinations land under the fixed header on touch widths, where
   sections carry less top padding than on desktop. */
@media (max-width: 1023px) {
  main > section[id],
  main > section > nav[id] {
    scroll-margin-top: 80px;
  }
}

/* Five vertical films fit five across at desktop widths; as a rail, exactly
   four showed and the fifth was never visible. Below 1024 the rail returns,
   now inside a .scroll-rail wrapper that fades the edge and says so. */
@media (min-width: 1024px) {
  .reel-rail--tall {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    overflow: visible;
    padding-bottom: 0;
  }
  .reel-rail--tall > * {
    height: auto;
    width: auto;
    aspect-ratio: 9 / 16;
  }
}
.reel-rail figcaption .u-mono-micro {
  text-wrap: balance;
}

/* Between 768 and 1023 the format index ran 2x2 at 367x460, a second gallery
   between the film and the first section; four across keeps it an index. */
@media (min-width: 768px) and (max-width: 1023px) {
  .fmt-tiles {
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
  }
}

/* The send row wrapped by one pixel at 1440 (two 217px buttons in a 445px
   row), stacking the two actions like a phone layout. */
#start .lf-send > .btn {
  flex: 1 1 0;
  min-width: 0;
  padding-inline: 20px;
}
/* The promise column is half the form's height; it stays in view while the
   reader works down to Send instead of scrolling away. */
@media (min-width: 1024px) {
  #start .grid--split > div:first-child {
    position: sticky;
    top: 96px;
  }
}

/* The fixed cookie-preferences pill steps out of the lightbox and the channel
   bar, which both own the bottom of the viewport while open. */
body.wg-locked #umg-cookie-preferences,
html.has-channel #umg-cookie-preferences {
  visibility: hidden;
}

/* Contact and Start below 1024: the copy column now carries the eyebrow and
   headline, and the touch rule above put the whole column after the form, so
   a phone opened on a form with no headline. The column dissolves into the
   grid so the eyebrow and headline lead, the form follows, and the lede, press
   and promises close. */
@media (max-width: 1023px) {
  .hero-lp > :first-child {
    display: contents;
  }
  .hero-lp > :first-child > * {
    order: 3;
  }
  .hero-lp > :first-child > .eb,
  .hero-lp > :first-child > h1 {
    order: 1;
  }
  .hero-lp > :first-child > h1 {
    margin-top: 0;
  }
  .hero-lp > :not(:first-child) {
    order: 2;
  }
}

/* The 9:16 breakdown film is narrower than its column at every width above
   the stack; it centres instead of hugging the left edge with dead space
   beside it. */
@media (min-width: 900px) {
  .case-film {
    justify-self: center;
    width: fit-content;
    max-width: 100%;
  }
}
@media (max-width: 899px) {
  .case-film {
    width: fit-content;
    max-width: 100%;
    margin-inline: auto;
  }
}

/* While the channel plays, its bar owns the bottom edge; the consent notice
   sat on top of the now-playing title and thumbnail. It returns when the
   channel stops. */
body.wg-locked #umg-cookie-consent,
html.has-channel #umg-cookie-consent {
  visibility: hidden;
}

/* The footer column wrapper carried its flex layout inline, which outranked
   the tablet and phone grid rules above; those never applied, and LEGAL sat
   alone under a void at every width below 1024. The layout lives here now. */
.foot-cols {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(32px, 5vw, 72px);
}

/* One hundred characters a line at 768 on the Studio page's rules. */
.rule-body {
  max-width: 62ch;
}

/* Four format tiles across a tablet leave 170px per tile: balance the wrapped
   names and sub-labels so neither ends on a dangling word. */
@media (min-width: 768px) and (max-width: 1023px) {
  .fmt-tile-name,
  .fmt-tile-for {
    text-wrap: balance;
  }
}

/* The drawer's vertical centring was inline, which outranked the short-screen
   rule above that starts the list at the top; it lives here so both apply. */
#nav-drawer nav {
  justify-content: center;
}

/* At 768 to 899 the breakdown card is wide enough for the film and the steps
   side by side; stacked, the 9:16 film sat matted in the centre with the
   four steps 500px below it. */
@media (min-width: 768px) and (max-width: 899px) {
  .case {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  }
  .case-film {
    margin-inline: 0;
    justify-self: center;
  }
}

/* On a short landscape viewport the hero monitor narrows to 300px and its
   title bar truncated ("SNEAKER · NIGHT STRE…"); the bar tightens its
   tracking and gaps when the monitor itself is narrow. */
.hero-monitor {
  container-type: inline-size;
}
@container (max-width: 340px) {
  .hero-monitor-label,
  .hero-monitor-pos {
    letter-spacing: 0.04em;
  }
  .hero-monitor-bar {
    gap: 8px;
    padding-inline: 12px;
  }
}

/* The homepage form forces its two submit buttons side by side; at 360 the
   labels touched the button edges and "CALL" clipped. Under 480 they stack. */
@media (max-width: 479px) {
  #start .lf-send > .btn {
    flex-basis: 100%;
  }
}

/* On a phone the two-column stills grid put the landscape frame fourth,
   which left the third and fifth stills each alone beside an empty cell;
   the landscape frame goes last and closes the grid. */
@media (max-width: 767px) {
  .stills-strip__wide {
    order: 1;
  }
}

/* Quiet links that wrap at 360 left one word on the second line. */
@media (max-width: 479px) {
  .btn--quiet {
    text-wrap: balance;
  }
}

/* On a phone the Legal column runs as one row, and the column rule above
   that folds every gap into link padding fused PRIVACYTERMSSECURITY into one
   word; the row keeps its 20px gaps and its label sits on a line of its own. */
@media (max-width: 479px) {
  footer nav[aria-label="Legal"] {
    gap: 4px 20px !important;
  }
  footer nav[aria-label="Legal"] > span:first-child {
    flex-basis: 100%;
    margin-bottom: 4px;
  }
}

/* At 360 the "AS SEEN IN" row wrapped its second citation onto a line of its
   own; the label takes the first line and the two citations share the next. */
@media (max-width: 399px) {
  .press-hero > span.u-mono-label:first-child {
    flex-basis: 100%;
  }
}

/* On a phone the step tag ("A 15-MINUTE DISCOVERY CALL") sat inline after
   one name and under the next, depending on length; below 768 it always
   takes its own line. */
@media (max-width: 767px) {
  .stage-head > .u-mono-label {
    flex-basis: 100%;
  }
}

/* The four-step pipeline kept a 560px column and left the right half of the
   container empty for four screens on a desktop. From 1024 the "You get"
   card sits beside the step body; below that it follows it as before. */
.stage-out {
  margin-top: 18px;
  max-width: var(--measure-body);
}
@media (min-width: 1024px) {
  .stage-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(260px, 36%);
    column-gap: clamp(28px, 4vw, 64px);
    align-items: start;
  }
  .stage-head {
    grid-column: 1 / -1;
  }
  .stage-out {
    margin-top: 16px;
    max-width: none;
  }
}

/* On a tablet the drawer centred four links in a 1180px-tall overlay, with
   250px of nothing above and below them; the list starts near the top and
   the two actions keep the bottom edge, where a thumb reaches. */
@media (min-width: 768px) and (max-width: 1023px) {
  #nav-drawer nav {
    justify-content: flex-start;
    padding-top: clamp(32px, 8vh, 96px);
  }
}

/* Phone footer columns are 144px wide; a link the width of THE UNREAL COMPANY
   ran past the viewport edge instead of wrapping inside its column. */
@media (max-width: 479px) {
  .foot-link {
    max-width: 100%;
  }
}

/* The portal button's blade is a flex item and shrank to nothing at 360
   before the label would wrap; the label wraps first now. */
.fx-cta .fx-blade {
  flex: none;
}

/* =============================================================
   REFINEMENT PASS (2 Sep 2026) — the surface, after the audit
   ============================================================= */

/* Buttons carry a label and nothing else; the blade belongs to the eyebrow. */
.btn .fx-blade,
.fx-cta .fx-blade {
  display: none;
}
/* One link idiom: a text link carrying a hairline, which brightens on hover.
   The quiet button, the partnership door and the hero's piece link share it. */
.btn--quiet,
.hero-alt,
.hero-meta-link {
  padding-inline: 0;
  color: var(--text-primary);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 8px;
  text-decoration-color: var(--line-4);
  transition: text-decoration-color var(--dur-base) var(--ease-out, ease);
}
.btn--quiet:hover,
.btn--quiet:focus-visible,
.hero-alt:hover,
.hero-alt:focus-visible,
.hero-meta-link:hover,
.hero-meta-link:focus-visible {
  color: var(--text-primary);
  text-decoration-color: currentColor;
  text-underline-offset: 8px;
}

/* Media without frames. Film and stills sit edge to edge in hard-cornered
   frames; the hairline card is kept for interactive objects only. */
.reel-rail .card,
figure.card:has(> video),
.stills-strip > figure,
.ugc-media,
.fmt-tiles .fmt-tile,
.hero-strip .strip-cell {
  border: 0;
  border-radius: 0;
  background: #000;
}
.reel-rail .card--hover:hover,
figure.card--hover:has(> video):hover,
.ugc-card:hover .ugc-media {
  transform: none;
}
.fmt-tiles .fmt-tile-media,
.fmt-tiles .fmt-tile-media img {
  border-radius: 0;
}
/* Decoration numerals and per-tile chrome are gone: the sequence numbers
   stay only where order carries information (pipeline steps, the reel
   counter, the case-study beats). */
.ugc-badge,
.fmt-tile .fmt-num,
.fmt-tile-go,
.wc-card__tags {
  display: none;
}
/* Textures: grain stays on video surfaces; the stripes go. The tiled U-mark
   field behind every closing call to action stays (Noah, 2 Sep 2026: "add
   back the U background logo image that we had on all pages"). */
.tex-stripes::before,
.tex-stripes--diag::before {
  display: none;
}
/* The same U-mark field as an element, for closing sections that already
   spend their ::before on something else (the homepage brief sits on a
   photograph; the partnership close on grain). Placed after any backdrop
   layers and before the content, which is position:relative above it. */
.cta-field {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url("assets/u-mark-white-176.png");
  background-repeat: repeat;
  background-size: 88px auto;
  opacity: 0.075;
  mask-image: radial-gradient(115% 88% at 50% 50%, transparent 16%, #000 68%);
  -webkit-mask-image: radial-gradient(115% 88% at 50% 50%, transparent 16%, #000 68%);
}
/* Sections meet on spacing, not on hairlines. The inline dividers each page
   authored are neutralised here rather than edited out of 40 places. */
main > section[style*="border-bottom"],
main > section[style*="border-top"] {
  border-top-color: transparent !important;
  border-bottom-color: transparent !important;
}
/* Footer wordmark, solid and tonal rather than hollow. --ink-200 on the
   canvas was a 1.3:1 step and read as a smudge (Noah, 2 Sep 2026: "make it
   brighter like it used to be"); --ink-500 keeps it a tone, not a headline. */
.footer-wordmark {
  color: var(--ink-500) !important;
  -webkit-text-stroke: 0 !important;
}
/* Data that stays in monospace, wherever the old label class is still on it. */
.wg-reel__feature-facts,
.hero-meta-pos,
.fact-value,
.vs-file,
.vs-kind,
.film-meta {
  font-family: var(--font-mono);
  font-weight: 400;
  letter-spacing: 0.04em;
}
/* Labels that are sentences read as sentences. */
.hero-alt,
.hero-meta-link {
  text-transform: none;
  letter-spacing: 0.01em;
  font-size: 0.875rem;
}

/* =============================================================
   CONVERSION PATH PASS (2 Sep 2026)
   ============================================================= */
/* Phones carry the primary path in the bar itself. */
.nav-cta-mobile {
  display: none;
}
@media (max-width: 1023px) {
  .nav-cta-mobile {
    display: inline-flex;
    margin-left: auto;
    margin-right: 8px;
    padding: 0 14px;
  }
  .nav-burger {
    flex: none;
    padding: 0 14px;
  }
}
/* 390 wide: logo, primary and menu share 350px. The lockup steps down a size
   and the two controls lose their outer padding; measured 366px at 390. */
@media (max-width: 479px) {
  .nav-logo img {
    height: 26px !important;
  }
  .nav-cta-mobile,
  .nav-burger {
    padding: 0 12px;
    height: 38px;
  }
}
@media (max-width: 359px) {
  .nav-cta-mobile {
    display: none;
  }
}
/* While the brief is on screen nothing pinned to the bottom edge covers it. */
html[data-form-in-view] .qbar {
  display: none !important;
}
@media (max-width: 767px) {
  html[data-form-in-view] #umg-cookie-consent {
    visibility: hidden;
  }
}
.drawer-note {
  margin-top: 4px;
}
.proof-band .btn--quiet {
  flex: none;
}

/* =============================================================
   PARTNERSHIP + HOW IT WORKS CONDENSE PASS (2 Sep 2026)
   Both pages were argument-length prose. The copy is cut to what the
   reader needs to decide, and what was said in paragraphs is now said
   in artifacts: a fact ledger under each hero, two "who carries what"
   cards, framed steps, a manifest beside the master it lists, and
   answers laid out as a grid instead of a list.
   ============================================================= */

/* ---- Hero fact ledger: four facts, value over label ---- */
.pt-facts {
  list-style: none;
  margin: clamp(30px, 4vh, 44px) 0 0;
  padding: clamp(18px, 2.4vh, 24px) 0 0;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px clamp(16px, 2.4vw, 32px);
  max-width: 920px;
}
.pt-facts > li {
  min-width: 0;
}
.pt-facts .fact-value {
  display: block;
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1;
  font-size: clamp(1.5rem, 2.6vw, 2.25rem);
  color: var(--text-primary);
}
.pt-facts .fact-label {
  display: block;
  margin-top: 8px;
  color: var(--text-tertiary);
}
@media (max-width: 767px) {
  .pt-facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ---- Who carries what: two ledgers and the line that pays them ---- */
.pt-carry {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(12px, 1.6vw, 20px);
  margin-top: clamp(32px, 5vh, 48px);
}
.pt-carry__card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
  padding: clamp(22px, 2.6vw, 32px);
  border-radius: var(--radius-md);
  border: 1px solid var(--line-2);
  background: var(--surface-card);
}
.pt-carry__card--us {
  border-color: var(--line-3);
  background: linear-gradient(180deg, var(--ink-200), var(--ink-150));
  box-shadow: var(--elev-card);
}
.pt-carry__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.pt-carry__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.pt-carry__list li {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 7px 10px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  color: var(--text-secondary);
}
.pt-carry__card--us .pt-carry__list li {
  border-color: var(--line-4);
  color: var(--text-primary);
}
.pt-carry__foot {
  margin-top: auto !important;
  padding-top: 14px;
  border-top: 1px solid var(--border-subtle);
}
.pt-carry__paid {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: minmax(150px, 13rem) minmax(0, 1fr);
  align-items: baseline;
  gap: 8px clamp(20px, 3vw, 48px);
  padding: 18px clamp(18px, 2.4vw, 28px);
  border: 1px dashed var(--line-4);
  border-radius: var(--radius-md);
}
@media (max-width: 767px) {
  .pt-carry {
    grid-template-columns: minmax(0, 1fr);
  }
  .pt-carry__paid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---- Access ledger beside the honest bit ---- */
.pt-access {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
  margin-top: clamp(32px, 4.5vh, 52px);
}
.pt-quote {
  border-left: 2px solid var(--text-primary);
  padding-left: clamp(18px, 2.4vw, 28px);
}
@media (max-width: 1023px) {
  .pt-access {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---- Definition grids: the terms, and the five settled questions.
   Cards in a grid rather than a hairline list, each with its index drawn in
   the site's outlined numeral. The grid variant only changes layout; the
   dt/dd type roles above still apply. ---- */
.pt-terms--grid,
.hiw-settled--grid {
  border-top: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(12px, 1.6vw, 20px);
}
.pt-terms--grid .pt-terms__row,
.hiw-settled--grid .hiw-settled__row {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  padding: clamp(20px, 2.4vw, 28px);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-card);
}
.pt-terms--grid .pt-terms__row dd,
.hiw-settled--grid .hiw-settled__row dd {
  max-width: none;
}
.pt-terms--grid .rule-num {
  margin-bottom: 6px;
}
.pt-terms__row--action {
  border-style: dashed;
  background: transparent;
}
.hiw-settled__row--wide {
  grid-column: 1 / -1;
}
@media (min-width: 1024px) {
  .hiw-settled--grid .hiw-settled__row--wide {
    display: grid;
    grid-template-columns: minmax(150px, 13rem) minmax(0, 1fr);
    align-items: baseline;
  }
}
@media (max-width: 767px) {
  .pt-terms--grid,
  .hiw-settled--grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---- How It Works: four framed steps in a row ---- */
.hiw-steps {
  list-style: none;
  margin: clamp(36px, 5vh, 56px) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(14px, 1.8vw, 24px);
}
.hiw-step {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.hiw-step__frame {
  position: relative;
  margin: 0;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-md);
  border: 1px solid var(--line-2);
  background: var(--surface-card);
}
.hiw-step__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--dur-slow) var(--ease-out, ease);
}
.hiw-step:hover .hiw-step__frame img {
  transform: scale(1.04);
}
.hiw-step__num {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  color: #fff;
  background: rgba(10, 10, 11, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: var(--radius-sm);
  backdrop-filter: blur(6px);
}
.hiw-step__tag {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
}
.hiw-step__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-top: 16px;
}
.hiw-step__out {
  display: block;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border-subtle);
  color: var(--text-tertiary);
}
/* Bodies of different lengths float each column's YOU GET row to its own
   height; subgrid shares one row set across the band, as the steps-h rail
   already does. */
@supports (grid-template-rows: subgrid) {
  .hiw-steps {
    grid-auto-rows: auto auto auto 1fr auto;
  }
  .hiw-step {
    display: grid;
    grid-row: span 5;
    grid-template-rows: subgrid;
  }
}
@media (max-width: 1023px) {
  .hiw-steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: clamp(28px, 4vh, 40px);
  }
}
@media (max-width: 539px) {
  .hiw-steps {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---- How It Works: the manifest beside the master it lists ---- */
.hiw-delivery {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(16px, 2.4vw, 32px);
  align-items: start;
  margin-top: clamp(36px, 5vh, 56px);
}
.hiw-delivery .hiw-master {
  margin: 0;
}
@media (max-width: 1023px) {
  .hiw-delivery {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---- How It Works: the four rules, numbered ---- */
.hiw-rules {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(12px, 1.6vw, 18px);
}
.hiw-rules li {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-md);
  background: rgba(10, 10, 11, 0.55);
  backdrop-filter: blur(6px);
}
@media (max-width: 539px) {
  .hiw-rules {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* Phones: a stacked column of four framed steps measured ~1,100px taller than
   the old timeline at 390. Each step goes horizontal instead, the frame as a
   narrow portrait beside its copy, so the sequence still reads without a
   full-width image per step. Declared after the subgrid block so both levels
   opt back out of it, as the format rail does. */
@media (max-width: 539px) {
  .hiw-steps {
    grid-auto-rows: auto;
    row-gap: clamp(22px, 3.5vh, 32px);
  }
  .hiw-step {
    display: grid;
    grid-row: auto;
    grid-template-columns: 108px minmax(0, 1fr);
    grid-template-rows: auto auto 1fr auto;
    column-gap: 14px;
  }
  .hiw-step__frame {
    grid-row: 1 / span 4;
    aspect-ratio: 3 / 4;
  }
  .hiw-step__meta {
    margin-top: 0;
    flex-wrap: wrap;
  }
  /* The STEP label beside the frame already numbers it; the badge and the
     Concept tag collided in a 108px frame. */
  .hiw-step__num {
    display: none;
  }
}

/* =============================================================
   PARTNERSHIP + HOW IT WORKS · RESPONSIVE REVIEW (2 Sep 2026)
   ============================================================= */
/* A subgrid inherits the parent's row-gap between ITS OWN tracks, so the
   28-40px band gap between step rows at tablet widths was also opening
   between each step's frame, meta, title, body and YOU GET line (measured
   ~60px frame-to-meta at 768). The step's own margins carry that rhythm;
   the inner gap goes to zero and the band gap stays between rows. */
@supports (grid-template-rows: subgrid) {
  .hiw-step {
    row-gap: 0;
  }
}
/* Phones: three portrait stills stacked full-width cost ~1,700px at 390,
   most of it the same slate the reader had already seen. A snap rail keeps
   all three within one screen and matches the format rail on the homepage. */
/* media-treatments.css loads after this sheet and declares .pt-slate as a grid
   unconditionally, so the rail needs one more level of specificity. */
@media (max-width: 767px) {
  .u-container--content > .pt-slate {
    display: flex;
    grid-template-columns: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 12px;
    padding-bottom: 4px;
  }
  .u-container--content > .pt-slate::-webkit-scrollbar {
    display: none;
  }
  .u-container--content > .pt-slate > .pt-slate__item {
    flex: 0 0 72%;
    scroll-snap-align: start;
  }
}
/* The manifest sheet runs ~470px beside a 16:9 master at ~280px on desktop;
   centred, the pair reads as one exhibit rather than a document with a
   picture hung off its top corner. */
@media (min-width: 1024px) {
  .hiw-delivery {
    align-items: center;
  }
}
/* The outlined index numerals were struck at 16% white on 5% cards and read
   as blank until hover on both pages (measured at every width). The stronger
   divider token keeps them quiet without making them invisible. */
.pt-terms--grid .rule-num,
.hiw-rules .rule-num {
  -webkit-text-stroke-color: var(--line-4);
}
