/* =============================================================================
   Unknown Shape — v1 site
   -----------------------------------------------------------------------------
   This is a STRUCTURAL FRAME, not a finished look. The visual craft is Z's.
   Styling here is deliberately neutral so it doesn't fight your aesthetic.

   HOW TO USE THIS FILE
   - Design tokens live in :root. Change tokens first; most of the look flows
     from them. Add tokens freely (type scale, motion, etc.).
   - Sections marked "CRAFT HERE" are intentionally bare — your layer goes there.
   - Nothing here is precious. Overwrite anything.
   ========================================================================== */

/* --- Design tokens -------------------------------------------------------- */
:root {
  /* Color — placeholder neutral palette. Replace with the real system. */
  --color-bg: #ffffff;
  --color-fg: #111111;
  --color-muted: #6b6b6b;
  --color-line: #e6e6e6;
  --color-accent: #111111; /* TODO: real accent once brand direction exists */

  /* Design system color tokens — from Figma "Unknown Shape design system" > Colors. */
  /* Bali Hai (blue-gray) */
  --color-bali-hai-50: #F4F8F9;
  --color-bali-hai-100: #EBF2F4;
  --color-bali-hai-200: #DAE8EB;
  --color-bali-hai-300: #C4D6DD;
  --color-bali-hai-400: #ABC2CE;
  --color-bali-hai-500: #95AEBF;
  --color-bali-hai-600: #889EB3; /* == the old-site slate */
  --color-bali-hai-700: #6C8196; /* current hero bg */
  --color-bali-hai-800: #596A7A;
  --color-bali-hai-900: #4B5864;
  --color-bali-hai-950: #2C333A;
  /* Tuna (charcoal) */
  --color-tuna-50: #F7F7F8;
  --color-tuna-100: #EEEDF1;
  --color-tuna-200: #D7D7E0;
  --color-tuna-300: #B5B6C4;
  --color-tuna-400: #8C8EA4;
  --color-tuna-500: #6E7089;
  --color-tuna-600: #585871;
  --color-tuna-700: #48485C;
  --color-tuna-800: #3E3E4E;
  --color-tuna-900: #32323D; /* the dark we A/B'd against */
  --color-tuna-950: #25242D;
  /* Neutrals */
  --color-white: #FFFFFF;
  --color-black: #000000;

  /* Type — Figtree per the design system (loaded via Google Fonts in index.html). */
  --font-display: "Figtree", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-body: "Figtree", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;

  /* Type scale — from Figma "Unknown Shape design system" > Typography.
     Every token shares line-height 1.4 and letter-spacing 0. Sizes are fixed
     (the system defines fixed sizes). Compose a size (--fs-*) with a weight
     (--fw-*) and the line-height (--lh-text). */
  --fs-xxs: 0.625rem;  /* 10px */
  --fs-xs: 0.75rem;    /* 12px */
  --fs-sm: 0.875rem;   /* 14px */
  --fs-base: 1rem;     /* 16px */
  --fs-lg: 1.125rem;   /* 18px */
  --fs-xl: 1.25rem;    /* 20px */
  --fs-2xl: 1.5rem;    /* 24px */
  --fs-3xl: 1.875rem;  /* 30px */
  --fs-4xl: 2.25rem;   /* 36px */
  --fs-5xl: 3rem;      /* 48px */
  --fs-6xl: 3.75rem;   /* 60px */
  --fs-7xl: 4.5rem;    /* 72px */

  --fw-light: 300;
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  --lh-text: 1.4;

  /* Spacing rhythm */
  --space-section: clamp(4rem, 12vw, 9rem);
  --space-gutter: clamp(1.25rem, 5vw, 4rem);
  --measure: 38rem; /* max readable line length */
  --content-max: 69rem; /* 1104px — section content width. Figma reference: 1280px frame, 88px L/R margins. Reuse across content sections for matched margins. */
}

/* --- Reset / baseline ----------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-fg);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
img, video { max-width: 100%; height: auto; display: block; }
a { color: inherit; }

/* Visually-hidden but available to assistive tech. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- Layout helpers ------------------------------------------------------- */
.site-header,
main > section {
  padding-inline: var(--space-gutter);
  max-width: 90rem;
  margin-inline: auto;
}
main > section { padding-block: var(--space-section); }

