/* dverti — one stylesheet (stage 300 reshape).

   Contract: runs/agency-2026-09-22/300-site-reshape/build/ART-DIRECTION.md.
   Palette is Ando's and nothing else: #0A0A0B / #141416 / #F2F2F2 / #8A8A93 / #FFD11A. Every
   other value is an alpha of one of those five.
   NO `text-transform` anywhere (house rule since stage 80): caps are written in the DOM.
   Motion: only transform and opacity animate (plus two short clip-path glitch bursts, named where
   they sit); every animation has a reduced-motion answer at the bottom of this file. */

@font-face {
  font-family: "Space Grotesk";
  src: url("/assets/fonts/space-grotesk-var.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #0A0A0B;
  --surface: #141416;
  --text: #F2F2F2;
  --muted: #8A8A93;
  --accent: #FFD11A;

  --line: rgb(242 242 242 / 10%);
  --line-soft: rgb(242 242 242 / 6%);

  /* 42 %: the control edge. Composites to #6B6B6C = 3.72:1 on --bg, 3.46:1 on --surface
     (WCAG 1.4.11 needs 3:1). */
  --ghost-edge: rgb(242 242 242 / 42%);

  --s1: 8px;
  --s2: 16px;
  --s3: 24px;
  --s4: 32px;
  --s5: 48px;
  --s6: 64px;
  --s7: 96px;
  --s8: 160px;

  --pad: 20px;
  --max: 1320px;

  /* UI transitions: Ando's ruling 2026-09-22 (140/200 ms, ease-out). Entrances are animations
     and run longer by contract (ART-DIRECTION §11). */
  --d-fast: 140ms;
  --d-base: 200ms;
  --d-enter: 700ms;
  --d-slide: 520ms;
  --e-out: cubic-bezier(0.16, 1, 0.3, 1);
  --e-out-soft: cubic-bezier(0.33, 1, 0.68, 1);

  --f: "Space Grotesk", "Helvetica Neue", helvetica, arial, sans-serif;
}

@media (min-width: 760px) {
  :root { --pad: 40px; }
}

*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 72px;
  background: var(--bg);

  /* stylelint-disable-next-line property-no-vendor-prefix -- the only form iOS honours */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;

  /* no background here: the page ground is html's, so the fixed light field (z-index -2) can sit
     between the ground and the sections (round 2, Ando §6) */
  color: var(--text);
  font-family: var(--f);
  font-size: 1.0625rem;
  line-height: 1.55;
  font-weight: 400;
  text-wrap: pretty;
  -webkit-font-smoothing: antialiased;
}

img, video, canvas {
  display: block;
  max-width: 100%;
}

h1, h2, h3 {
  margin: 0;
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.02;
  text-wrap: balance;
}

p { margin: 0; }

ul, ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

a { color: inherit; }

button { font: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip {
  position: absolute;
  top: -100px;
  left: var(--pad);
  z-index: 100;
  padding: 12px 16px;
  background: var(--accent);
  color: var(--bg);
  font-weight: 700;
  text-decoration: none;
}

.skip:focus { top: 12px; }

.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.sep { color: var(--muted); }

.dot { color: var(--accent); }

.link {
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--ghost-edge);
  transition: border-color var(--d-base) var(--e-out), color var(--d-base) var(--e-out);
}

.link:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.icon {
  width: 20px;
  height: 20px;
  flex: none;
  fill: none;
  stroke: currentcolor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  gap: 10px;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 22px;
  border: 1px solid transparent;
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  background: none;
  color: var(--text);
  transition: transform var(--d-fast) var(--e-out-soft),
    background-color var(--d-base) var(--e-out),
    border-color var(--d-base) var(--e-out),
    color var(--d-base) var(--e-out);
}

.btn:hover { transform: translateY(-2px); }

.btn:active { transform: translateY(0) scale(0.98); }

.btn--fill {
  background: var(--accent);
  color: var(--bg);
}

.btn--fill:hover { background: var(--text); }

.btn--ghost { border-color: var(--ghost-edge); }

.btn--ghost:hover { border-color: var(--text); }

.btn .icon--arrow {
  width: 16px;
  height: 16px;
  stroke-width: 2;
}

/* ================================================================ HERO ==
   One box, 100svh, never resized by its content. Layers bottom→top: poster (the film's first
   frame), video, end layer (plate → WebGL objects → the real logo), UI. Every media layer uses
   object-fit: cover centred, and hero-live.js maps its scene with the same cover maths, so the
   layers stay registered at any viewport. */

.hero {
  position: relative;
  height: 100vh;
  height: 100svh;
  min-height: 460px;
  overflow: hidden;
  background: var(--bg);
  isolation: isolate;
}

.hero__poster,
.hero__plate { display: contents; }

.hero__img,
.hero__v,
.hero__gl {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: 50% 50%;
}

/* Round 2 revision 1 (LCP, measured in build/evidence/lcp-probe.txt): Chrome does not count an
   image that exactly covers the viewport as a Largest Contentful Paint candidate (it treats it as a
   background). With the Sound button gone the hero had no other candidate, so LCP fell on whatever
   came later. Pre-live: the poster keeps the video's exact box (same size, same cover crop, so the
   swap lands pixel-on-pixel) and loses a 1 px ring by clip-path instead of by a smaller box; Chrome
   still takes it as the LCP (build/evidence/prelive/lcp-clip-probe.txt). */
