/* ==========================================================================
   Triple Zero Labs — landing page
   Monochrome · bold typography · fluid motion
   ========================================================================== */

/* ---------- tokens ---------- */
:root{
  /* monochrome ramp */
  --black:  #0B0B0C;
  --white:  #F4F4F5;

  /* themed (flipped by [data-theme="light"] sections via JS) */
  --bg:     #0B0B0C;
  --fg:     #F4F4F5;
  --muted:  rgba(244,244,245,.56);
  --faint:  rgba(244,244,245,.34);
  --line:   rgba(244,244,245,.14);
  --hair:   rgba(244,244,245,.08);

  /* type scale — fluid, no breakpoints needed */
  --t-xs:   clamp(.688rem, .66rem + .12vw, .75rem);
  --t-sm:   clamp(.813rem, .78rem + .16vw, .875rem);
  --t-base: clamp(1rem, .96rem + .22vw, 1.125rem);
  --t-lg:   clamp(1.125rem, 1.05rem + .4vw, 1.375rem);
  --t-xl:   clamp(1.5rem, 1.25rem + 1.1vw, 2.25rem);
  --t-h2:   clamp(2.25rem, 1.4rem + 3.9vw, 5.5rem);
  --t-hero: clamp(2.75rem, 1rem + 8.6vw, 9.5rem);
  --t-huge: clamp(5rem, 2rem + 15vw, 16rem);

  /* rhythm */
  --gutter: clamp(1.25rem, 4vw, 4rem);
  --wrap:   1440px;
  --sect:   clamp(6rem, 12vh + 4rem, 12rem);

  /* motion */
  --ease:     cubic-bezier(.22,1,.36,1);   /* soft out — the Apple feel */
  --ease-io:  cubic-bezier(.65,0,.35,1);
  --dur:      .9s;
}

body.is-light{
  --bg:    #F4F4F5;
  --fg:    #0B0B0C;
  --muted: rgba(11,11,12,.62);
  --faint: rgba(11,11,12,.38);
  --line:  rgba(11,11,12,.16);
  --hair:  rgba(11,11,12,.09);
}

/* ---------- theme flip ----------
   Cross-fading text from white to black drags it through muddy mid-greys,
   which reads as a smear. Instead the content fades out, the palette swaps
   while nothing is visible, then it fades back in over the settled
   background. Durations here must stay in sync with THEME_OUT / THEME_SWAP
   in main.js. */
.nav, main, .footer{
  transition:opacity .22s var(--ease);
}
body.is-theming .nav,
body.is-theming main,
body.is-theming .footer{
  opacity:0;
}

/* ---------- reset ---------- */
*,*::before,*::after{ margin:0; padding:0; box-sizing:border-box; }

html{
  scroll-behavior:smooth;
  -webkit-text-size-adjust:100%;
}

body{
  background:var(--bg);
  color:var(--fg);
  font-family:"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
              "Helvetica Neue", Arial, sans-serif;
  font-size:var(--t-base);
  line-height:1.5;
  font-weight:400;
  letter-spacing:-.011em;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
  /* colour is deliberately NOT transitioned — see the theme-flip block below */
  transition:background-color .45s var(--ease-io);
}

img,svg{ display:block; max-width:100%; }
button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer; }
a{ color:inherit; text-decoration:none; }
ul,ol{ list-style:none; }

::selection{ background:var(--fg); color:var(--bg); }

:focus-visible{
  outline:2px solid var(--fg);
  outline-offset:4px;
  border-radius:2px;
}

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

/* ---------- scroll progress ---------- */
.progress{
  position:fixed; inset:0 0 auto 0;
  height:2px; z-index:120;
  background:transparent;
  pointer-events:none;
}
.progress__bar{
  display:block; height:100%; width:0%;
  background:var(--fg);
  transition:background-color .9s var(--ease-io);
}

/* ---------- film grain ---------- */
/* Shimmers by moving the tile, not the element. It used to be inset:-150% —
   four times the viewport — so a translate() never exposed an edge, but iOS
   Safari lets an oversized fixed box inflate the scrollable area, which showed
   up as dead space below the footer. At inset:0 there is nothing to overhang. */
.grain{
  position:fixed; inset:0;
  z-index:110;
  pointer-events:none;
  opacity:.035;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:grain 6s steps(6) infinite;
}
@keyframes grain{
  0%,100%{ background-position:0 0; }
  20%{ background-position:-24px 16px; }
  40%{ background-position:16px -24px; }
  60%{ background-position:-16px -16px; }
  80%{ background-position:24px 8px; }
}

/* ==========================================================================
   NAV
   ========================================================================== */
.nav{
  position:fixed; top:0; left:0; right:0;
  z-index:100;
  display:flex; align-items:center; justify-content:space-between;
  gap:2rem;
  padding:1.35rem var(--gutter);
  /* opacity included so the theme flip fades the nav with everything else —
     this declaration would otherwise override the shared .22s rule above */
  transition:background-color .5s var(--ease), backdrop-filter .5s var(--ease),
             border-color .5s var(--ease), padding .5s var(--ease),
             opacity .22s var(--ease);
  border-bottom:1px solid transparent;
}
.nav.is-stuck{
  padding-block:.95rem;
  background:color-mix(in srgb, var(--bg) 72%, transparent);
  backdrop-filter:blur(20px) saturate(160%);
  -webkit-backdrop-filter:blur(20px) saturate(160%);
  border-bottom-color:var(--hair);
}

.nav__brand{ display:flex; align-items:center; gap:.7rem; }
.nav__name{
  font-weight:700; font-size:var(--t-sm);
  letter-spacing:-.02em;
}