.section-label {
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-muted);
  margin: 0 0 2rem;
}

/* --- Header / footer ------------------------------------------------------ */
.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: 1.5rem;
}
.wordmark { font-weight: 600; text-decoration: none; letter-spacing: -0.01em; }

/* Footer — full-bleed dark band (Bali Hai/700). Contact CTA near the top,
   copyright pinned to the bottom. From Figma node 1198:241. */
.site-footer {
  position: relative;
  background: var(--color-bali-hai-700);
  color: var(--color-white);
  min-height: 448px;
  padding: 24px var(--space-gutter);
  display: flex;
  flex-direction: column;
  justify-content: center; /* CTA vertically centered */
  align-items: center;
  text-align: center;
}
.site-footer__cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
  max-width: 986px;
  transform: translateY(-12px); /* matches Figma's calc(50% - 12px) centering */
}
.site-footer__heading {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--fw-medium);
  font-size: var(--fs-5xl); /* 48px Medium */
  line-height: var(--lh-text);
}
.site-footer__email {
  font-family: var(--font-display);
  font-weight: var(--fw-regular);
  font-size: var(--fs-xl); /* 20px (was 24px) */
  line-height: var(--lh-text);
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--color-white);
  padding-bottom: 6px;
  transition: opacity 200ms ease;
}
.site-footer__email:hover { opacity: 0.8; }
.site-footer__copyright {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 12px; /* pinned near the bottom, per Figma */
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--fw-light);
  font-size: var(--fs-xs); /* 12px */
  line-height: var(--lh-text);
}

/* --- 1. Hero --------------------------------------------------------------
   Full-viewport showpiece. Atmospheric gradient background lives behind the
   hero contents via z-index. Colors from the old unknownshape shader; effect
   quality inspired by monopo.vn's atmosphere (authored in pure CSS for the
   no-build constraint). See inspiration-log.md. */

:root {
  --hero-bg: var(--color-bali-hai-700); /* Bali Hai/700; matches shader color0 so no flash before WebGL initializes. */
  --hero-fg: var(--color-white); /* hero text color (light). */

  /* Logo reveal — measured from monopo.vn (masked rise + fade). Tunable. */
  --logo-rise-dur: 1s;
  --logo-fade-dur: 0.5s;
  --logo-ease: cubic-bezier(0.16, 1, 0.3, 1); /* easeOutExpo: fast rise, long smooth settle */

  /* Hero subhead fade — arrives as the logo reveal completes (~1.8s). Tunable. */
  --hero-sub-delay: 1.5s;
  --hero-sub-dur: 0.7s;

  /* Shape conveyor (post-reveal loop in the "a" slot). Dwell + start-delay live
     in the JS (see index.html); these two are shared with the pe-shift
     transition so the motion stays in sync. */
  --shape-slide-dur: 0.5s;
  --shape-ease: cubic-bezier(0.87, 0, 0.13, 1); /* easeInOutExpo */
}

.hero {
  position: relative;
  min-height: 100vh;
  overflow: hidden;
  background: var(--hero-bg);
  isolation: isolate;
  /* Content gutter — matches min(100% - 3rem, --content-max) centered, i.e. the
     same inset the grid verticals and other sections use. Shared so the logo
     and subhead anchor to the grid instead of the viewport (which let them
     drift across the gridlines on wide screens). */
  --hero-gutter: max(1.5rem, (100% - var(--content-max)) / 2);
  /* Override the shared layout helper (max-width 90rem + centering margin)
     so the hero (shader + content) bleeds edge-to-edge. The padding-inline
     from the helper is overridden too because .hero-content positions itself
     with its own left/top offsets. */
  max-width: none;
  margin-inline: 0;
  padding-inline: 0;
}

/* Parallax layer — holds the grid + canvas + content (all absolute, inset 0).
   A scroll-driven transform (set in the hero-parallax IIFE, desktop only) makes
   it lag behind the page so sections below appear to rise over the hero. The
   hero's overflow:hidden clips it as it recedes. */