.hero__poster .hero__img {
  clip-path: inset(1px);
}

/* Letterboxed on the page ground when cover would crop the logo — the 16:9 film on squarish
   desktop windows only ((viewport aspect / 1.7778) < 0.86 -> max-aspect-ratio 1.5289). Round 3,
   Ando: the 9:16 film on tall phones is CROPPED (cover), never letterboxed. */
@media (min-aspect-ratio: 100001/100000) and (max-aspect-ratio: 15289/10000) {
  .hero__img,
  .hero__v { object-fit: contain; }
}

.hero__v {
  opacity: 0;
  transition: opacity 240ms linear;
}

.hero[data-state="playing"] .hero__v,
.hero[data-state="end"] .hero__v { opacity: 1; }

.hero__end {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 400ms linear, visibility 0s linear 400ms;
}

.hero[data-state="end"] .hero__end,
.hero[data-state="still"] .hero__end {
  opacity: 1;
  visibility: visible;
  transition: opacity 400ms linear, visibility 0s;
}

/* The real logo, placed by main.js on the scene's logo box (--mx/--my/--mw in px). */
.hero__mark {
  position: absolute;
  left: var(--mx, 32%);
  top: var(--my, 44%);
  width: var(--mw, 36%);
  aspect-ratio: 1818 / 436;
}

.hero__logo {
  width: 100%;
  height: auto;
}

/* Glitch burst: two slices of the same mark (one off-white, one yellow) jump sideways for 240 ms.
   clip-path is a paint property; it is used here for one small box, a quarter-second at a time,
   every few seconds — named, bounded, and off under reduced motion. */
.hero__mark::before,
.hero__mark::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0;
  mask: url("/assets/brand/dverti-logo-1818.webp") center / 100% 100% no-repeat;
  pointer-events: none;
}

.hero__mark::before { background: var(--text); }

.hero__mark::after { background: var(--accent); }

.hero__mark.is-glitch .hero__logo { animation: mark-jolt 240ms steps(1, end) 1; }

.hero__mark.is-glitch::before { animation: mark-slice-a 240ms steps(1, end) 1; }

.hero__mark.is-glitch::after { animation: mark-slice-b 240ms steps(1, end) 1; }

@keyframes mark-jolt {
  0% {
    transform: translateX(0);
    opacity: 1;
  }

  20% {
    transform: translateX(-0.6%);
    opacity: 0.85;
  }

  45% {
    transform: translateX(0.9%);
    opacity: 1;
  }
  70% { transform: translateX(-0.3%); }
  100% { transform: translateX(0); }
}

@keyframes mark-slice-a {
  0% {
    opacity: 1;
    clip-path: inset(12% 0 64% 0);
    transform: translateX(-3.2%);
  }

  30% {
    opacity: 1;
    clip-path: inset(58% 0 22% 0);
    transform: translateX(2.4%);
  }

  60% {
    opacity: 1;
    clip-path: inset(34% 0 48% 0);
    transform: translateX(-1.4%);
  }

  100% {
    opacity: 0;
    clip-path: inset(50% 0 50% 0);
    transform: none;
  }
}

@keyframes mark-slice-b {
  0% {
    opacity: 0.9;
    clip-path: inset(70% 0 12% 0);
    transform: translateX(2.6%);
  }

  35% {
    opacity: 0.9;
    clip-path: inset(22% 0 66% 0);
    transform: translateX(-2%);
  }

  70% {
    opacity: 0.8;
    clip-path: inset(44% 0 40% 0);
    transform: translateX(1.2%);
  }

  100% {
    opacity: 0;
    clip-path: inset(50% 0 50% 0);
    transform: none;
  }
}

/* The heartbeat: a halo expanding from the logo's own dot. The dot itself is never redrawn —
   the halo sits over its measured centre (96.48 % / 83.49 %, Ø 6.99 % of the mark width). */
.hero__dot {
  position: absolute;
  left: 96.48%;
  top: 83.49%;
  width: 6.99%;
  aspect-ratio: 1;
  border-radius: 50%;
  translate: -50% -50%;
  box-shadow: 0 0 0 2px var(--accent);
  opacity: 0;
  pointer-events: none;
}

.hero[data-state="end"] .hero__dot { animation: dot-beat 2.4s var(--e-out) 1.2s infinite; }

@keyframes dot-beat {
  0% {
    opacity: 0.75;
    transform: scale(1);
  }

  60% {
    opacity: 0;
    transform: scale(2.4);
  }

  100% {
    opacity: 0;
    transform: scale(2.4);
  }
}

.hero__ui {
  position: absolute;
  inset: auto 0 0;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: end;
  gap: var(--s2);
  padding: 0 var(--pad) max(20px, env(safe-area-inset-bottom));
  pointer-events: none;
}

.hero__ui > * { pointer-events: auto; }

.hero__btn {
  display: inline-flex;
  gap: 10px;
  align-items: center;
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--ghost-edge);
  background: rgb(10 10 11 / 55%);
  color: var(--text);
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color var(--d-base) var(--e-out), color var(--d-base) var(--e-out);
}