/* the three zeros, as a mark */
.nav__mark{ display:flex; gap:3px; }
.nav__mark span{
  width:8px; height:8px; border-radius:50%;
  border:1.5px solid var(--fg);
  transition:transform .5s var(--ease), background-color .3s var(--ease);
}
.nav__brand:hover .nav__mark span{ background:var(--fg); }
.nav__brand:hover .nav__mark span:nth-child(1){ transform:translateY(-3px); }
.nav__brand:hover .nav__mark span:nth-child(2){ transform:translateY(-3px); transition-delay:.05s; }
.nav__brand:hover .nav__mark span:nth-child(3){ transform:translateY(-3px); transition-delay:.1s; }

.nav__links{ display:flex; gap:2.25rem; margin-left:auto; }
.nav__links a{
  font-size:var(--t-sm); color:var(--muted);
  position:relative; padding-block:.25rem;
  transition:color .35s var(--ease);
}
.nav__links a::after{
  content:""; position:absolute; left:0; bottom:0;
  width:100%; height:1px; background:var(--fg);
  transform:scaleX(0); transform-origin:right;
  transition:transform .5s var(--ease);
}
.nav__links a:hover{ color:var(--fg); }
.nav__links a:hover::after{ transform:scaleX(1); transform-origin:left; }

.nav__toggle{ display:none; width:28px; height:18px; position:relative; }
.nav__toggle span{
  position:absolute; left:0; width:100%; height:1.5px;
  background:var(--fg); transition:transform .45s var(--ease), opacity .3s;
}
.nav__toggle span:nth-child(1){ top:3px; }
.nav__toggle span:nth-child(2){ bottom:3px; }
.nav__toggle.is-open span:nth-child(1){ transform:translateY(5.5px) rotate(45deg); }
.nav__toggle.is-open span:nth-child(2){ transform:translateY(-5.5px) rotate(-45deg); }

/* mobile menu */
.menu{
  position:fixed; inset:0; z-index:99;
  background:var(--bg);
  display:flex; flex-direction:column; justify-content:center;
  gap:.5rem; padding:var(--gutter);
  clip-path:inset(0 0 100% 0);
  transition:clip-path .8s var(--ease);
  pointer-events:none;
}
.menu.is-open{ clip-path:inset(0 0 0 0); pointer-events:auto; }
.menu a{
  font-size:clamp(2rem,9vw,3.5rem);
  font-weight:700; letter-spacing:-.04em;
  padding-block:.35rem;
  opacity:0; transform:translateY(24px);
  transition:opacity .6s var(--ease), transform .6s var(--ease);
}
.menu.is-open a{ opacity:1; transform:none; }
.menu.is-open a:nth-child(1){ transition-delay:.18s; }
.menu.is-open a:nth-child(2){ transition-delay:.24s; }
.menu.is-open a:nth-child(3){ transition-delay:.30s; }
.menu.is-open a:nth-child(4){ transition-delay:.36s; }
.menu.is-open a:nth-child(5){ transition-delay:.42s; }
.menu.is-open a:nth-child(6){ transition-delay:.48s; }

/* ==========================================================================
   SHARED BITS
   ========================================================================== */
.eyebrow{
  display:flex; align-items:center; gap:.6rem;
  font-size:var(--t-xs);
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--faint);
  font-variant-numeric:tabular-nums;
}
.eyebrow__dot{
  width:6px; height:6px; border-radius:50%;
  background:var(--fg);
  animation:pulse 2.6s var(--ease-io) infinite;
}
@keyframes pulse{
  0%,100%{ opacity:1; transform:scale(1); }
  50%{ opacity:.35; transform:scale(.7); }
}

.h2{
  font-size:var(--t-h2);
  font-weight:700;
  line-height:.96;
  letter-spacing:-.045em;
  max-width:18ch;
}
.h2 em{ font-style:normal; color:var(--faint); }

/* Inline emphasis inside body copy: lifts a phrase from muted to full
   contrast — white on the dark sections, near-black on the light ones,
   since --fg flips with the theme. Weight is inherited on purpose, so it
   reads as brightness rather than bolding. Use <strong> or class="hl".
   For a touch more presence, set font-weight:500 instead of inherit. */
strong,
.hl{
  color:var(--fg);
  font-weight:inherit;
}

.section{ padding-block:var(--sect); position:relative; }
.section__head{ margin-bottom:clamp(3rem,7vw,6rem); }
.section__head .eyebrow{ margin-bottom:1.75rem; }

/* buttons */
.btn{
  position:relative;
  display:inline-flex; align-items:center; justify-content:center;
  padding:1.1rem 2rem;
  border-radius:100px;
  border:1px solid var(--fg);
  font-size:var(--t-sm); font-weight:500;
  letter-spacing:-.01em;
  overflow:hidden;
  isolation:isolate;
  transition:color .45s var(--ease), border-color .45s var(--ease);
}
.btn::before{
  content:""; position:absolute; inset:0; z-index:-1;
  background:var(--fg);
  transform:translateY(101%);
  transition:transform .55s var(--ease);
}
.btn:hover{ color:var(--bg); }
.btn:hover::before{ transform:translateY(0); }
.btn span{ display:block; }
.btn--sm{ padding:.7rem 1.35rem; }
.btn--lg{
  padding:1.35rem 2.75rem;
  font-size:var(--t-lg); font-weight:600;
}

.link-arrow{
  display:inline-flex; align-items:center; gap:.55rem;
  font-size:var(--t-sm); color:var(--muted);
  transition:color .35s var(--ease), gap .35s var(--ease);
}
.link-arrow::after{
  content:"→";
  transition:transform .45s var(--ease);
}
.link-arrow:hover{ color:var(--fg); gap:.85rem; }
.link-arrow:hover::after{ transform:translateX(3px); }