.hero-inner {
  position: absolute;
  inset: 0;
  will-change: transform;
}

/* Phase 3 canvas. Layers ABOVE the decorative grid but below the content, so
   the (now-transparent-based) shader paints its cyan/lime blobs over the grid
   while calm areas stay clear and reveal the grid + flat base behind it. Sized
   to fit the hero via CSS; the WebGL drawing buffer is set in JS via setSize. */
.hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  display: block;
  pointer-events: none;
}

/* Decorative grid — sits furthest back (behind the canvas, above the flat
   --hero-bg base). Lines = Bali Hai/600, crosshair ticks = Bali Hai/300.
   Verticals anchor to the site content gutters (same inset as --content-max
   sections); horizontals sit at proportional offsets of the hero height. */
.hero-grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  --grid-inset: var(--hero-gutter);
  --grid-top: 16.67%;     /* 120 / 720 (Figma) */
  --grid-bottom: 59.17%;  /* 426 / 720 (Figma) */
  --grid-line: var(--color-bali-hai-600);
  --grid-tick: var(--color-bali-hai-300);
}
.hero-grid__v {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--grid-line);
  transform: translateX(-50%);
}
.hero-grid__v--left  { left: var(--grid-inset); }
.hero-grid__v--right { left: calc(100% - var(--grid-inset)); }
.hero-grid__h {
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grid-line);
}
.hero-grid__h--top    { top: var(--grid-top); }
.hero-grid__h--bottom { top: var(--grid-bottom); }
.hero-grid__tick {
  position: absolute;
  width: 17px;
  height: 17px;
  transform: translate(-50%, -50%);
}
.hero-grid__tick::before,
.hero-grid__tick::after {
  content: "";
  position: absolute;
  background: var(--grid-tick);
}
.hero-grid__tick::before { left: 50%; top: 0; width: 1px; height: 100%; transform: translateX(-50%); }
.hero-grid__tick::after  { top: 50%; left: 0; height: 1px; width: 100%; transform: translateY(-50%); }
.hero-grid__tick--tl { left: var(--grid-inset);              top: var(--grid-top); }
.hero-grid__tick--tr { left: calc(100% - var(--grid-inset)); top: var(--grid-top); }
.hero-grid__tick--bl { left: var(--grid-inset);              top: var(--grid-bottom); }
.hero-grid__tick--br { left: calc(100% - var(--grid-inset)); top: var(--grid-bottom); }

/* Hero content — asymmetric layout matching the latest Figma (1280×720).
   Logo top-left, subhead bottom-right. Percentages are of .hero (which is
   100vh tall, 100vw wide), so positions scale with the hero element. */
.hero-content {
  position: absolute;
  inset: 0;
  z-index: 2;
}

.hero-headline { margin: 0; line-height: 0; }

/* Logo — Figma: left:140, top:168, 480×209 on a 1280×720 frame. Left anchors to
   the content gutter + 52px so it sits just inside the left gridline at every
   width (was a viewport %, which drifted left across the gridline on wide
   screens). 52px = the logo-to-gutter gap at the 1280 design width. */
.hero-logo {
  position: absolute;
  left: calc(var(--hero-gutter) + 3.25rem);
  top: 23.33%;    /* 168 / 720  */
  width: 37.5%;   /* 480 / 1280 */
  max-width: 480px;
  min-width: 240px;
  aspect-ratio: 480 / 209;
  display: block;
}
/* Two groupings, positioned per the Figma insets within the 480x209 logo box.
   Each is a clip mask for the monopo-style reveal. */
.hero-logo-group { position: absolute; overflow: hidden; }
.hero-logo-group--1 { top: 0; right: 0; bottom: 60.86%; left: 0.35%; --logo-delay: 0.5s; }   /* "unknown" */
.hero-logo-group--2 { top: 51.67%; right: 33.96%; bottom: 0; left: 0; --logo-delay: 0.8s;  /* "shape" row, +0.3s after grouping_1 */
  /* Vertical-only mask (not overflow:hidden) so the masked reveal still clips
     the rise at top/bottom, but pe's +3px nudge isn't clipped at the right edge. */
  overflow: visible;
  clip-path: inset(0 -100px);
}
.hero-logo-group--1 img { width: 100%; height: 100%; display: block; }