.hero__btn:hover {
  border-color: var(--text);
}

/* Revision 1 (reviewer MINOR-1): the controls own FIXED slots and swap by visibility, never by
   display, so the landing moves no box: no layout shift. Round 2: the Sound and "Play the film"
   buttons are gone (Ando); the motion toggle keeps its slot. */
.hero__btn[hidden] {
  display: inline-flex;
  visibility: hidden;
}

.hero__motion {
  grid-row: 1;
  grid-column: 3;
  justify-self: end;
}

.hero__motion[aria-pressed="false"] .icon__resume,
.hero__motion[aria-pressed="true"] .icon__pause { display: none; }

.hero__motion[aria-pressed="true"] .icon__resume { display: inline; }

.hero[data-motion="paused"] .hero__dot { animation-play-state: paused; }

/* The tilt control exists only where the browser demands a permission prompt (iOS); it takes the
   empty left slot, so showing it moves nothing. */
.hero__tilt {
  grid-row: 1;
  grid-column: 1;
  justify-self: start;
}

.hero__chev {
  grid-row: 1;
  grid-column: 2;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  color: var(--text);
  animation: chev-bob 2.4s ease-in-out infinite;
}

.hero__chev .icon {
  width: 28px;
  height: 28px;
}

.hero[data-motion="paused"] .hero__chev { animation-play-state: paused; }

@keyframes chev-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(6px); }
}

/* ================================================================ NAV == */

.nav-probe { height: 0; }

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid var(--line);
  background: rgb(10 10 11 / 82%);
  backdrop-filter: blur(14px);
}

.nav__in {
  display: flex;
  gap: var(--s3);
  align-items: center;
  justify-content: space-between;
  max-width: var(--max);
  min-height: 64px;
  margin-inline: auto;
  padding-inline: var(--pad);
}

.nav__logo {
  display: block;
  padding-block: 12px;
}

.nav__logo img {
  width: 100px;
  height: auto;
}

.nav__toggle {
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--ghost-edge);
  background: none;
  color: var(--text);
  font-weight: 500;
  cursor: pointer;
}

.nav__menu {
  display: flex;
  gap: var(--s4);
  align-items: center;
}

.nav__link {
  position: relative;
  padding-block: 12px;
  color: var(--text);
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
}

.nav__link::before {
  content: "";
  position: absolute;
  top: 50%;
  left: -12px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  transform: translateY(-50%) scale(0.4);
  transition: opacity var(--d-base) var(--e-out), transform var(--d-base) var(--e-out);
}

.nav__link:hover::before,
.nav__link[aria-current="true"]::before {
  opacity: 1;
  transform: translateY(-50%) scale(1);
}

.nav__cta {
  min-height: 40px;
  padding: 0 16px;
  font-size: 0.9375rem;
}

@media (max-width: 759px) {
  /* closed: the links fold away, the one filled CTA stays in the bar (AD §15) */
  .nav__menu[data-open="false"] {
    display: flex;
    margin-left: auto;
  }

  .nav__menu[data-open="false"] .nav__link { display: none; }

  .nav__toggle { order: 2; }

  .nav__in { gap: 10px; }

  .nav__logo img { width: 84px; }

  .nav__menu[data-open="false"] .nav__cta {
    min-height: 40px;
    padding: 0 12px;
    font-size: 0.875rem;
  }

  .nav__menu[data-open="true"] {
    position: absolute;
    top: 100%;
    right: 0;
    left: 0;
    flex-direction: column;
    gap: 0;
    align-items: stretch;
    padding: var(--s2) var(--pad) var(--s3);
    border-bottom: 1px solid var(--line);
    background: var(--bg);
    animation: menu-in var(--d-base) var(--e-out);
  }

  .nav__menu[data-open="true"] .nav__link {
    padding: 14px 0;
    border-bottom: 1px solid var(--line-soft);
    font-size: 1.25rem;
  }

  .nav__menu[data-open="true"] .nav__link::before { display: none; }

  .nav__menu[data-open="true"] .nav__cta {
    margin-top: var(--s3);
    min-height: 48px;
  }
}

@media (min-width: 760px) {
  .nav__toggle { display: none; }
}