/* ---------- reveal system ---------- */
[data-reveal]{
  opacity:0;
  transform:translateY(26px);
  transition:opacity .95s var(--ease), transform .95s var(--ease);
  transition-delay:calc(var(--i, 0) * 90ms);
}
[data-reveal].is-in{ opacity:1; transform:none; }

/* masked line reveal (hero + cta) */
/* The mask that hides the text before it slides up also clips descenders
   (g, y, p) — line-height is .87, so the box ends at the baseline.
   Pad the mask for descender room, then pull it back so the tight
   leading is unchanged. The reveal starts below the padded edge. */
.line{
  display:block;
  overflow:hidden;
  padding-bottom:.3em;     /* deepest descender is "g" at .238em (Segoe UI) */
  margin-bottom:-.3em;
}
.line__in{
  display:block;
  transform:translateY(calc(100% + .4em));   /* must exceed the padding to stay hidden */
  transition:transform 1.15s var(--ease);
}
.is-loaded .hero .line__in{ transform:none; }
.hero .line:nth-child(1) .line__in{ transition-delay:.15s; }
.hero .line:nth-child(2) .line__in{ transition-delay:.27s; }
.hero .line:nth-child(3) .line__in{ transition-delay:.39s; }

.cta__title .line__in{ transform:translateY(calc(100% + .4em)); }
.cta__title .line__in.is-in{ transform:none; }

/* ==========================================================================
   HERO
   ========================================================================== */
.hero{
  position:relative;
  min-height:100svh;
  display:flex; flex-direction:column; justify-content:flex-end;
  padding:calc(var(--gutter) + 5rem) var(--gutter) clamp(2.5rem,6vh,4rem);
  overflow:hidden;
}