/* The rising layer (masked reveal). grouping_1 is a single image; grouping_2's
   .logo-row wraps sh + slot + pe so the whole "shape" word rises as one. */
.hero-logo-group--1 img,
.logo-row {
  animation:
    logo-rise var(--logo-rise-dur) var(--logo-ease) var(--logo-delay, 0s) both,
    logo-fade var(--logo-fade-dur) var(--logo-ease) var(--logo-delay, 0s) both;
}
.logo-row { position: absolute; inset: 0; }

@keyframes logo-rise {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
@keyframes logo-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Bottom-row pieces, positioned within grouping_2's 317x101 box (logo coords,
   from Figma for_motion). sh + pe are static; pe nudges +3px right once the
   cycle begins (the shapes' 64px slot sits 3px right of the narrower "a"). */
.logo-sh,
.logo-shape-slot,
.logo-pe { position: absolute; }
.logo-sh         { left: 0;      top: 0;      width: 37.54%; height: 81.19%; }   /* 119x82 @ (0,0)   */
.logo-shape-slot { left: 40.06%; top: 18.81%; width: 20.19%; height: 63.37%;     /* 64x64  @ (127,19) */
  /* Vertical-only mask: clips the conveyor at top/bottom but lets the "a" sit
     3px left (its natural kerning) without its left edge getting clipped. */
  clip-path: inset(0 -100px);
}
.logo-pe { left: 60.88%; top: 18.81%; width: 39.12%; height: 81.19%;            /* 124x82 @ (193,19) */
  transform: translateX(0);
  transition: transform var(--shape-slide-dur) var(--shape-ease);
}
.hero-logo.is-cycling .logo-pe { transform: translateX(2.42%); }  /* +3px (3/124 of pe width) */

.logo-sh img,
.logo-pe img { width: 100%; height: 100%; display: block; }

/* Conveyor items fill the slot; the JS drives translateY for the vertical
   slide. The "a" sits 3px left of the shapes (its natural kerning) via a
   static translateX baked into its transform. */
.logo-shape-item { position: absolute; inset: 0; }
.logo-shape-item img { width: 100%; height: 100%; display: block; }
.logo-shape-item--a { transform: translateX(-4.69%); }  /* -3px (3/64 of slot width) */

@media (prefers-reduced-motion: reduce) {
  .hero-logo-group--1 img,
  .logo-row { animation: none; }
}

/* Subheading — Figma (latest): left:311, right:148, top:501 (center via
   translateY -50%). Box is ~821px at the 1280 design width so each sentence sits
   on its own line. Right edge anchors to the content gutter + 60px so it tracks
   just inside the right gridline at any width (no max-width cap, which used to
   force the longer sentence to wrap). */
.hero-subhead {
  position: absolute;
  left: 24.3%;         /* 311 / 1280 */
  right: calc(var(--hero-gutter) + 3.75rem);  /* 148 from edge at 1280 */
  top: 69.58%;         /* 501 / 720  */
  transform: translateY(-50%);
  margin: 0;
  color: var(--hero-fg);
  /* Fade in as the logo reveal completes. Opacity only — keeps the centering transform intact. */
  animation: hero-sub-fade var(--hero-sub-dur) ease var(--hero-sub-delay) both;
}
@keyframes hero-sub-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-subhead { animation: none; }
}
.hero-subhead p {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  line-height: var(--lh-text);
  letter-spacing: 0;
}
/* Line 1: semibold, white (inherits --hero-fg). Line 2: regular, Bali Hai/200. */
.hero-subhead__lead { font-weight: var(--fw-semibold); }
.hero-subhead__sub  { font-weight: var(--fw-regular); color: var(--color-bali-hai-200); }

/* Narrow viewport — collapse the diagonal layout to stacked (logo above subhead). */
@media (max-width: 768px) {
  .hero-subhead {
    left: 10.94%;
    right: 1.5rem;
    top: auto;
    bottom: 3rem;
    transform: none;
    max-width: none;
  }
}