@keyframes menu-in {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* ============================================================ INTRO == */

/* Round 2 (Ando §6): sections are NOT stacking contexts and do not clip vertically. Every plate
   (z -2) and scrim/glow (z -1) therefore lives in the page's own background layers, above the fixed
   light field (z -3) and below ALL section content, and can overhang into the neighbouring section
   behind that section's text. overflow-x: clip only stops horizontal spill. */
.intro {
  position: relative;
  overflow-x: clip;
  padding-bottom: clamp(72px, 12vw, 176px);
}

.intro__bg,
.studio__bg,
.how__bg,
.ways__bg {
  position: absolute;
  inset: -18% 0;
  z-index: -2;
  background-position: 50% 60%;
  background-size: cover;
  opacity: 0.9;
  mask-image: linear-gradient(to bottom, transparent 0%, #000 22%, #000 78%, transparent 100%);
  will-change: transform;
}

.intro__bg {
  /* no upward overhang: above is the opaque hero, and a plate hidden behind it would still be
     counted as the largest paint (measured: Lighthouse picked it as LCP) */
  inset: 0 0 -18%;
  background-image: image-set(url("/assets/bg/plate-a-liquid-grain-960.webp") type("image/webp") 1x, url("/assets/bg/plate-a-liquid-grain-960.jpg") type("image/jpeg") 1x);
}

@media (min-width: 900px) {
  .intro__bg {
    background-image: image-set(url("/assets/bg/plate-a-liquid-grain-1920.webp") type("image/webp") 1x, url("/assets/bg/plate-a-liquid-grain-1920.jpg") type("image/jpeg") 1x);
  }
}

/* Revision 1 (reviewer MINOR-2): a scrim between plate A and the headline. The plate's yellow
   streak measured 2.42-2.77:1 under "not months."; at 55 % of the page ground over the plate, the
   brightest streak pixel composites to about rgb(120 100 18) -> 5.2:1 for #F2F2F2 (re-measured on
   rendered pixels, build/evidence/rev1/). */
.intro::after {
  content: "";
  position: absolute;
  inset: -18% 0;
  z-index: -1;
  mask-image: linear-gradient(to bottom, transparent 0%, #000 22%, #000 78%, transparent 100%);
  background: rgb(10 10 11 / 55%);
  pointer-events: none;
}

.marq {
  overflow: hidden;
  border-bottom: 1px solid var(--line);
  background: rgb(10 10 11 / 60%);
}

.marq__track {
  display: flex;
  width: max-content;
  animation: marq 38s linear infinite;
}

.marq:hover .marq__track { animation-play-state: paused; }

.marq__row {
  display: flex;
  flex: none;
  align-items: center;
}

.marq__row li {
  display: inline-flex;
  align-items: center;
  padding-block: 20px;
  font-size: clamp(1rem, 1.8vw, 1.375rem);
  font-weight: 500;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* the separator is the logo's dot, never an icon or emoji (P7) */
.marq__row li::after {
  content: "";
  width: 8px;
  height: 8px;
  margin-inline: clamp(20px, 3vw, 40px);
  border-radius: 50%;
  background: var(--accent);
}

.marq__row li.is-glitch { animation: word-glitch 260ms steps(1, end) 1; }

@keyframes marq {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@keyframes word-glitch {
  0% {
    transform: translateX(-3px) skewX(-8deg);
    text-shadow: 3px 0 var(--accent), -3px 0 rgb(242 242 242 / 50%);
  }

  25% {
    transform: translateX(4px);
    text-shadow: -4px 0 var(--accent);
    opacity: 0.6;
  }

  50% {
    transform: translateX(-2px) skewX(6deg);
    text-shadow: 2px 0 rgb(242 242 242 / 60%);
    opacity: 1;
  }

  75% {
    transform: translateX(1px);
    text-shadow: none;
  }

  100% {
    transform: none;
    text-shadow: none;
  }
}

.intro__in { padding-top: clamp(64px, 11vw, 168px); }

/* Revision 1 (reviewer MINOR-6): clamped by height as well as width, so on a 1440x900 desktop the
   whole headline sits in one screen (it then sets in 3 lines there, 4 on phones). */
.intro__h {
  font-size: clamp(3rem, min(14vw, 18svh), 14rem);
  font-weight: 300;
  line-height: 0.88;
  letter-spacing: -0.045em;
}

.intro__line {
  display: block;
  text-wrap: balance;
}

.intro__line + .intro__line { margin-top: 0.08em; }

.intro__cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-top: clamp(40px, 5vw, 72px);
}

/* ======================================================= SECTIONS == */

.sec {
  position: relative;
  padding-block: clamp(80px, 11vw, 160px);
}

.eyebrow {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-bottom: clamp(40px, 5vw, 72px);
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.08em;
}

.eyebrow::before {
  content: "";
  width: 28px;
  height: 1px;
  background: var(--ghost-edge);
}

/* ============================================================= WORK == */

/* Round 2 (Ando §6): the reel no longer sits on its own grey band with hard top/bottom lines. A warm
   glow behind the stage overhangs into the neighbouring sections and fades out (mask), so the page
   reads as one piece. overflow-x: clip keeps the off-stage slides from widening the page while
   letting the glow spill vertically. */
.work {
  overflow-x: clip;
}

.work::before {
  content: "";
  position: absolute;
  inset: -22% 0;
  z-index: -1;
  background:
    radial-gradient(38% 42% at 50% 50%, rgb(255 209 26 / 11%), transparent 72%),
    radial-gradient(70% 60% at 50% 55%, rgb(242 242 242 / 4%), transparent 75%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 28%, #000 72%, transparent 100%);
  pointer-events: none;
}

.reel {
  --fw: min(72vw, 330px);
  --fh: calc(var(--fw) * 16 / 9);
  --step: calc(var(--fw) * 0.86);

  position: relative;
}

@media (min-width: 760px) {
  .reel {
    --fh: min(72svh, 720px);
    --fw: calc(var(--fh) * 9 / 16);
    --step: calc(var(--fw) * 0.98);
  }
}

.reel__viewport {
  position: relative;
  height: calc(var(--fh) + 88px);
  touch-action: pan-y;
  user-select: none;
}

.reel__track { height: 100%; }

.reel__item {
  position: absolute;
  top: 0;
  left: 50%;
  width: var(--fw);
  margin-left: calc(var(--fw) / -2);
  cursor: pointer;
  opacity: 0;
  transform: translateX(0) scale(0.6);
  transition: transform var(--d-slide) var(--e-out), opacity var(--d-slide) var(--e-out);
}

.reel__item[data-pos="0"] {
  z-index: 3;
  cursor: default;
  opacity: 1;
  transform: none;
}

.reel__item[data-pos="-1"],
.reel__item[data-pos="1"] {
  z-index: 2;
  opacity: 1;
}

.reel__item[data-pos="-1"] { transform: translateX(calc(var(--step) * -1)) scale(0.78); }

.reel__item[data-pos="1"] { transform: translateX(var(--step)) scale(0.78); }

.reel__item[data-pos="-2"] { transform: translateX(calc(var(--step) * -1.72)) scale(0.6); }

.reel__item[data-pos="2"] { transform: translateX(calc(var(--step) * 1.72)) scale(0.6); }

@media (min-width: 1100px) {
  .reel__item[data-pos="-2"],
  .reel__item[data-pos="2"] {
    z-index: 1;
    opacity: 1;
  }
}

.reel__frame {
  position: relative;
  overflow: hidden;
  aspect-ratio: 9 / 16;
  background: var(--bg);
  outline: 1px solid var(--line);
}

.reel__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--bg);
  opacity: 0;
  transition: opacity var(--d-slide) var(--e-out);
  pointer-events: none;
}

.reel__item:not([data-pos="0"]) .reel__frame::after { opacity: 0.6; }

.reel__item[data-pos="2"] .reel__frame::after,
.reel__item[data-pos="-2"] .reel__frame::after { opacity: 0.78; }

.reel__v,
.reel__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Round 2 (Ando §3): the concept stills must never read as broken video. They carry no play
   affordance; instead the centred still breathes: a slow push-in and, every 7 s, one soft light
   sweep across it. Transform and opacity only; off under reduced motion; neighbours stay still. */
.reel__item[data-kind="concept"][data-pos="0"] .reel__img {
  animation: still-push 16s ease-in-out infinite alternate;
}

@keyframes still-push {
  from { transform: scale(1) translate3d(0, 0, 0); }
  to { transform: scale(1.07) translate3d(-1.2%, -1.6%, 0); }
}

.reel__item[data-kind="concept"] .reel__frame::before {
  content: "";
  position: absolute;
  inset: -20% -60%;
  z-index: 1;
  background: linear-gradient(105deg, transparent 42%, rgb(255 209 26 / 10%) 48%, rgb(242 242 242 / 16%) 50%, rgb(255 209 26 / 10%) 52%, transparent 58%);
  opacity: 0;
  transform: translateX(-60%);
  pointer-events: none;
}

.reel__item[data-kind="concept"][data-pos="0"] .reel__frame::before {
  animation: still-sweep 7s ease-in-out 1.2s infinite;
}

@keyframes still-sweep {
  0% {
    opacity: 0;
    transform: translateX(-60%);
  }

  12% { opacity: 1; }

  38% { opacity: 1; }

  50%,
  100% {
    opacity: 0;
    transform: translateX(60%);
  }
}

.reel__meta {
  padding-top: 18px;
  text-align: center;
  opacity: 0;
  transition: opacity var(--d-base) var(--e-out);
}

.reel__item[data-pos="0"] .reel__meta { opacity: 1; }

.reel__chip {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  color: rgb(242 242 242 / 72%); /* R2: on the stage glow the muted grey measured 4.32:1 */
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.04em;
}

/* the playing item's marker is the dot (P9) */
.reel__chip::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
}

.reel__t {
  margin-top: 4px;
  font-size: 1.125rem;
  font-weight: 500;
}

.reel__controls {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: center;
  margin-top: var(--s3);
}

.reel__btn {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border: 1px solid var(--ghost-edge);
  border-radius: 50%;
  background: none;
  color: var(--text);
  cursor: pointer;
  transition: border-color var(--d-base) var(--e-out), transform var(--d-fast) var(--e-out-soft);
}

.reel__btn:hover {
  border-color: var(--text);
  transform: translateY(-2px);
}

/* keeps its slot (no shift when auto-advance moves between the film and a poster) */
.reel__btn[hidden] { visibility: hidden; }

.reel__pause[aria-pressed="false"] .icon__resume,
.reel__pause[aria-pressed="true"] .icon__pause { display: none; }

.reel__pause[aria-pressed="true"] .icon__resume { display: inline; }

.reel__count {
  min-width: 56px;
  color: var(--muted);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.work__note {
  margin-top: var(--s5);
  color: var(--muted);
  font-size: 0.9375rem;
  text-align: center;
}

/* ========================================================= SERVICES == */

.rows { border-top: 1px solid var(--line); }

.row {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: 8px var(--s3);
  align-items: baseline;
  padding-block: clamp(28px, 4vw, 48px);
  border-bottom: 1px solid var(--line);
  transition: transform var(--d-base) var(--e-out);
}

.row__n {
  color: var(--muted);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
}

.row__h {
  font-size: clamp(2.25rem, 6.4vw, 5.5rem);
  font-weight: 300;
  letter-spacing: -0.045em;
}

.row__p {
  grid-column: 2;
  max-width: 44ch;
  color: var(--muted);
}

.row__art {
  grid-column: 2;
  width: min(64%, 260px);
  margin: var(--s2) 0 0;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--surface);
}

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

@media (min-width: 900px) {
  .row {
    grid-template-columns: 64px minmax(0, 4fr) minmax(0, 4fr) 240px;
    align-items: center;
  }

  .row__p { grid-column: 3; }

  .row__art {
    grid-column: 4;
    width: 240px;
    margin: 0;
    opacity: 0.9;
    transform: scale(0.97);
    transition: opacity var(--d-base) var(--e-out), transform var(--d-base) var(--e-out);
  }

  .row:hover .row__art {
    opacity: 1;
    transform: none;
  }

  .row:hover { transform: translateX(6px); }
}

/* ======================================================= WARM LIGHT ==
   Round 2 (Ando §5): How it works and Ways to work are lit, not black. Each carries a generated
   warm-light plate that overhangs 25 % into its neighbours and fades out, plus a slow accent glow.
   The light is the accent's alpha over the page ground: no new hue. */

.how,
.ways {
  overflow-x: clip;
}

.how__bg {
  inset: -28% 0;
  background-image: image-set(url("/assets/bg/bg-warm-a-960.webp") type("image/webp") 1x, url("/assets/bg/bg-warm-a-960.jpg") type("image/jpeg") 1x);
  background-position: 20% 30%;
  opacity: 0.7;
}

.ways__bg {
  inset: -28% 0;
  background-image: image-set(url("/assets/bg/bg-warm-b-960.webp") type("image/webp") 1x, url("/assets/bg/bg-warm-b-960.jpg") type("image/jpeg") 1x);
  background-position: 50% 100%;
  opacity: 0.85;
}

@media (min-width: 900px) {
  .how__bg {
    background-image: image-set(url("/assets/bg/bg-warm-a-1920.webp") type("image/webp") 1x, url("/assets/bg/bg-warm-a-1920.jpg") type("image/jpeg") 1x);
  }

  .ways__bg {
    background-image: image-set(url("/assets/bg/bg-warm-b-1920.webp") type("image/webp") 1x, url("/assets/bg/bg-warm-b-1920.jpg") type("image/jpeg") 1x);
  }
}

.how::before,
.ways::before {
  content: "";
  position: absolute;
  z-index: -1;
  width: min(70vw, 900px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(255 209 26 / 12%), rgb(255 209 26 / 4%) 55%, transparent);
  pointer-events: none;
  animation: glow-drift 18s ease-in-out infinite alternate;
}

.how::before {
  top: -10%;
  left: -12%;
}

.ways::before {
  right: -14%;
  bottom: -20%;
  animation-delay: -9s;
}

@keyframes glow-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(6%, 8%, 0) scale(1.12); }
}