/* receding perspective grid — a nod to drawings, kept very quiet */
.hero__grid{
  position:absolute; inset:0;
  background-image:
    linear-gradient(to right, var(--hair) 1px, transparent 1px),
    linear-gradient(to bottom, var(--hair) 1px, transparent 1px);
  background-size:clamp(48px,7vw,110px) clamp(48px,7vw,110px);
  mask-image:radial-gradient(120% 85% at 50% 15%, #000 5%, transparent 72%);
  -webkit-mask-image:radial-gradient(120% 85% at 50% 15%, #000 5%, transparent 72%);
  opacity:0;
  animation:gridIn 2.4s var(--ease) .2s forwards;
}
@keyframes gridIn{ to{ opacity:1; } }

.hero__inner{
  position:relative;
  width:100%; max-width:var(--wrap);
  margin-inline:auto;
  flex:1;
  display:flex; flex-direction:column; justify-content:flex-end;
}

.hero__eyebrow{
  margin-bottom:clamp(2rem,5vw,3.5rem);
  opacity:0; transform:translateY(14px);
  transition:opacity 1s var(--ease) .05s, transform 1s var(--ease) .05s;
}
.is-loaded .hero__eyebrow{ opacity:1; transform:none; }

.hero__title{
  font-size:var(--t-hero);
  font-weight:800;
  line-height:.87;
  letter-spacing:-.055em;
  margin-bottom:clamp(2.5rem,6vw,4.5rem);
}

.hero__foot{
  display:grid;
  grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);
  gap:clamp(1.75rem,4vw,4rem);
  align-items:end;
  padding-top:clamp(1.75rem,4vw,2.5rem);
  border-top:1px solid var(--line);
  opacity:0; transform:translateY(20px);
  transition:opacity 1.1s var(--ease) .62s, transform 1.1s var(--ease) .62s;
}
.is-loaded .hero__foot{ opacity:1; transform:none; }

.hero__ledes{
  display:flex; flex-direction:column;
  gap:1.1em;
}
.hero__lede{
  font-size:var(--t-lg);
  line-height:1.42;
  color:var(--muted);
  max-width:46ch;
  letter-spacing:-.015em;
}

.hero__cta{
  display:flex; align-items:center; gap:1.75rem;
  flex-wrap:wrap;
  justify-content:flex-end;
}

.hero__scroll{
  position:absolute;
  right:var(--gutter);
  bottom:clamp(2.5rem,6vh,4rem);
  display:flex; flex-direction:column; align-items:center; gap:.75rem;
  font-size:var(--t-xs);
  letter-spacing:.16em; text-transform:uppercase;
  color:var(--faint);
  writing-mode:vertical-rl;
  opacity:0;
  animation:fadeIn 1s var(--ease) 1.3s forwards;
}
.hero__scroll i{
  display:block; width:1px; height:56px;
  background:linear-gradient(to bottom, var(--fg), transparent);
  animation:scrollLine 2.4s var(--ease-io) infinite;
  transform-origin:top;
}
@keyframes fadeIn{ to{ opacity:1; } }
@keyframes scrollLine{
  0%{ transform:scaleY(0); opacity:0; }
  40%{ transform:scaleY(1); opacity:1; }
  100%{ transform:scaleY(1) translateY(56px); opacity:0; }
}

/* ==========================================================================
   MARQUEE
   ========================================================================== */
.marquee{
  border-block:1px solid var(--line);
  padding-block:clamp(1.1rem,2vw,1.6rem);
  overflow:hidden;
  white-space:nowrap;
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image:linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee__track{
  display:inline-flex; align-items:center; gap:2.5rem;
  animation:marquee 46s linear infinite;
  will-change:transform;
}
.marquee__track span{
  font-size:var(--t-xl);
  font-weight:600;
  letter-spacing:-.035em;
  color:var(--faint);
}
.marquee__track i{ color:var(--line); font-style:normal; }
@keyframes marquee{ to{ transform:translateX(-50%); } }

/* ==========================================================================
   PRINCIPLES / THE THREE ZEROS
   ========================================================================== */
.zeros{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:clamp(2rem,4vw,4.5rem);
  border-top:1px solid var(--line);
}
.zero{
  padding-top:clamp(1.75rem,3vw,2.75rem);
  position:relative;
}
.zero::before{
  content:""; position:absolute; top:-1px; left:0;
  width:0; height:1px; background:var(--fg);
  transition:width 1.3s var(--ease);
  transition-delay:calc(var(--i,0) * 120ms + 200ms);
}
.zero.is-in::before{ width:100%; }

/* Slashed zero, drawn rather than typed. There is no Unicode digit-zero
   -with-slash, and the OpenType `zero` feature only fires if the loaded font
   ships it — so the slash is a pseudo-element and works on every device.
   Tune with the three custom properties below. */
.zero__num{
  /* measured against the rendered glyph: the bowl's outer edge sits at
     .36em from centre along this axis, so .77em breaks just past it */
  --slash-length: .77em;
  --slash-weight: .095em;
  --slash-angle: -58deg;

  display:block;
  width:fit-content;              /* box hugs the glyph, so 50% is its centre */
  position:relative;
  font-size:var(--t-huge);
  font-weight:800;
  line-height:.8;
  letter-spacing:0;               /* tracking on a lone glyph only offsets it */
  /* solid dark grey at rest, lifting to full white on hover */
  color:color-mix(in srgb, var(--fg) 20%, var(--bg));
  margin-bottom:clamp(1rem,2vw,1.75rem);
  transition:color .6s var(--ease);
}
.zero__num::after{
  content:"";
  position:absolute;
  left:50%; top:50%;
  width:var(--slash-length);
  height:var(--slash-weight);
  background:currentColor;        /* follows the hover colour transition */
  transform:translate(-50%,-50%) rotate(var(--slash-angle));
  border-radius:1px;
}
.zero:hover .zero__num{ color:var(--fg); }
.zero__title{
  font-size:var(--t-xl);
  font-weight:700; letter-spacing:-.035em;
  margin-bottom:.9rem;
}
.zero__body{
  color:var(--muted);
  max-width:34ch;
  line-height:1.55;
}

/* ==========================================================================
   FIGURES
   grayscale() keeps any real photograph dropped in here on-theme
   ========================================================================== */
.figure{ margin:0; }
.figure img{
  width:100%; height:auto;
  filter:grayscale(1);
}
.figure figcaption{
  margin-top:.9rem;
  font-size:var(--t-xs);
  letter-spacing:.02em;
  line-height:1.5;
  color:var(--faint);
  max-width:34ch;
}
.figure--manifesto img{
  border:1px solid var(--line);
  aspect-ratio:720/560;
  object-fit:cover;
}

/* ---------- the tower, assembling itself ----------
   Inline SVG, so the strokes take currentColor (and follow the light/dark
   flip) and each slab can be staggered as the figure scrolls into view. */
.figure--manifesto .tower{
  display:block;
  width:100%; height:auto;
  border:1px solid var(--line);
}
.tower__floor{
  /* inherited into the <use> shadow tree by the silhouette path, so each
     slab hides the floors behind it instead of every outline overlapping */
  fill:var(--bg);
  opacity:0;
  transform:translateY(34px);           /* px here = SVG user units */

  /* fill eases at the same rate as the body colour, so the slabs and their
     outlines cross the light/dark flip together instead of washing out.
     Only opacity and transform take the per-floor stagger. */
  transition-property:opacity, transform, fill;
  transition-duration:.5s, .8s, .45s;   /* fill matches the background flip */
  transition-timing-function:var(--ease), var(--ease), var(--ease-io);
  transition-delay:
    calc(var(--build-delay) + var(--f) * 95ms),
    calc(var(--build-delay) + var(--f) * 95ms),
    0s;
}
/* Just a beat after the frame settles — the observer in main.js now decides
   *when* to build (once the figure is mostly visible), so this no longer has
   to compensate for an early trigger. Same value at every size. */
.tower__floor{ --build-delay:300ms; }
/* .is-built (not .is-in) — set by a dedicated observer once the figure is
   mostly on screen, so the frame is visible before the stacking begins */
.figure--manifesto.is-built .tower__floor{
  opacity:1;
  transform:none;
}
@media (prefers-reduced-motion: reduce){
  .tower__floor{ opacity:1; transform:none; }
}
.figure--acc{ margin-top:clamp(1.5rem,3vw,2rem); }
.figure--acc img{
  border:1px solid var(--hair);
  aspect-ratio:16/9;
  object-fit:cover;
}

/* ==========================================================================
   MANIFESTO
   ========================================================================== */
.section--manifesto .eyebrow{ margin-bottom:clamp(2.5rem,5vw,4rem); }
.manifesto-grid{
  display:grid;
  grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);
  gap:clamp(2.5rem,6vw,6rem);
  align-items:center;        /* text sits centred against the tall tower */
}
.manifesto p{
  font-size:clamp(1.5rem,4.6vw,3.75rem);
  font-weight:600;
  line-height:1.12;
  letter-spacing:-.045em;
  max-width:24ch;
  color:var(--faint);
  transition:opacity 1s var(--ease), transform 1s var(--ease), color 1s var(--ease);
}
.manifesto p.is-in{ color:var(--muted); }
.manifesto__turn{ margin-top:clamp(1.75rem,4vw,3rem); }
.manifesto p.manifesto__turn.is-in{ color:var(--fg); }

/* ==========================================================================
   SERVICES ACCORDION
   ========================================================================== */
.acc{ border-top:1px solid var(--line); }
.acc__item{ border-bottom:1px solid var(--line); }

.acc__head{
  width:100%;
  display:grid;
  grid-template-columns:auto 1fr auto;
  align-items:center;
  gap:clamp(1rem,3vw,2.5rem);
  padding-block:clamp(1.5rem,3vw,2.25rem);
  text-align:left;
  transition:padding-inline .55s var(--ease);
}
.acc__item:hover .acc__head{ padding-inline:clamp(.5rem,1.5vw,1.25rem); }

.acc__idx{
  font-size:var(--t-xs);
  font-variant-numeric:tabular-nums;
  color:var(--faint);
  letter-spacing:.1em;
}
.acc__title{
  font-size:clamp(1.35rem,3.4vw,2.75rem);
  font-weight:700;
  line-height:1.05;
  letter-spacing:-.04em;
  color:var(--muted);
  transition:color .45s var(--ease);
}
.acc__item:hover .acc__title,
.acc__item.is-open .acc__title{ color:var(--fg); }

.acc__sign{
  position:relative;
  width:22px; height:22px;
  flex-shrink:0;
}
.acc__sign::before,.acc__sign::after{
  content:""; position:absolute; inset:0; margin:auto;
  background:var(--fg);
  transition:transform .55s var(--ease), opacity .4s var(--ease);
}
.acc__sign::before{ width:100%; height:1.5px; }
.acc__sign::after{ width:1.5px; height:100%; }
.acc__item.is-open .acc__sign::after{ transform:rotate(90deg); opacity:0; }

/* grid trick: animates height without knowing it */
.acc__panel{
  display:grid;
  grid-template-rows:0fr;
  transition:grid-template-rows .7s var(--ease);
}
.acc__item.is-open .acc__panel{ grid-template-rows:1fr; }
.acc__inner{
  overflow:hidden;
  display:grid;
  grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  gap:clamp(1.5rem,4vw,4rem);
  opacity:0;
  transition:opacity .5s var(--ease);
}
.acc__item.is-open .acc__inner{ opacity:1; transition-delay:.18s; }
.acc__inner > *{ padding-bottom:clamp(1.75rem,3.5vw,2.75rem); }
.acc__inner p{
  color:var(--muted);
  font-size:var(--t-lg);
  line-height:1.5;
  max-width:52ch;
}
.acc__inner ul{ align-self:start; }
.acc__inner li{
  font-size:var(--t-sm);
  color:var(--faint);
  padding-block:.55rem;
  border-bottom:1px solid var(--hair);
}
.acc__inner li:first-child{ border-top:1px solid var(--hair); }

/* ==========================================================================
   SECTORS — featured owner block, then the delivery teams
   ========================================================================== */
.lead-card{
  border:1px solid var(--fg);
  padding:clamp(1.5rem,3.5vw,3.25rem);
  display:grid;
  grid-template-columns:minmax(0,1.25fr) minmax(0,.75fr);
  column-gap:clamp(1.5rem,4vw,4rem);
  row-gap:clamp(1.5rem,3vw,2.25rem);
  align-items:start;
  margin-bottom:clamp(3rem,6vw,5rem);
}
.lead-card__head{
  grid-column:1 / -1;
  display:flex; align-items:center; gap:1.25rem;
}
.lead-card__badge{
  flex-shrink:0;
  border:1px solid var(--line);
  border-radius:100px;
  padding:.4rem .9rem;
  font-size:var(--t-xs);
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--fg);
}
.lead-card__rule{
  flex:1; height:1px; background:var(--line);
}
.lead-card__main h3{
  font-size:clamp(1.75rem,4.6vw,3.5rem);
  font-weight:700;
  letter-spacing:-.04em;
  line-height:1.03;
  margin-bottom:clamp(1rem,2vw,1.5rem);
  max-width:20ch;
}
.lead-card__main p{
  font-size:var(--t-lg);
  line-height:1.5;
  color:var(--muted);
  max-width:54ch;
}
.lead-card__list{ align-self:start; }
.lead-card__list li{
  font-size:var(--t-sm);
  color:var(--faint);
  padding-block:.65rem;
  border-bottom:1px solid var(--hair);
}
.lead-card__list li:first-child{ border-top:1px solid var(--hair); }