/* --- 2. Selected work -----------------------------------------------------
   CRAFT HERE. Grid is a sane default; the media treatment is the taste signal. */
.work-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: var(--space-gutter);
}
.work-item figure { margin: 0; }
.work-media {
  aspect-ratio: 4 / 3;
  background: var(--color-line); /* placeholder block — replace with real asset */
  border-radius: 2px;
}
.work-title { font-size: 1.1rem; margin: 1rem 0 0.25rem; }
.work-meta { color: var(--color-muted); margin: 0; font-size: 0.95rem; }

/* --- 2. Point of view -----------------------------------------------------
   From Figma (node 1183:60). Full-bleed white band; one statement block.
   Vertical padding 136px top / 72px bottom per the design; horizontal margins
   come from the inner wrapper at --content-max (matches Services). Two-tone:
   lead sentence semibold tuna-900, remainder regular tuna-800. */
.pov {
  background: var(--color-white);
  max-width: none;
  margin-inline: 0;
  padding-inline: 0;
  padding-block: 136px 72px;
}
.pov-inner {
  width: min(100% - 3rem, var(--content-max));
  margin-inline: auto;
}
.pov-statement {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--fw-regular);
  font-size: var(--fs-3xl);
  line-height: var(--lh-text);
  color: var(--color-tuna-500); /* body remainder; lead overrides to tuna-900 */
}
.pov-lead {
  font-weight: var(--fw-semibold);
  color: var(--color-tuna-900);
}

/* --- Accessibility -------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
:where(a, button):focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

/* --- Site navbar ----------------------------------------------------------
   Riff from newgenre.studio (see inspiration-log.md). Three behaviors:
   1) Fixed blurred panel with no hard bottom edge (gradient mask).
   2) Panel persists on scroll; contents hide on scroll-down, reveal on
      scroll-up (driven by [data-nav-revealed], toggled by JS).
   3) Contents color inverts (light <-> dark) based on the section under the
      nav (driven by [data-nav-color], toggled by an IntersectionObserver
      reading data-nav-color="light|dark" on each <section>).
   Tokens below are deliberately conservative so they don't fight the future
   design system. Tune freely against the reference. */

:root {
  --nav-fg-on-light: #111111;
  --nav-fg-on-dark: #ffffff;
  --nav-cta-border-on-light: rgba(17, 17, 17, 0.18);
  --nav-cta-border-on-dark: rgba(255, 255, 255, 0.28);

  --nav-height: 64px;
  --nav-logo-height: 1.5rem; /* ~24px at 16px base. Tune to taste. */
  --nav-blur-extent: 200px;  /* Vertical height of the progressive blur zone; extends below the nav so the blur fades out gradually. */
  --nav-color-duration: 280ms;
  --nav-reveal-duration: 360ms;
  --nav-reveal-easing: cubic-bezier(0.22, 1, 0.36, 1);
}

.site-nav {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--nav-height);
  z-index: 50;
  pointer-events: none; /* let the bg/contents claim their own pointer events */
}

/* Progressive blur stack — 1:1 from newgenre.studio (Playwright-inspected
   2026-05-20). 8 absolutely-positioned layers with doubling blur radii
   (0.078125 → 10px) and gradient masks offset by 12.5% of the zone. The
   layers overlap softly to produce a smooth blur intensity gradient: heavy
   at the top (where the nav sits), tapering to no blur at the bottom of
   the zone. There is no hard bottom edge because no single layer ends
   abruptly. The zone is taller than --nav-height so the fade extends below
   the nav contents. */