/* Text on warm light (measured, build/evidence/r2-contrast): the muted grey that reads at 5.8:1 on
   black fell to 1.6-4.5:1 where the amber light sits under it. So inside the lit sections the small
   text is off-white at 80 % (an alpha of --text), and a soft band of page ground (50 %, feathered)
   sits behind the content column only — the light stays visible around it. */
.how .wrap,
.ways .wrap {
  position: relative;
}

.how .wrap::after,
.ways .wrap::after {
  content: "";
  position: absolute;

  /* round 2 revision 1 (reviewer R2-VIS-1): feathered on ALL four sides. The band now reaches
     14vw past the content column and fades out over that margin, intersected with the vertical
     fade, so neither a horizontal nor a vertical edge exists at any width. */
  inset: -120px -14vw -220px;
  z-index: -1;
  background: rgb(10 10 11 / 52%);
  mask-image:
    linear-gradient(to bottom, transparent 0%, #000 22%, #000 78%, transparent 100%),
    linear-gradient(to right, transparent 0%, #000 14%, #000 86%, transparent 100%);
  mask-composite: intersect;
  pointer-events: none;
}

/* ============================================================ FIELD ==
   One fixed light field behind every section (Ando §6); main.js moves it with scroll progress. */

.lightfield {
  position: fixed;
  inset: 0;
  z-index: -3;
  overflow: hidden;
  pointer-events: none;
}

.lightfield__a,
.lightfield__b {
  position: absolute;
  width: 90vmax;
  aspect-ratio: 1;
  border-radius: 50%;
  will-change: transform;
}

.lightfield__a {
  top: -30vmax;
  left: -35vmax;
  background: radial-gradient(closest-side, rgb(255 209 26 / 7%), transparent);
  transform: translate3d(calc(var(--sp, 0) * 60vw), calc(var(--sp, 0) * 40vh), 0);
}

.lightfield__b {
  right: -40vmax;
  bottom: -40vmax;
  background: radial-gradient(closest-side, rgb(255 209 26 / 5%), transparent);
  transform: translate3d(calc(var(--sp, 0) * -50vw), calc(var(--sp, 0) * -30vh), 0);
}

/* ============================================================ STEPS == */

.steps {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s5);
  padding-left: 28px;
}

/* the line exists only here, because only 02 is a true sequence (AD §20) */
.steps::before {
  content: "";
  position: absolute;
  top: 8px;
  bottom: 8px;
  left: 5px;
  width: 1px;
  background: var(--ghost-edge);
}

.step { position: relative; }

.step__dot {
  position: absolute;
  top: 10px;
  left: -28px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px rgb(255 209 26 / 14%), 0 0 24px rgb(255 209 26 / 45%);
}

.step__h {
  font-size: clamp(1.75rem, 3.6vw, 3rem);
  font-weight: 300;
  letter-spacing: -0.04em;
}

.step__p {
  max-width: 34ch;
  margin-top: 12px;
  color: var(--muted);
}

@media (min-width: 860px) {
  .steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s4);
    padding: 36px 0 0;
  }

  .steps::before {
    inset: 5px 0 auto;
    width: auto;
    height: 1px;
  }

  .step__dot {
    top: -36px;
    left: 0;
  }
}