.sectors__note{
  font-size:var(--t-sm);
  color:var(--faint);
  max-width:44ch;
  line-height:1.55;
  margin-bottom:clamp(1.5rem,3vw,2.25rem);
}

.cards{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:1px;
  background:var(--line);
  border-block:1px solid var(--line);
}
.card{
  background:var(--bg);
  padding:clamp(1.75rem,3vw,2.75rem) clamp(1.25rem,2vw,2rem)
          clamp(2.5rem,5vw,4rem);
  display:flex; flex-direction:column;
  min-height:clamp(18rem,26vw,24rem);
  transition:background-color .5s var(--ease), color .5s var(--ease);
}
.card:hover{ background:var(--fg); color:var(--bg); }
.card__idx{
  font-size:var(--t-xs);
  letter-spacing:.12em;
  color:var(--faint);
  margin-bottom:auto;
  transition:color .5s var(--ease);
}
.card:hover .card__idx{ color:currentColor; opacity:.5; }
.card h3{
  font-size:var(--t-xl);
  font-weight:700; letter-spacing:-.035em;
  line-height:1.05;
  margin-bottom:.9rem;
  margin-top:clamp(2.5rem,6vw,4rem);
}
.card p{
  font-size:var(--t-sm);
  line-height:1.55;
  color:var(--muted);
  transition:color .5s var(--ease);
}
.card:hover p{ color:currentColor; opacity:.75; }