.site-nav-bg {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--nav-blur-extent);
  pointer-events: none;
}
.site-nav-blur-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.site-nav-blur-layer[data-blur="8"] {
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  -webkit-mask-image: linear-gradient(to top, transparent 87.5%, black 100%);
          mask-image: linear-gradient(to top, transparent 87.5%, black 100%);
}
.site-nav-blur-layer[data-blur="7"] {
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  -webkit-mask-image: linear-gradient(to top, transparent 75%, black 87.5%, black 100%);
          mask-image: linear-gradient(to top, transparent 75%, black 87.5%, black 100%);
}
.site-nav-blur-layer[data-blur="6"] {
  backdrop-filter: blur(2.5px);
  -webkit-backdrop-filter: blur(2.5px);
  -webkit-mask-image: linear-gradient(to top, transparent 62.5%, black 75%, black 87.5%, transparent 100%);
          mask-image: linear-gradient(to top, transparent 62.5%, black 75%, black 87.5%, transparent 100%);
}
.site-nav-blur-layer[data-blur="5"] {
  backdrop-filter: blur(1.25px);
  -webkit-backdrop-filter: blur(1.25px);
  -webkit-mask-image: linear-gradient(to top, transparent 50%, black 62.5%, black 75%, transparent 87.5%);
          mask-image: linear-gradient(to top, transparent 50%, black 62.5%, black 75%, transparent 87.5%);
}
.site-nav-blur-layer[data-blur="4"] {
  backdrop-filter: blur(0.625px);
  -webkit-backdrop-filter: blur(0.625px);
  -webkit-mask-image: linear-gradient(to top, transparent 37.5%, black 50%, black 62.5%, transparent 75%);
          mask-image: linear-gradient(to top, transparent 37.5%, black 50%, black 62.5%, transparent 75%);
}
.site-nav-blur-layer[data-blur="3"] {
  backdrop-filter: blur(0.3125px);
  -webkit-backdrop-filter: blur(0.3125px);
  -webkit-mask-image: linear-gradient(to top, transparent 25%, black 37.5%, black 50%, transparent 62.5%);
          mask-image: linear-gradient(to top, transparent 25%, black 37.5%, black 50%, transparent 62.5%);
}
.site-nav-blur-layer[data-blur="2"] {
  backdrop-filter: blur(0.15625px);
  -webkit-backdrop-filter: blur(0.15625px);
  -webkit-mask-image: linear-gradient(to top, transparent 12.5%, black 25%, black 37.5%, transparent 50%);
          mask-image: linear-gradient(to top, transparent 12.5%, black 25%, black 37.5%, transparent 50%);
}
.site-nav-blur-layer[data-blur="1"] {
  backdrop-filter: blur(0.078125px);
  -webkit-backdrop-filter: blur(0.078125px);
  -webkit-mask-image: linear-gradient(to top, transparent 0%, black 12.5%, black 25%, transparent 37.5%);
          mask-image: linear-gradient(to top, transparent 0%, black 12.5%, black 25%, transparent 37.5%);
}