/* ============================================================= WAYS == */

.plans {
  display: grid;
  grid-template-columns: 1fr;
  border-top: 1px solid var(--line);
}

.plan {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  min-width: 0;
  padding: var(--s5) 0;
  border-bottom: 1px solid var(--line);
}

@media (min-width: 900px) {
  .plans {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    border-bottom: 1px solid var(--line);
  }

  .plan {
    padding: var(--s5) var(--s4) var(--s5) 0;
    border-bottom: 0;
  }

  .plan + .plan {
    padding-left: var(--s4);
    border-left: 1px solid var(--line);
  }
}

/* each plan column catches the warm light on its top edge (accent detail, R2 §5) */
.plan::before {
  content: "";
  position: absolute;
  top: -1px;
  right: 20%;
  left: 0;
  height: 1px;
  background: linear-gradient(90deg, rgb(255 209 26 / 70%), rgb(255 209 26 / 0%));
}

.plan__h {
  font-size: clamp(2rem, 4vw, 3.5rem);
  font-weight: 300;
  letter-spacing: -0.045em;
}

.plan__p {
  max-width: 30ch;
  color: var(--muted);
}

.plan__cta {
  align-self: flex-start;
  margin-top: auto;
}

.plan__p + .plan__cta { margin-top: var(--s3); }