/* ==========================================================================
   APPROACH
   ========================================================================== */
.approach{
  display:grid;
  grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
  gap:clamp(2.5rem,6vw,7rem);
  align-items:start;
}
.approach__sticky{ position:sticky; top:clamp(6rem,14vh,9rem); }
.approach__sticky .eyebrow{ margin-bottom:1.75rem; }
.approach__note{
  margin-top:1.75rem;
  color:var(--muted);
  max-width:34ch;
  line-height:1.55;
}

.steps{ display:flex; flex-direction:column; }
.step{
  padding-block:clamp(1.75rem,3.5vw,2.75rem);
  border-top:1px solid var(--line);
  display:grid;
  grid-template-columns:auto 1fr;
  gap:clamp(1.25rem,3vw,2.5rem);
  align-items:start;
}
.step:last-child{ border-bottom:1px solid var(--line); }
.step__idx{
  font-size:var(--t-xs);
  letter-spacing:.12em;
  color:var(--faint);
  padding-top:.55rem;
  font-variant-numeric:tabular-nums;
}
.step h3{
  font-size:clamp(1.5rem,3vw,2.25rem);
  font-weight:700; letter-spacing:-.04em;
  line-height:1.05;
  margin-bottom:.75rem;
}
.step p{
  color:var(--muted);
  line-height:1.55;
  max-width:48ch;
}

/* ==========================================================================
   STATS
   ========================================================================== */
.section--stats{ padding-block:clamp(4rem,9vw,8rem); }
.stats{
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:clamp(2rem,4vw,3rem);
  border-top:1px solid var(--line);
  padding-top:clamp(2.5rem,5vw,4rem);
}
.stat{ display:flex; flex-wrap:wrap; align-items:baseline; gap:.15rem; }
.stat__num{
  font-size:clamp(2.75rem,6.5vw,5.5rem);
  font-weight:800;
  letter-spacing:-.055em;
  line-height:.9;
  font-variant-numeric:tabular-nums;
}
.stat__suf{
  font-size:clamp(1.1rem,2vw,1.75rem);
  font-weight:600;
  letter-spacing:-.03em;
  color:var(--faint);
}
.stat p{
  flex-basis:100%;
  margin-top:.9rem;
  font-size:var(--t-sm);
  color:var(--muted);
  max-width:22ch;
}

/* ==========================================================================
   CTA
   ========================================================================== */
/* ---------- blog ---------- */
.blog__foot{
  display:grid;
  grid-template-columns:minmax(0,1fr) auto;
  gap:clamp(1.75rem,4vw,4rem);
  align-items:center;
  padding-top:clamp(1.75rem,4vw,2.5rem);
  border-top:1px solid var(--line);
}
.blog__body{
  font-size:var(--t-lg);
  line-height:1.45;
  color:var(--muted);
  max-width:54ch;
}

.section--cta{
  padding-block:100px;        /* was inline on the section — unchanged value */
  text-align:left;
}
.section--cta .eyebrow{ margin-bottom:clamp(2rem,4vw,3rem); }
.cta__title{
  font-size:var(--t-hero);
  font-weight:800;
  line-height:.88;
  letter-spacing:-.055em;
  margin-bottom:clamp(2rem,4vw,3rem);
}
.cta__body{
  font-size:var(--t-lg);
  color:var(--muted);
  max-width:48ch;
  line-height:1.45;
  margin-bottom:clamp(2.5rem,5vw,3.5rem);
}
.cta__actions{
  display:flex; align-items:center; gap:2rem; flex-wrap:wrap;
}
/* full contrast here — these are the only way to reach us while the form is hidden */
.cta__actions .link-arrow{ color:var(--fg); }


/* ==========================================================================
   ORIGIN POINT
   The X/Y/Z axes from [01] drawing inward to 0,0,0. Keyed off body.is-light
   rather than the scroll reveal: the theme flip blanks the content for ~840ms,
   so a scroll-triggered version would play behind a curtain. Starting from the
   flip means it always runs against the settled white background.
   ========================================================================== */
.section--cta{ position:relative; overflow:hidden; }

/* the hero's blueprint grid, reprised for the finale. --hair is theme-aware,
   so the same declaration reads as dark rules on the white background. */