/* Contents — what hides/reveals on scroll. */
.site-nav-inner {
  position: relative;
  height: 100%;
  max-width: 90rem;
  margin-inline: auto;
  padding-inline: var(--space-gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  pointer-events: auto;
  transition:
    transform var(--nav-reveal-duration) var(--nav-reveal-easing),
    opacity var(--nav-reveal-duration) ease;
}
.site-nav[data-nav-revealed="false"] .site-nav-inner {
  transform: translateY(calc(-1 * var(--nav-height)));
  opacity: 0;
  pointer-events: none;
}

/* Logo wordmark — the SVG inherits currentColor, so the inversion only swaps
   the color token. Opacity transition drives the hide/reveal crossfade. */
.site-nav-mark {
  color: var(--nav-fg-on-light);
  text-decoration: none;
  transition:
    color var(--nav-color-duration) ease,
    opacity var(--nav-reveal-duration) var(--nav-reveal-easing);
}

/* CTA — outlined pill. On hover a circular fill (the ::before) scale-expands
   from the lower-left to cover the button while the label flips to the inverse
   color. Replicated 1:1 from monopo.london (0.6s easeOutQuart). The fill +
   label colors are driven by --cta-fg / --cta-ink, which flip with the nav
   inversion (see the [data-nav-color="dark"] override below), giving two inverse
   variants: white-fill/dark-label on dark sections, dark-fill/white-label on light. */
.site-nav-cta {
  --cta-fg: var(--nav-fg-on-light);   /* outline + label, and the hover fill */
  --cta-ink: var(--nav-fg-on-dark);   /* label color once the fill covers it */
  --cta-ease: cubic-bezier(0.165, 0.84, 0.44, 1);
  --cta-dur: 0.6s;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding: 0.45rem 0.95rem;
  border: 1px solid var(--nav-cta-border-on-light);
  border-radius: 999px;
  color: var(--cta-fg);
  text-decoration: none;
  font-weight: 600;
  letter-spacing: -0.01em;
  font-size: 0.95rem;
  transition:
    color var(--cta-dur) var(--cta-ease),
    border-color var(--nav-color-duration) ease;
}
.site-nav-cta__label { position: relative; z-index: 1; }
.site-nav-cta::before {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 220px;
  height: 220px;
  margin: -110px; /* circle centered on the lower-left corner */
  border-radius: 50%;
  background: var(--cta-fg);
  transform: scale(0);
  transform-origin: center;
  transition: transform var(--cta-dur) var(--cta-ease);
  z-index: 0;
  pointer-events: none;
}
.site-nav-cta:hover,
.site-nav-cta:focus-visible { color: var(--cta-ink); }
.site-nav-cta:hover::before,
.site-nav-cta:focus-visible::before { transform: scale(1); }

/* Wordmark SVG sized via token; width auto to preserve aspect ratio.
   The SVG uses fill="currentColor", so the inversion logic picks it up. */
.site-nav-logo {
  display: block;
  height: var(--nav-logo-height);
  width: auto;
}

/* Inversion — JS sets [data-nav-color="dark"] when the active section is dark. */
.site-nav[data-nav-color="dark"] .site-nav-mark {
  color: var(--nav-fg-on-dark);
}
/* CTA on dark sections: flip the fill/label vars (white fill, dark label) and
   the outline color. color + hover come from the vars, so no direct overrides. */
.site-nav[data-nav-color="dark"] .site-nav-cta {
  --cta-fg: var(--nav-fg-on-dark);
  --cta-ink: var(--nav-fg-on-light);
  border-color: var(--nav-cta-border-on-dark);
}

/* Wordmark visibility — driven by the active section's data-nav-mark.
   Hidden over the hero (which features a large display version of the logo);
   shown everywhere else. Opacity transition matches the color crossfade for
   a coherent feel; pointer-events disabled when hidden so the invisible link
   isn't clickable. aria-hidden is synced on the anchor by the observer. */
.site-nav[data-nav-mark="hide"] .site-nav-mark {
  opacity: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .site-nav-inner,
  .site-nav-mark,
  .site-nav-cta,
  .site-nav-cta::before { transition: none; }
}

/* --- Case-studies ticker (marquee) ----------------------------------------
   Running banner riffed from bureau-va.com (see inspiration-log.md). Standard
   duplicate-and-translateX(-50%) loop; the inline script clones the track's
   items once so the loop is seamless. Colors + speed are placeholder tokens. */
:root {
  --ticker-bg: var(--color-tuna-900);   /* placeholder — tweak with Z */
  --ticker-fg: var(--color-white);      /* placeholder — tweak with Z */
  --ticker-duration: 40s;               /* full loop time; lower = faster */
  --ticker-gap: 1.5rem;                 /* half the space between items */
  --ticker-pad-block: clamp(1.25rem, 3.5vh, 2.5rem);
  --ticker-motif-size: 1.5rem;
}

.ticker-strip {
  background: var(--ticker-bg);
  overflow: hidden;
  /* full-bleed: override the shared layout helper (max-width + gutter + centering) */
  max-width: none;
  margin-inline: 0;
  padding-inline: 0;
  padding-block: var(--ticker-pad-block);
}

.ticker { overflow: hidden; width: 100%; }

.ticker__track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  width: max-content;
  align-items: center;
  animation: ticker-scroll var(--ticker-duration) linear infinite;
}

.ticker__item {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  margin-inline: var(--ticker-gap);
}

.ticker__text {
  font-family: var(--font-display);
  font-weight: var(--fw-medium);
  font-size: var(--fs-4xl);
  line-height: var(--lh-text); /* 1.4 — leaves room for descenders (g/y/p) so overflow:hidden doesn't clip them */
  white-space: nowrap;
  color: var(--ticker-fg);
}

.ticker__motif-svg {
  display: block;
  width: var(--ticker-motif-size);
  height: var(--ticker-motif-size);
  color: var(--ticker-fg); /* placeholder uses currentColor */
}

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