.ways__note {
  margin-top: var(--s4);
  color: var(--muted);
  font-size: 0.9375rem;
}

/* R2: small text on the warm light is off-white at 80 % (see WARM LIGHT above) */
.how .step__p,
.ways .plan__p {
  color: rgb(242 242 242 / 80%);
}

/* labels on the warm light (reviewer R2-MINOR-1: "02 — HOW IT WORKS" measured 2.64-4.05:1) */
.how .eyebrow,
.ways .eyebrow { color: rgb(242 242 242 / 80%); }

/* the note sits in the scrim's lower feather, over the brightest glow: full off-white there */
.ways .ways__note { color: var(--text); }

/* =========================================================== STUDIO == */

.studio {
  overflow-x: clip;
  padding-block: clamp(120px, 16vw, 240px);
}

.studio__bg {
  background-image: image-set(url("/assets/bg/plate-b-knit-scan-960.webp") type("image/webp") 1x, url("/assets/bg/plate-b-knit-scan-960.jpg") type("image/jpeg") 1x);
  opacity: 0.75;
}

@media (min-width: 900px) {
  .studio__bg {
    background-image: image-set(url("/assets/bg/plate-b-knit-scan-1920.webp") type("image/webp") 1x, url("/assets/bg/plate-b-knit-scan-1920.jpg") type("image/jpeg") 1x);
  }
}

/* a scrim between the plate and the words: text contrast is measured on pixels, not assumed */
.studio::before {
  content: "";
  position: absolute;
  inset: -18% 0;
  z-index: -1;
  background: linear-gradient(90deg, rgb(10 10 11 / 78%) 0%, rgb(10 10 11 / 55%) 60%, rgb(10 10 11 / 30%) 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 22%, #000 78%, transparent 100%);
}

.studio__p {
  max-width: 20ch;
  font-size: clamp(2rem, 5.2vw, 4.75rem);
  font-weight: 300;
  line-height: 1.04;
  letter-spacing: -0.04em;
}

.studio__p .w {
  opacity: var(--lit, 1);
  transition: opacity 120ms linear;
}

.studio__p--accent {
  margin-top: clamp(32px, 4vw, 56px);
  font-weight: 500;
}

/* ========================================================== CONTACT == */

.contact__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s6) var(--s7);
}

@media (min-width: 900px) {
  .contact__grid { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
}

.contact__h {
  max-width: 12ch;
  font-size: clamp(2.5rem, 6vw, 5rem);
  font-weight: 300;
  letter-spacing: -0.045em;
}

.contact__line {
  margin-top: var(--s2);
  color: var(--muted);
}

.contact__h + .contact__line { margin-top: var(--s5); }

.form {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s3);
  padding: clamp(20px, 3vw, 40px);
  border: 1px solid var(--line);
  background: var(--surface);
}