.cta__bg{
  position:absolute;
  inset:0;
  z-index:0;
  pointer-events:none;
  background-image:
    linear-gradient(to right, var(--hair) 1px, transparent 1px),
    linear-gradient(to bottom, var(--hair) 1px, transparent 1px);
  background-size:clamp(48px,7vw,110px) clamp(48px,7vw,110px);
  /* pooled around the cross on the left, falling away to the edges */
  mask-image:radial-gradient(100% 92% at 30% 50%, #000 10%, transparent 74%);
  -webkit-mask-image:radial-gradient(100% 92% at 30% 50%, #000 10%, transparent 74%);
  opacity:0;
  transition:opacity 1.1s var(--ease);
  transition-delay:600ms;
}
body.is-light .cta__bg{ opacity:1; }
/* The copy sits above the graphic but lets pointer events fall through to it,
   so the whole cross is grabbable. Links opt back in below. */
.section--cta .wrap{ position:relative; z-index:1; pointer-events:none; }
.section--cta .wrap a,
.section--cta .wrap button{ pointer-events:auto; }

.origin{
  --origin-delay:800ms;          /* clears the theme flip before drawing */
  position:absolute;
  /* At half-viewport scale it can no longer sit beside the copy — it becomes
     a drafting underlay behind it, so the opacity drops to keep type readable */
  /* Flush with the text: mirrors how .wrap centres itself and then pads, so
     the canvas edge tracks the copy's left edge at any viewport width. */
  left:max(var(--gutter), calc((100% - var(--wrap)) / 2 + var(--gutter)));
  top:50%;
  transform:translateY(-50%);
  /* Square, so height tracks width. The vh cap is what keeps it inside the
     band between the eyebrow and "Let's build something together" — vertical
     centring already lands it on that band's midpoint. */
  width:min(52vw, 46vh, 720px);
  z-index:0;
  opacity:.28;
  /* nothing here should ever be draggable as text or as an image */
  user-select:none;
  -webkit-user-select:none;
}
.origin svg{ display:block; width:100%; height:auto; overflow:visible; }

/* transparent interaction layer stacked exactly over the art */
.origin__ui{
  position:absolute;
  inset:0;
  /* the svg root hit-tests its whole box by default, which would swallow
     everything over the canvas — children opt back in individually below */
  pointer-events:none;
}
/* inert by default — on desktop the copy sits under the canvas and must stay
   selectable, so only the lines and dots are grabbable. Enabled on mobile. */
.origin__pad{ pointer-events:none; }
.origin__grip{ pointer-events:fill; }
.origin__hit{ pointer-events:fill; }
/* only the grips are draggable: an all-over grab area meant every drag
   wrestled the browser for the text underneath. touch-action:none lets a
   vertical drag rotate instead of scrolling — safe because they're small. */
.origin__grip,
.origin__wire,
.origin__link{
  cursor:grab;
  touch-action:none;
}
.origin.is-dragging .origin__grip,
.origin.is-dragging .origin__wire,
.origin.is-dragging .origin__link{ cursor:grabbing; }

/* invisible but hit-testable: pointer-events:stroke picks up the band even
   though nothing is painted, and it only covers the lines — not the whole
   canvas — so the copy either side stays selectable */
.origin__wire{
  fill:none;
  stroke:transparent;
  stroke-width:26;
  stroke-linecap:round;
  pointer-events:stroke;
}

/* the visible dots that mark each grip */
.origin__node{
  opacity:0;
  transition:opacity .5s var(--ease);
  transition-delay:calc(var(--origin-delay) + 900ms + var(--n) * 200ms);
}
body.is-light .origin__node{ opacity:1; }
.origin:has(.origin__grip:hover) .origin__node,
.origin:has(.origin__wire:hover) .origin__node,
.origin.is-dragging .origin__node{ opacity:1; }

/* Large screens: the copy is left-aligned and leaves the right half open, so
   move across and take that space. Below this it stays left-aligned, where
   there is no second column to move into. */
@media (min-width:1100px){
  .origin{
    left:auto;
    right:max(var(--gutter), calc((100% - var(--wrap)) / 2 + var(--gutter)));
    /* the px cap is the real limit: the section's height is content-driven
       (~770px), so on a tall viewport vh alone would overrun and clip */
    width:min(48vw, 62vh, 700px);
  }
}

/* axes: each path is 150 units, drawn from its far end toward the origin */
.origin__axis{
  stroke-dasharray:152;
  stroke-dashoffset:152;
  transition:stroke-dashoffset 1s var(--ease);
  transition-delay:calc(var(--origin-delay) + var(--a) * 120ms);
}
body.is-light .origin__axis{ stroke-dashoffset:0; }

/* letters arrive one at a time, each trailing its own axis */
.origin__glyph{
  opacity:0;
  transition:opacity .5s var(--ease);
  transition-delay:calc(var(--origin-delay) + 1100ms + var(--l) * 200ms);
}
body.is-light .origin__glyph{ opacity:1; }

.origin__dot{
  transform-box:fill-box;
  transform-origin:center;
  transform:scale(0);
  transition:transform .5s var(--ease);
  transition-delay:calc(var(--origin-delay) + 1300ms);
}
body.is-light .origin__dot{ transform:scale(1); }
/* the centre is a link to the blog — grow it on hover/focus. Overriding the
   delay matters, or the entrance delay would make hover feel broken. */
.origin__link:hover ~ * .origin__dot,
.origin:has(.origin__link:hover) .origin__dot,
.origin:has(.origin__link:focus-visible) .origin__dot{
  transform:scale(2.4);
  transition-delay:0s;
}
.origin:has(.origin__link:focus-visible) .origin__ring{
  opacity:1;
  animation:none;
  transform:scale(1.6);
}

.origin__ring{
  transform-box:fill-box;
  transform-origin:center;
  opacity:0;
}
body.is-light .origin__ring{
  animation:originPulse 3s var(--ease-io) infinite;
  animation-delay:calc(var(--origin-delay) + 1500ms);
}
@keyframes originPulse{
  0%   { opacity:.6; transform:scale(.45); }
  70%  { opacity:0;  transform:scale(1.7); }
  100% { opacity:0;  transform:scale(1.7); }
}

@media (prefers-reduced-motion: reduce){
  .origin__axis{ stroke-dashoffset:0; }
  .origin__glyph,
  .origin__node{ opacity:1; }
  .origin__dot{ transform:none; }
  .origin__ring{ display:none; }
}
.cta__grid{
  display:grid;
  /* auto-fit collapses the empty track, so hiding the form leaves the intro
     full-width instead of stranded in one half */
  grid-template-columns:repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
  gap:clamp(2.5rem,6vw,6rem);
  align-items:start;
}

/* ---------- contact form ---------- */
.form{ display:flex; flex-direction:column; gap:clamp(1.5rem,3vw,2rem); }
.form__row{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(1.25rem,2.5vw,1.75rem);
}
.field{ display:flex; flex-direction:column; gap:.6rem; }
.field label{
  font-size:var(--t-xs);
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--faint);
  display:flex; align-items:center; gap:.5rem;
}
.field__opt{ text-transform:none; letter-spacing:0; opacity:.6; }

.field input,
.field select,
.field textarea{
  width:100%;
  background:transparent;
  border:0;
  border-bottom:1px solid var(--line);
  border-radius:0;
  padding:.65rem 0;
  color:var(--fg);
  font:inherit;
  font-size:var(--t-base);
  letter-spacing:-.01em;
  transition:border-color .4s var(--ease);
}
.field textarea{ resize:vertical; min-height:6.5rem; }
.field select{
  appearance:none; -webkit-appearance:none;
  cursor:pointer;
  padding-right:1.75rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23F4F4F5' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right .35rem center;
}
/* the dropdown list itself is painted by the OS — keep it readable */
.field select option{ background:#0B0B0C; color:#F4F4F5; }

.field input:focus,
.field select:focus,
.field textarea:focus{
  outline:none;
  border-bottom-color:var(--fg);
}
.field input::placeholder,
.field textarea::placeholder{ color:var(--faint); }

.field.is-error input,
.field.is-error select,
.field.is-error textarea{ border-bottom-color:var(--fg); }
.field__err{
  font-size:var(--t-xs);
  color:var(--fg);
  min-height:1em;
  opacity:0;
  transform:translateY(-4px);
  transition:opacity .35s var(--ease), transform .35s var(--ease);
}
.field.is-error .field__err{ opacity:.75; transform:none; }

/* honeypot — off-screen rather than display:none, which some bots skip */
.hp{
  position:absolute;
  width:1px; height:1px;
  overflow:hidden; clip-path:inset(50%);
  white-space:nowrap;
}

.form__foot{
  display:flex; align-items:center; gap:1.5rem;
  flex-wrap:wrap;
  margin-top:.5rem;
}
.form__status{
  font-size:var(--t-sm);
  color:var(--muted);
  opacity:0;
  transition:opacity .4s var(--ease);
}
.form__status.is-shown{ opacity:1; }
.form.is-sent{ opacity:.55; pointer-events:none; }

/* ==========================================================================
   FOOTER
   ========================================================================== */
.footer{
  border-top:1px solid var(--line);
  padding-block:clamp(2.5rem,5vw,4rem);
}
.footer__grid{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:2rem; flex-wrap:wrap;
}
.footer__brand{ display:flex; align-items:center; gap:.85rem; }
.footer__brand p{
  font-size:var(--t-sm); color:var(--muted);
  white-space:nowrap;          /* keep the tagline on one line */
}
.footer__meta{
  display:flex; flex-direction:column; gap:.35rem;
  text-align:right;
  font-size:var(--t-xs);
  color:var(--faint);
  letter-spacing:.02em;
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width:1080px){
  .zeros{ grid-template-columns:1fr 1fr; row-gap:clamp(2.5rem,6vw,4rem); }
  .stats{ grid-template-columns:1fr 1fr; row-gap:clamp(2.5rem,6vw,3.5rem); }
}

@media (max-width:860px){
  .nav__links{ display:none; }
  .nav > .btn{ display:none; }
  .nav__toggle{ display:block; margin-left:auto; }

  .hero__foot{ grid-template-columns:1fr; align-items:start; }
  .hero__cta{ justify-content:flex-start; }
  .hero__scroll{ display:none; }

  .approach{ grid-template-columns:1fr; }
  .approach__sticky{ position:static; }

  .lead-card{ grid-template-columns:1fr; }
  .cards{ grid-template-columns:1fr; }
  .manifesto-grid{ grid-template-columns:1fr; align-items:start; }
  .figure--manifesto{ order:-1; }   /* tower leads on small screens */
  .blog__foot{ grid-template-columns:1fr; align-items:start; }
  /* no room to sit behind the copy — drop it below, right-aligned.
     relative, NOT static: .origin__ui is absolutely positioned, so a static
     parent sends it to .section--cta instead and every hit target lands
     hundreds of pixels away from the artwork. */
  .origin{
    position:relative;
    transform:none;
    width:min(88%,340px);
    opacity:.4;
    margin:clamp(2.5rem,8vw,4rem) var(--gutter) 0 auto;
  }
  /* finger-sized: grab anywhere on the canvas here */
  .origin__pad{
    pointer-events:fill;
    cursor:grab;
    touch-action:none;
  }
  /* the axis is the last thing before the footer, so a deep bottom pad just
     pushes it off the top of the screen at the end of the scroll */
  .section--cta{ padding-block:72px 32px; }
  .cta__grid{ grid-template-columns:1fr; }

  .acc__inner{ grid-template-columns:1fr; }
  .acc__inner > *:not(:last-child){ padding-bottom:1.25rem; }
}

@media (max-width:620px){
  .zeros{ grid-template-columns:1fr; }
  .cards{ grid-template-columns:1fr; }
  .card{ min-height:0; }
  .card h3{ margin-top:clamp(1.5rem,8vw,2.5rem); }
  .stats{ grid-template-columns:1fr; }
  .footer__grid{ flex-direction:column; align-items:flex-start; }
  .footer__meta{ text-align:left; }
  .acc__head{ grid-template-columns:1fr auto; }
  .acc__idx{ display:none; }
  .form__row{ grid-template-columns:1fr; }
}

/* ==========================================================================
   REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  [data-reveal]{ opacity:1; transform:none; }
  .line__in{ transform:none !important; }
  .hero__eyebrow,.hero__foot{ opacity:1; transform:none; }
  .hero__grid{ opacity:1; }
  .grain{ display:none; }
}