/* Pause the scroll for reduced-motion users (shows a static, clipped row). */
@media (prefers-reduced-motion: reduce) {
  .ticker__track { animation: none; }
}

/* --- Services -------------------------------------------------------------
   From Figma. Two-column: intro (heading + subhead) left, accordion rows
   right (labels right-aligned, + toggle). Base/collapsed state. The expanded
   panel content + styling are TODO (pending Z's design). */
.services {
  background: var(--color-white);
  /* Neutralize the inherited section box so .services-inner controls horizontal
     sizing (the shared content-width / margin reference). */
  max-width: none;
  margin-inline: 0;
  padding-inline: 0;
  padding-block: 72px var(--space-section); /* top 72px per Figma; bottom unchanged */
}

.services-inner {
  /* Content reference: 1000px wide, centered → 140px L/R margins at the 1280px
     design width, and identical margins on every section using this pattern. */
  width: min(100% - 3rem, var(--content-max));
  margin-inline: auto;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(2rem, 6vw, 5.5rem); /* ~88px max, the Figma column gap */
  justify-content: space-between;
  align-items: flex-start;
}

.services-intro { flex: 1 1 320px; max-width: 25rem; /* 400px */ }
.services-heading {
  margin: 0 0 1.25rem; /* 20px gap to subhead, per Figma */
  font-family: var(--font-display);
  font-weight: var(--fw-semibold); /* text-3xl/SemiBold */
  font-size: var(--fs-3xl);
  line-height: var(--lh-text);
  color: var(--color-tuna-900);
}
.services-sub { color: var(--color-tuna-500); }
.services-sub p {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--fw-regular);
  font-size: var(--fs-2xl); /* 24px (was 20px) */
  line-height: var(--lh-text);
}

.services-list { flex: 1 1 500px; max-width: 38.5rem; /* 616px */ }

.service-row { border-bottom: 1px solid var(--color-tuna-300); }
.service-row:first-child { border-top: 1px solid var(--color-tuna-300); }

.service-row__trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem; /* 12px */
  padding: 1.125rem 0 1rem; /* ~18px top / 16px bottom */
  background: none;
  border: 0;
  cursor: pointer;
  text-align: right;
  font: inherit;
  color: inherit;
}
.service-row__label {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-2xl);
  line-height: var(--lh-text);
  color: var(--color-tuna-900);
  white-space: nowrap;
}
.service-row__icon {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  display: inline-flex;
  transition: transform 220ms ease;
}
.service-row__icon svg { display: block; }

/* Open affordance: the + rotates to x. */
.service-row__trigger[aria-expanded="true"] .service-row__icon { transform: rotate(45deg); }

/* Expanded panel — a right-aligned list of service tags. Expand/collapse via a
   grid-rows 0fr->1fr height animation: the panel is the grid, its single child
   (the list) collapses to 0 height (overflow hidden) when closed. */
.service-row__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 320ms var(--logo-ease, ease);
}
.service-row__trigger[aria-expanded="true"] + .service-row__panel {
  grid-template-rows: 1fr;
}
/* The grid item: carries overflow:hidden + min-height:0 (and NO padding) so the
   0fr track collapses to a true 0. Padding lives on the list inside, where it
   gets clipped when closed. */
.service-row__panel-inner {
  min-height: 0;
  overflow: hidden;
}
.service-row__tags {
  list-style: none;
  margin: 0;
  padding: 0.25rem 0 1.5rem; /* 4px top (≈20px below header with the trigger pad) / 24px bottom */
  text-align: right;
}
.service-row__tags li {
  font-family: var(--font-display);
  font-weight: var(--fw-regular);
  font-size: var(--fs-xl); /* 20px */
  line-height: var(--lh-text); /* 1.4 → 28px */
  color: var(--color-tuna-800);
  margin-bottom: 8px; /* 28px line + 8px = 36px row pitch (Figma) */
}
.service-row__tags li:last-child { margin-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .service-row__panel { transition: none; }
}

@media (max-width: 768px) {
  .services-intro,
  .services-list { flex-basis: 100%; max-width: none; }
}