@media (min-width: 560px) {
  .form { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .field--wide { grid-column: 1 / -1; }
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.label {
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.06em;
}

.input {
  width: 100%;
  min-width: 0;
  min-height: 48px;
  padding: 12px 14px;
  border: 1px solid var(--ghost-edge);
  border-radius: 0;
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 1rem;
  transition: border-color var(--d-base) var(--e-out);
}

.input:hover { border-color: var(--text); }

.input:focus { border-color: var(--accent); }

.input--area {
  min-height: 140px;
  resize: vertical;
}

/* honeypot: display:none (browsers do not autofill it; it still submits) */
.trap { display: none; }

.form__foot {
  display: flex;
  flex-flow: row wrap;
  gap: var(--s2) var(--s3);
  align-items: center;
  justify-content: flex-start;
}

.form__send { min-width: 140px; }

.form__state {
  margin: 0;
  color: var(--muted);
  font-size: 0.9375rem;
}

.form__state[data-state="ok"] { color: var(--accent); }

.form__state[data-state="error"] { color: var(--text); }

.form__privacy {
  flex-basis: 100%;
  margin: 0;
  color: var(--muted);
  font-size: 0.8125rem;
}

.form__note {
  grid-column: 1 / -1;
  color: var(--muted);
  font-size: 0.875rem;
}

/* =========================================================== FOOTER == */

.foot {
  padding-block: var(--s6) var(--s5);
  background: linear-gradient(90deg, transparent, var(--line) 18%, var(--line) 82%, transparent) top / 100% 1px no-repeat;
}

.foot__logo {
  display: inline-block;
}

.foot__logo img {
  width: 132px;
  height: auto;
}

.foot__bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  align-items: center;
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--line);
}

.foot__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1) var(--s4);
  font-size: 0.9375rem;
}

.foot__links .link {
  display: inline-block;
  padding-block: 12px;
}

.foot__c {
  margin-left: auto;
  color: var(--muted);
  font-size: 0.875rem;
}

/* ========================================================== REVEALS ==
   The hidden state exists only under .js (set by main.js), so with no script everything is
   simply there. */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--d-enter) var(--e-out), transform var(--d-enter) var(--e-out);
  transition-delay: calc(var(--i, 0) * 70ms);
}

.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
}

/* the headline lines land with a single short glitch after they rise */
.js .intro__line.is-in { animation: line-glitch 300ms steps(1, end) calc(var(--i, 0) * 70ms + 520ms) 1; }

@keyframes line-glitch {
  0% {
    text-shadow: 6px 0 rgb(255 209 26 / 70%), -6px 0 rgb(242 242 242 / 35%);
    transform: translateX(-4px);
  }

  33% {
    text-shadow: -4px 0 rgb(255 209 26 / 60%);
    transform: translateX(5px);
  }

  66% {
    text-shadow: 2px 0 rgb(242 242 242 / 40%);
    transform: translateX(-1px);
  }

  100% {
    text-shadow: none;
    transform: none;
  }
}

/* ==================================================== REDUCED MOTION ==
   Tier 1 REMOVE: marquee travel, chevron bob, dot heartbeat, logo and line glitches, drift
   (JS stops drift, the film's autoplay, the carousel's auto-advance and the live loop).
   Tier 2 SOFTEN: reveals keep a 1 ms opacity change and lose their travel; the reel moves
   instantly.
   Tier 3 KEEP: colour/border affordances and the focus ring. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  html { scroll-behavior: auto; }

  .marq__track {
    flex-wrap: wrap;
    width: auto;
    animation: none;
  }

  .marq__row {
    flex-wrap: wrap;
    justify-content: center;
  }

  .marq__row[aria-hidden="true"] { display: none; }

  .hero__chev,
  .hero__dot,
  .hero__mark,
  .hero__mark::before,
  .hero__mark::after,
  .hero__logo,
  .intro__line,
  .marq__row li,
  .reel__img,
  .reel__frame::before { animation: none !important; }

  .js [data-reveal] { transform: none; }

  .btn:hover,
  .reel__btn:hover,
  .row:hover { transform: none; }
}

/* ============================================================= 404 == */

.nf {
  display: grid;
  place-items: center;
  min-height: 100svh;
}

.nf__in {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  align-items: flex-start;
  padding-block: var(--s6);
}

.nf__in .nav__logo img { width: 120px; }

.nf__h {
  font-size: clamp(2.5rem, 7vw, 4.5rem);
  font-weight: 300;
  letter-spacing: -0.045em;
}

.nf__p {
  max-width: 40ch;
  color: var(--muted);
}

.nf__cta { margin-top: var(--s2); }

/* ========================================================= PRIVACY == */

.prose > * { max-width: 68ch; }

.prose__h {
  font-size: clamp(2.5rem, 7vw, 4.5rem);
  font-weight: 300;
  letter-spacing: -0.045em;
}

.prose__lede {
  max-width: 44ch;
  margin-top: var(--s3);
  color: var(--muted);
  font-size: clamp(1.0625rem, 2vw, 1.25rem);
}

.prose__h2 {
  margin-top: var(--s6);
  font-size: clamp(1.125rem, 2.2vw, 1.375rem);
}

.prose p {
  margin-top: var(--s2);
  color: var(--muted);
}

.prose code {
  color: var(--text);
  font-size: 0.9em;
}

.prose strong {
  color: var(--text);
  font-weight: 500;
}

.prose__foot {
  margin-top: var(--s6);
  padding-top: var(--s3);
  border-top: 1px solid var(--line);
  font-size: 0.875rem;
}

.prose__back { margin-top: var(--s5); }
